1 // Copyright 2017 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/fpdfapi/page/cpdf_psengine.h" 8 9 #include <algorithm> 10 #include <utility> 11 12 #include "core/fpdfapi/parser/cpdf_simple_parser.h" 13 #include "core/fxcrt/fx_safe_types.h" 14 #include "core/fxcrt/fx_string.h" 15 #include "third_party/base/logging.h" 16 #include "third_party/base/ptr_util.h" 17 18 namespace { 19 20 struct PDF_PSOpName { 21 const char* name; 22 PDF_PSOP op; 23 }; 24 25 constexpr PDF_PSOpName kPsOpNames[] = { 26 {"abs", PSOP_ABS}, 27 {"add", PSOP_ADD}, 28 {"and", PSOP_AND}, 29 {"atan", PSOP_ATAN}, 30 {"bitshift", PSOP_BITSHIFT}, 31 {"ceiling", PSOP_CEILING}, 32 {"copy", PSOP_COPY}, 33 {"cos", PSOP_COS}, 34 {"cvi", PSOP_CVI}, 35 {"cvr", PSOP_CVR}, 36 {"div", PSOP_DIV}, 37 {"dup", PSOP_DUP}, 38 {"eq", PSOP_EQ}, 39 {"exch", PSOP_EXCH}, 40 {"exp", PSOP_EXP}, 41 {"false", PSOP_FALSE}, 42 {"floor", PSOP_FLOOR}, 43 {"ge", PSOP_GE}, 44 {"gt", PSOP_GT}, 45 {"idiv", PSOP_IDIV}, 46 {"if", PSOP_IF}, 47 {"ifelse", PSOP_IFELSE}, 48 {"index", PSOP_INDEX}, 49 {"le", PSOP_LE}, 50 {"ln", PSOP_LN}, 51 {"log", PSOP_LOG}, 52 {"lt", PSOP_LT}, 53 {"mod", PSOP_MOD}, 54 {"mul", PSOP_MUL}, 55 {"ne", PSOP_NE}, 56 {"neg", PSOP_NEG}, 57 {"not", PSOP_NOT}, 58 {"or", PSOP_OR}, 59 {"pop", PSOP_POP}, 60 {"roll", PSOP_ROLL}, 61 {"round", PSOP_ROUND}, 62 {"sin", PSOP_SIN}, 63 {"sqrt", PSOP_SQRT}, 64 {"sub", PSOP_SUB}, 65 {"true", PSOP_TRUE}, 66 {"truncate", PSOP_TRUNCATE}, 67 {"xor", PSOP_XOR}, 68 }; 69 70 } // namespace 71 72 CPDF_PSOP::CPDF_PSOP() 73 : m_op(PSOP_PROC), m_value(0), m_proc(pdfium::MakeUnique<CPDF_PSProc>()) {} 74 75 CPDF_PSOP::CPDF_PSOP(PDF_PSOP op) : m_op(op), m_value(0) { 76 ASSERT(m_op != PSOP_CONST); 77 ASSERT(m_op != PSOP_PROC); 78 } 79 80 CPDF_PSOP::CPDF_PSOP(float value) : m_op(PSOP_CONST), m_value(value) {} 81 82 CPDF_PSOP::~CPDF_PSOP() {} 83 84 float CPDF_PSOP::GetFloatValue() const { 85 if (m_op == PSOP_CONST) 86 return m_value; 87 88 NOTREACHED(); 89 return 0; 90 } 91 92 CPDF_PSProc* CPDF_PSOP::GetProc() const { 93 if (m_op == PSOP_PROC) 94 return m_proc.get(); 95 NOTREACHED(); 96 return nullptr; 97 } 98 99 bool CPDF_PSEngine::Execute() { 100 return m_MainProc.Execute(this); 101 } 102 103 CPDF_PSProc::CPDF_PSProc() {} 104 CPDF_PSProc::~CPDF_PSProc() {} 105 106 bool CPDF_PSProc::Parse(CPDF_SimpleParser* parser, int depth) { 107 if (depth > kMaxDepth) 108 return false; 109 110 while (1) { 111 ByteStringView word = parser->GetWord(); 112 if (word.IsEmpty()) 113 return false; 114 115 if (word == "}") 116 return true; 117 118 if (word == "{") { 119 m_Operators.push_back(pdfium::MakeUnique<CPDF_PSOP>()); 120 if (!m_Operators.back()->GetProc()->Parse(parser, depth + 1)) 121 return false; 122 continue; 123 } 124 125 AddOperator(word); 126 } 127 } 128 129 bool CPDF_PSProc::Execute(CPDF_PSEngine* pEngine) { 130 for (size_t i = 0; i < m_Operators.size(); ++i) { 131 const PDF_PSOP op = m_Operators[i]->GetOp(); 132 if (op == PSOP_PROC) 133 continue; 134 135 if (op == PSOP_CONST) { 136 pEngine->Push(m_Operators[i]->GetFloatValue()); 137 continue; 138 } 139 140 if (op == PSOP_IF) { 141 if (i == 0 || m_Operators[i - 1]->GetOp() != PSOP_PROC) 142 return false; 143 144 if (pEngine->PopInt()) 145 m_Operators[i - 1]->GetProc()->Execute(pEngine); 146 } else if (op == PSOP_IFELSE) { 147 if (i < 2 || m_Operators[i - 1]->GetOp() != PSOP_PROC || 148 m_Operators[i - 2]->GetOp() != PSOP_PROC) { 149 return false; 150 } 151 size_t offset = pEngine->PopInt() ? 2 : 1; 152 m_Operators[i - offset]->GetProc()->Execute(pEngine); 153 } else { 154 pEngine->DoOperator(op); 155 } 156 } 157 return true; 158 } 159 160 void CPDF_PSProc::AddOperatorForTesting(const ByteStringView& word) { 161 AddOperator(word); 162 } 163 164 void CPDF_PSProc::AddOperator(const ByteStringView& word) { 165 const auto* pFound = std::lower_bound( 166 std::begin(kPsOpNames), std::end(kPsOpNames), word, 167 [](const PDF_PSOpName& name, const ByteStringView& word) { 168 return name.name < word; 169 }); 170 if (pFound != std::end(kPsOpNames) && pFound->name == word) 171 m_Operators.push_back(pdfium::MakeUnique<CPDF_PSOP>(pFound->op)); 172 else 173 m_Operators.push_back(pdfium::MakeUnique<CPDF_PSOP>(FX_atof(word))); 174 } 175 176 CPDF_PSEngine::CPDF_PSEngine() : m_StackCount(0) {} 177 178 CPDF_PSEngine::~CPDF_PSEngine() {} 179 180 void CPDF_PSEngine::Push(float v) { 181 if (m_StackCount < kPSEngineStackSize) 182 m_Stack[m_StackCount++] = v; 183 } 184 185 float CPDF_PSEngine::Pop() { 186 return m_StackCount > 0 ? m_Stack[--m_StackCount] : 0; 187 } 188 189 int CPDF_PSEngine::PopInt() { 190 return static_cast<int>(Pop()); 191 } 192 193 bool CPDF_PSEngine::Parse(const char* str, int size) { 194 CPDF_SimpleParser parser(reinterpret_cast<const uint8_t*>(str), size); 195 ByteStringView word = parser.GetWord(); 196 return word == "{" ? m_MainProc.Parse(&parser, 0) : false; 197 } 198 199 bool CPDF_PSEngine::DoOperator(PDF_PSOP op) { 200 int i1; 201 int i2; 202 float d1; 203 float d2; 204 FX_SAFE_INT32 result; 205 switch (op) { 206 case PSOP_ADD: 207 d1 = Pop(); 208 d2 = Pop(); 209 Push(d1 + d2); 210 break; 211 case PSOP_SUB: 212 d2 = Pop(); 213 d1 = Pop(); 214 Push(d1 - d2); 215 break; 216 case PSOP_MUL: 217 d1 = Pop(); 218 d2 = Pop(); 219 Push(d1 * d2); 220 break; 221 case PSOP_DIV: 222 d2 = Pop(); 223 d1 = Pop(); 224 Push(d1 / d2); 225 break; 226 case PSOP_IDIV: 227 i2 = PopInt(); 228 i1 = PopInt(); 229 if (i2) { 230 result = i1; 231 result /= i2; 232 Push(result.ValueOrDefault(0)); 233 } else { 234 Push(0); 235 } 236 break; 237 case PSOP_MOD: 238 i2 = PopInt(); 239 i1 = PopInt(); 240 if (i2) { 241 result = i1; 242 result %= i2; 243 Push(result.ValueOrDefault(0)); 244 } else { 245 Push(0); 246 } 247 break; 248 case PSOP_NEG: 249 d1 = Pop(); 250 Push(-d1); 251 break; 252 case PSOP_ABS: 253 d1 = Pop(); 254 Push(fabs(d1)); 255 break; 256 case PSOP_CEILING: 257 d1 = Pop(); 258 Push(ceil(d1)); 259 break; 260 case PSOP_FLOOR: 261 d1 = Pop(); 262 Push(floor(d1)); 263 break; 264 case PSOP_ROUND: 265 d1 = Pop(); 266 Push(FXSYS_round(d1)); 267 break; 268 case PSOP_TRUNCATE: 269 i1 = PopInt(); 270 Push(i1); 271 break; 272 case PSOP_SQRT: 273 d1 = Pop(); 274 Push(sqrt(d1)); 275 break; 276 case PSOP_SIN: 277 d1 = Pop(); 278 Push(sin(d1 * FX_PI / 180.0f)); 279 break; 280 case PSOP_COS: 281 d1 = Pop(); 282 Push(cos(d1 * FX_PI / 180.0f)); 283 break; 284 case PSOP_ATAN: 285 d2 = Pop(); 286 d1 = Pop(); 287 d1 = atan2(d1, d2) * 180.0 / FX_PI; 288 if (d1 < 0) { 289 d1 += 360; 290 } 291 Push(d1); 292 break; 293 case PSOP_EXP: 294 d2 = Pop(); 295 d1 = Pop(); 296 Push(FXSYS_pow(d1, d2)); 297 break; 298 case PSOP_LN: 299 d1 = Pop(); 300 Push(log(d1)); 301 break; 302 case PSOP_LOG: 303 d1 = Pop(); 304 Push(log10(d1)); 305 break; 306 case PSOP_CVI: 307 i1 = PopInt(); 308 Push(i1); 309 break; 310 case PSOP_CVR: 311 break; 312 case PSOP_EQ: 313 d2 = Pop(); 314 d1 = Pop(); 315 Push(d1 == d2); 316 break; 317 case PSOP_NE: 318 d2 = Pop(); 319 d1 = Pop(); 320 Push(d1 != d2); 321 break; 322 case PSOP_GT: 323 d2 = Pop(); 324 d1 = Pop(); 325 Push(d1 > d2); 326 break; 327 case PSOP_GE: 328 d2 = Pop(); 329 d1 = Pop(); 330 Push(d1 >= d2); 331 break; 332 case PSOP_LT: 333 d2 = Pop(); 334 d1 = Pop(); 335 Push(d1 < d2); 336 break; 337 case PSOP_LE: 338 d2 = Pop(); 339 d1 = Pop(); 340 Push(d1 <= d2); 341 break; 342 case PSOP_AND: 343 i1 = PopInt(); 344 i2 = PopInt(); 345 Push(i1 & i2); 346 break; 347 case PSOP_OR: 348 i1 = PopInt(); 349 i2 = PopInt(); 350 Push(i1 | i2); 351 break; 352 case PSOP_XOR: 353 i1 = PopInt(); 354 i2 = PopInt(); 355 Push(i1 ^ i2); 356 break; 357 case PSOP_NOT: 358 i1 = PopInt(); 359 Push(!i1); 360 break; 361 case PSOP_BITSHIFT: { 362 int shift = PopInt(); 363 result = PopInt(); 364 if (shift > 0) { 365 result <<= shift; 366 } else { 367 // Avoids unsafe negation of INT_MIN. 368 FX_SAFE_INT32 safe_shift = shift; 369 result >>= (-safe_shift).ValueOrDefault(0); 370 } 371 Push(result.ValueOrDefault(0)); 372 break; 373 } 374 case PSOP_TRUE: 375 Push(1); 376 break; 377 case PSOP_FALSE: 378 Push(0); 379 break; 380 case PSOP_POP: 381 Pop(); 382 break; 383 case PSOP_EXCH: 384 d2 = Pop(); 385 d1 = Pop(); 386 Push(d2); 387 Push(d1); 388 break; 389 case PSOP_DUP: 390 d1 = Pop(); 391 Push(d1); 392 Push(d1); 393 break; 394 case PSOP_COPY: { 395 int n = PopInt(); 396 if (n < 0 || m_StackCount + n > kPSEngineStackSize || 397 n > static_cast<int>(m_StackCount)) 398 break; 399 for (int i = 0; i < n; i++) 400 m_Stack[m_StackCount + i] = m_Stack[m_StackCount + i - n]; 401 m_StackCount += n; 402 break; 403 } 404 case PSOP_INDEX: { 405 int n = PopInt(); 406 if (n < 0 || n >= static_cast<int>(m_StackCount)) 407 break; 408 Push(m_Stack[m_StackCount - n - 1]); 409 break; 410 } 411 case PSOP_ROLL: { 412 int j = PopInt(); 413 int n = PopInt(); 414 if (j == 0 || n == 0 || m_StackCount == 0) 415 break; 416 if (n < 0 || n > static_cast<int>(m_StackCount)) 417 break; 418 419 j %= n; 420 if (j > 0) 421 j -= n; 422 auto* begin_it = std::begin(m_Stack) + m_StackCount - n; 423 auto* middle_it = begin_it - j; 424 auto* end_it = std::begin(m_Stack) + m_StackCount; 425 std::rotate(begin_it, middle_it, end_it); 426 break; 427 } 428 default: 429 break; 430 } 431 return true; 432 } 433