• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CPDF_PSOP()72 CPDF_PSOP::CPDF_PSOP()
73     : m_op(PSOP_PROC), m_value(0), m_proc(pdfium::MakeUnique<CPDF_PSProc>()) {}
74 
CPDF_PSOP(PDF_PSOP op)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 
CPDF_PSOP(float value)80 CPDF_PSOP::CPDF_PSOP(float value) : m_op(PSOP_CONST), m_value(value) {}
81 
~CPDF_PSOP()82 CPDF_PSOP::~CPDF_PSOP() {}
83 
GetFloatValue() const84 float CPDF_PSOP::GetFloatValue() const {
85   if (m_op == PSOP_CONST)
86     return m_value;
87 
88   NOTREACHED();
89   return 0;
90 }
91 
GetProc() const92 CPDF_PSProc* CPDF_PSOP::GetProc() const {
93   if (m_op == PSOP_PROC)
94     return m_proc.get();
95   NOTREACHED();
96   return nullptr;
97 }
98 
Execute()99 bool CPDF_PSEngine::Execute() {
100   return m_MainProc.Execute(this);
101 }
102 
CPDF_PSProc()103 CPDF_PSProc::CPDF_PSProc() {}
~CPDF_PSProc()104 CPDF_PSProc::~CPDF_PSProc() {}
105 
Parse(CPDF_SimpleParser * parser,int depth)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 
Execute(CPDF_PSEngine * pEngine)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 
AddOperatorForTesting(const ByteStringView & word)160 void CPDF_PSProc::AddOperatorForTesting(const ByteStringView& word) {
161   AddOperator(word);
162 }
163 
AddOperator(const ByteStringView & word)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 
CPDF_PSEngine()176 CPDF_PSEngine::CPDF_PSEngine() : m_StackCount(0) {}
177 
~CPDF_PSEngine()178 CPDF_PSEngine::~CPDF_PSEngine() {}
179 
Push(float v)180 void CPDF_PSEngine::Push(float v) {
181   if (m_StackCount < kPSEngineStackSize)
182     m_Stack[m_StackCount++] = v;
183 }
184 
Pop()185 float CPDF_PSEngine::Pop() {
186   return m_StackCount > 0 ? m_Stack[--m_StackCount] : 0;
187 }
188 
PopInt()189 int CPDF_PSEngine::PopInt() {
190   return static_cast<int>(Pop());
191 }
192 
Parse(const char * str,int size)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 
DoOperator(PDF_PSOP op)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