Home | History | Annotate | Download | only in page
      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