1 // Copyright 2014 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/fpdf_page/pageint.h"
8 
9 #include <limits.h>
10 
11 #include <algorithm>
12 #include <memory>
13 #include <utility>
14 #include <vector>
15 
16 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
17 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
18 #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h"
19 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
20 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
21 #include "core/fxcrt/include/fx_safe_types.h"
22 #include "third_party/base/numerics/safe_conversions_impl.h"
23 
24 namespace {
25 
26 enum PDF_PSOP {
27   PSOP_ADD,
28   PSOP_SUB,
29   PSOP_MUL,
30   PSOP_DIV,
31   PSOP_IDIV,
32   PSOP_MOD,
33   PSOP_NEG,
34   PSOP_ABS,
35   PSOP_CEILING,
36   PSOP_FLOOR,
37   PSOP_ROUND,
38   PSOP_TRUNCATE,
39   PSOP_SQRT,
40   PSOP_SIN,
41   PSOP_COS,
42   PSOP_ATAN,
43   PSOP_EXP,
44   PSOP_LN,
45   PSOP_LOG,
46   PSOP_CVI,
47   PSOP_CVR,
48   PSOP_EQ,
49   PSOP_NE,
50   PSOP_GT,
51   PSOP_GE,
52   PSOP_LT,
53   PSOP_LE,
54   PSOP_AND,
55   PSOP_OR,
56   PSOP_XOR,
57   PSOP_NOT,
58   PSOP_BITSHIFT,
59   PSOP_TRUE,
60   PSOP_FALSE,
61   PSOP_IF,
62   PSOP_IFELSE,
63   PSOP_POP,
64   PSOP_EXCH,
65   PSOP_DUP,
66   PSOP_COPY,
67   PSOP_INDEX,
68   PSOP_ROLL,
69   PSOP_PROC,
70   PSOP_CONST
71 };
72 
73 class CPDF_PSEngine;
74 class CPDF_PSProc;
75 
76 class CPDF_PSOP {
77  public:
CPDF_PSOP(PDF_PSOP op)78   explicit CPDF_PSOP(PDF_PSOP op) : m_op(op), m_value(0) {
79     ASSERT(m_op != PSOP_CONST);
80     ASSERT(m_op != PSOP_PROC);
81   }
CPDF_PSOP(FX_FLOAT value)82   explicit CPDF_PSOP(FX_FLOAT value) : m_op(PSOP_CONST), m_value(value) {}
CPDF_PSOP(std::unique_ptr<CPDF_PSProc> proc)83   explicit CPDF_PSOP(std::unique_ptr<CPDF_PSProc> proc)
84       : m_op(PSOP_PROC), m_value(0), m_proc(std::move(proc)) {}
85 
GetFloatValue() const86   FX_FLOAT GetFloatValue() const {
87     if (m_op == PSOP_CONST)
88       return m_value;
89 
90     ASSERT(false);
91     return 0;
92   }
GetProc() const93   CPDF_PSProc* GetProc() const {
94     if (m_op == PSOP_PROC)
95       return m_proc.get();
96     ASSERT(false);
97     return nullptr;
98   }
99 
GetOp() const100   PDF_PSOP GetOp() const { return m_op; }
101 
102  private:
103   const PDF_PSOP m_op;
104   const FX_FLOAT m_value;
105   std::unique_ptr<CPDF_PSProc> m_proc;
106 };
107 
108 class CPDF_PSProc {
109  public:
CPDF_PSProc()110   CPDF_PSProc() {}
~CPDF_PSProc()111   ~CPDF_PSProc() {}
112 
113   FX_BOOL Parse(CPDF_SimpleParser* parser);
114   FX_BOOL Execute(CPDF_PSEngine* pEngine);
115 
116  private:
117   std::vector<std::unique_ptr<CPDF_PSOP>> m_Operators;
118 };
119 
120 const uint32_t PSENGINE_STACKSIZE = 100;
121 
122 class CPDF_PSEngine {
123  public:
124   CPDF_PSEngine();
125   ~CPDF_PSEngine();
126 
127   FX_BOOL Parse(const FX_CHAR* str, int size);
Execute()128   FX_BOOL Execute() { return m_MainProc.Execute(this); }
129   FX_BOOL DoOperator(PDF_PSOP op);
Reset()130   void Reset() { m_StackCount = 0; }
131   void Push(FX_FLOAT value);
Push(int value)132   void Push(int value) { Push((FX_FLOAT)value); }
133   FX_FLOAT Pop();
GetStackSize() const134   uint32_t GetStackSize() const { return m_StackCount; }
135 
136  private:
137   FX_FLOAT m_Stack[PSENGINE_STACKSIZE];
138   uint32_t m_StackCount;
139   CPDF_PSProc m_MainProc;
140 };
141 
Execute(CPDF_PSEngine * pEngine)142 FX_BOOL CPDF_PSProc::Execute(CPDF_PSEngine* pEngine) {
143   for (size_t i = 0; i < m_Operators.size(); ++i) {
144     const PDF_PSOP op = m_Operators[i]->GetOp();
145     if (op == PSOP_PROC)
146       continue;
147 
148     if (op == PSOP_CONST) {
149       pEngine->Push(m_Operators[i]->GetFloatValue());
150       continue;
151     }
152 
153     if (op == PSOP_IF) {
154       if (i == 0 || m_Operators[i - 1]->GetOp() != PSOP_PROC)
155         return FALSE;
156 
157       if (static_cast<int>(pEngine->Pop()))
158         m_Operators[i - 1]->GetProc()->Execute(pEngine);
159     } else if (op == PSOP_IFELSE) {
160       if (i < 2 || m_Operators[i - 1]->GetOp() != PSOP_PROC ||
161           m_Operators[i - 2]->GetOp() != PSOP_PROC) {
162         return FALSE;
163       }
164       size_t offset = static_cast<int>(pEngine->Pop()) ? 2 : 1;
165       m_Operators[i - offset]->GetProc()->Execute(pEngine);
166     } else {
167       pEngine->DoOperator(op);
168     }
169   }
170   return TRUE;
171 }
172 
CPDF_PSEngine()173 CPDF_PSEngine::CPDF_PSEngine() {
174   m_StackCount = 0;
175 }
~CPDF_PSEngine()176 CPDF_PSEngine::~CPDF_PSEngine() {}
Push(FX_FLOAT v)177 void CPDF_PSEngine::Push(FX_FLOAT v) {
178   if (m_StackCount == PSENGINE_STACKSIZE) {
179     return;
180   }
181   m_Stack[m_StackCount++] = v;
182 }
Pop()183 FX_FLOAT CPDF_PSEngine::Pop() {
184   if (m_StackCount == 0) {
185     return 0;
186   }
187   return m_Stack[--m_StackCount];
188 }
189 const struct PDF_PSOpName {
190   const FX_CHAR* name;
191   PDF_PSOP op;
192 } PDF_PSOpNames[] = {{"add", PSOP_ADD},         {"sub", PSOP_SUB},
193                      {"mul", PSOP_MUL},         {"div", PSOP_DIV},
194                      {"idiv", PSOP_IDIV},       {"mod", PSOP_MOD},
195                      {"neg", PSOP_NEG},         {"abs", PSOP_ABS},
196                      {"ceiling", PSOP_CEILING}, {"floor", PSOP_FLOOR},
197                      {"round", PSOP_ROUND},     {"truncate", PSOP_TRUNCATE},
198                      {"sqrt", PSOP_SQRT},       {"sin", PSOP_SIN},
199                      {"cos", PSOP_COS},         {"atan", PSOP_ATAN},
200                      {"exp", PSOP_EXP},         {"ln", PSOP_LN},
201                      {"log", PSOP_LOG},         {"cvi", PSOP_CVI},
202                      {"cvr", PSOP_CVR},         {"eq", PSOP_EQ},
203                      {"ne", PSOP_NE},           {"gt", PSOP_GT},
204                      {"ge", PSOP_GE},           {"lt", PSOP_LT},
205                      {"le", PSOP_LE},           {"and", PSOP_AND},
206                      {"or", PSOP_OR},           {"xor", PSOP_XOR},
207                      {"not", PSOP_NOT},         {"bitshift", PSOP_BITSHIFT},
208                      {"true", PSOP_TRUE},       {"false", PSOP_FALSE},
209                      {"if", PSOP_IF},           {"ifelse", PSOP_IFELSE},
210                      {"pop", PSOP_POP},         {"exch", PSOP_EXCH},
211                      {"dup", PSOP_DUP},         {"copy", PSOP_COPY},
212                      {"index", PSOP_INDEX},     {"roll", PSOP_ROLL}};
213 
Parse(const FX_CHAR * str,int size)214 FX_BOOL CPDF_PSEngine::Parse(const FX_CHAR* str, int size) {
215   CPDF_SimpleParser parser((uint8_t*)str, size);
216   CFX_ByteStringC word = parser.GetWord();
217   if (word != "{") {
218     return FALSE;
219   }
220   return m_MainProc.Parse(&parser);
221 }
Parse(CPDF_SimpleParser * parser)222 FX_BOOL CPDF_PSProc::Parse(CPDF_SimpleParser* parser) {
223   while (1) {
224     CFX_ByteStringC word = parser->GetWord();
225     if (word.IsEmpty()) {
226       return FALSE;
227     }
228     if (word == "}") {
229       return TRUE;
230     }
231     if (word == "{") {
232       std::unique_ptr<CPDF_PSProc> proc(new CPDF_PSProc);
233       std::unique_ptr<CPDF_PSOP> op(new CPDF_PSOP(std::move(proc)));
234       m_Operators.push_back(std::move(op));
235       if (!m_Operators.back()->GetProc()->Parse(parser)) {
236         return FALSE;
237       }
238     } else {
239       bool found = false;
240       for (const PDF_PSOpName& op_name : PDF_PSOpNames) {
241         if (word == CFX_ByteStringC(op_name.name)) {
242           std::unique_ptr<CPDF_PSOP> op(new CPDF_PSOP(op_name.op));
243           m_Operators.push_back(std::move(op));
244           found = true;
245           break;
246         }
247       }
248       if (!found) {
249         std::unique_ptr<CPDF_PSOP> op(new CPDF_PSOP(FX_atof(word)));
250         m_Operators.push_back(std::move(op));
251       }
252     }
253   }
254 }
255 
DoOperator(PDF_PSOP op)256 FX_BOOL CPDF_PSEngine::DoOperator(PDF_PSOP op) {
257   int i1, i2;
258   FX_FLOAT d1, d2;
259   switch (op) {
260     case PSOP_ADD:
261       d1 = Pop();
262       d2 = Pop();
263       Push(d1 + d2);
264       break;
265     case PSOP_SUB:
266       d2 = Pop();
267       d1 = Pop();
268       Push(d1 - d2);
269       break;
270     case PSOP_MUL:
271       d1 = Pop();
272       d2 = Pop();
273       Push(d1 * d2);
274       break;
275     case PSOP_DIV:
276       d2 = Pop();
277       d1 = Pop();
278       Push(d1 / d2);
279       break;
280     case PSOP_IDIV:
281       i2 = (int)Pop();
282       i1 = (int)Pop();
283       Push(i1 / i2);
284       break;
285     case PSOP_MOD:
286       i2 = (int)Pop();
287       i1 = (int)Pop();
288       Push(i1 % i2);
289       break;
290     case PSOP_NEG:
291       d1 = Pop();
292       Push(-d1);
293       break;
294     case PSOP_ABS:
295       d1 = Pop();
296       Push((FX_FLOAT)FXSYS_fabs(d1));
297       break;
298     case PSOP_CEILING:
299       d1 = Pop();
300       Push((FX_FLOAT)FXSYS_ceil(d1));
301       break;
302     case PSOP_FLOOR:
303       d1 = Pop();
304       Push((FX_FLOAT)FXSYS_floor(d1));
305       break;
306     case PSOP_ROUND:
307       d1 = Pop();
308       Push(FXSYS_round(d1));
309       break;
310     case PSOP_TRUNCATE:
311       i1 = (int)Pop();
312       Push(i1);
313       break;
314     case PSOP_SQRT:
315       d1 = Pop();
316       Push((FX_FLOAT)FXSYS_sqrt(d1));
317       break;
318     case PSOP_SIN:
319       d1 = Pop();
320       Push((FX_FLOAT)FXSYS_sin(d1 * FX_PI / 180.0f));
321       break;
322     case PSOP_COS:
323       d1 = Pop();
324       Push((FX_FLOAT)FXSYS_cos(d1 * FX_PI / 180.0f));
325       break;
326     case PSOP_ATAN:
327       d2 = Pop();
328       d1 = Pop();
329       d1 = (FX_FLOAT)(FXSYS_atan2(d1, d2) * 180.0 / FX_PI);
330       if (d1 < 0) {
331         d1 += 360;
332       }
333       Push(d1);
334       break;
335     case PSOP_EXP:
336       d2 = Pop();
337       d1 = Pop();
338       Push((FX_FLOAT)FXSYS_pow(d1, d2));
339       break;
340     case PSOP_LN:
341       d1 = Pop();
342       Push((FX_FLOAT)FXSYS_log(d1));
343       break;
344     case PSOP_LOG:
345       d1 = Pop();
346       Push((FX_FLOAT)FXSYS_log10(d1));
347       break;
348     case PSOP_CVI:
349       i1 = (int)Pop();
350       Push(i1);
351       break;
352     case PSOP_CVR:
353       break;
354     case PSOP_EQ:
355       d2 = Pop();
356       d1 = Pop();
357       Push((int)(d1 == d2));
358       break;
359     case PSOP_NE:
360       d2 = Pop();
361       d1 = Pop();
362       Push((int)(d1 != d2));
363       break;
364     case PSOP_GT:
365       d2 = Pop();
366       d1 = Pop();
367       Push((int)(d1 > d2));
368       break;
369     case PSOP_GE:
370       d2 = Pop();
371       d1 = Pop();
372       Push((int)(d1 >= d2));
373       break;
374     case PSOP_LT:
375       d2 = Pop();
376       d1 = Pop();
377       Push((int)(d1 < d2));
378       break;
379     case PSOP_LE:
380       d2 = Pop();
381       d1 = Pop();
382       Push((int)(d1 <= d2));
383       break;
384     case PSOP_AND:
385       i1 = (int)Pop();
386       i2 = (int)Pop();
387       Push(i1 & i2);
388       break;
389     case PSOP_OR:
390       i1 = (int)Pop();
391       i2 = (int)Pop();
392       Push(i1 | i2);
393       break;
394     case PSOP_XOR:
395       i1 = (int)Pop();
396       i2 = (int)Pop();
397       Push(i1 ^ i2);
398       break;
399     case PSOP_NOT:
400       i1 = (int)Pop();
401       Push((int)!i1);
402       break;
403     case PSOP_BITSHIFT: {
404       int shift = (int)Pop();
405       int i = (int)Pop();
406       if (shift > 0) {
407         Push(i << shift);
408       } else {
409         Push(i >> -shift);
410       }
411       break;
412     }
413     case PSOP_TRUE:
414       Push(1);
415       break;
416     case PSOP_FALSE:
417       Push(0);
418       break;
419     case PSOP_POP:
420       Pop();
421       break;
422     case PSOP_EXCH:
423       d2 = Pop();
424       d1 = Pop();
425       Push(d2);
426       Push(d1);
427       break;
428     case PSOP_DUP:
429       d1 = Pop();
430       Push(d1);
431       Push(d1);
432       break;
433     case PSOP_COPY: {
434       int n = static_cast<int>(Pop());
435       if (n < 0 || m_StackCount + n > PSENGINE_STACKSIZE ||
436           n > static_cast<int>(m_StackCount))
437         break;
438       for (int i = 0; i < n; i++)
439         m_Stack[m_StackCount + i] = m_Stack[m_StackCount + i - n];
440       m_StackCount += n;
441       break;
442     }
443     case PSOP_INDEX: {
444       int n = static_cast<int>(Pop());
445       if (n < 0 || n >= static_cast<int>(m_StackCount))
446         break;
447       Push(m_Stack[m_StackCount - n - 1]);
448       break;
449     }
450     case PSOP_ROLL: {
451       int j = static_cast<int>(Pop());
452       int n = static_cast<int>(Pop());
453       if (m_StackCount == 0)
454         break;
455       if (n < 0 || n > static_cast<int>(m_StackCount))
456         break;
457       if (j < 0) {
458         for (int i = 0; i < -j; i++) {
459           FX_FLOAT first = m_Stack[m_StackCount - n];
460           for (int ii = 0; ii < n - 1; ii++)
461             m_Stack[m_StackCount - n + ii] = m_Stack[m_StackCount - n + ii + 1];
462           m_Stack[m_StackCount - 1] = first;
463         }
464       } else {
465         for (int i = 0; i < j; i++) {
466           FX_FLOAT last = m_Stack[m_StackCount - 1];
467           int ii;
468           for (ii = 0; ii < n - 1; ii++)
469             m_Stack[m_StackCount - ii - 1] = m_Stack[m_StackCount - ii - 2];
470           m_Stack[m_StackCount - ii - 1] = last;
471         }
472       }
473       break;
474     }
475     default:
476       break;
477   }
478   return TRUE;
479 }
480 
481 // See PDF Reference 1.7, page 170, table 3.36.
IsValidBitsPerSample(uint32_t x)482 bool IsValidBitsPerSample(uint32_t x) {
483   switch (x) {
484     case 1:
485     case 2:
486     case 4:
487     case 8:
488     case 12:
489     case 16:
490     case 24:
491     case 32:
492       return true;
493     default:
494       return false;
495   }
496 }
497 
498 // See PDF Reference 1.7, page 170.
PDF_Interpolate(FX_FLOAT x,FX_FLOAT xmin,FX_FLOAT xmax,FX_FLOAT ymin,FX_FLOAT ymax)499 FX_FLOAT PDF_Interpolate(FX_FLOAT x,
500                          FX_FLOAT xmin,
501                          FX_FLOAT xmax,
502                          FX_FLOAT ymin,
503                          FX_FLOAT ymax) {
504   FX_FLOAT divisor = xmax - xmin;
505   return ymin + (divisor ? (x - xmin) * (ymax - ymin) / divisor : 0);
506 }
507 
508 class CPDF_PSFunc : public CPDF_Function {
509  public:
CPDF_PSFunc()510   CPDF_PSFunc() : CPDF_Function(Type::kType4PostScript) {}
~CPDF_PSFunc()511   ~CPDF_PSFunc() override {}
512 
513   // CPDF_Function
514   FX_BOOL v_Init(CPDF_Object* pObj) override;
515   FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override;
516 
517  private:
518   CPDF_PSEngine m_PS;
519 };
520 
v_Init(CPDF_Object * pObj)521 FX_BOOL CPDF_PSFunc::v_Init(CPDF_Object* pObj) {
522   CPDF_StreamAcc acc;
523   acc.LoadAllData(pObj->AsStream(), FALSE);
524   return m_PS.Parse(reinterpret_cast<const FX_CHAR*>(acc.GetData()),
525                     acc.GetSize());
526 }
527 
v_Call(FX_FLOAT * inputs,FX_FLOAT * results) const528 FX_BOOL CPDF_PSFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const {
529   CPDF_PSEngine& PS = const_cast<CPDF_PSEngine&>(m_PS);
530   PS.Reset();
531   for (uint32_t i = 0; i < m_nInputs; i++)
532     PS.Push(inputs[i]);
533   PS.Execute();
534   if (PS.GetStackSize() < m_nOutputs)
535     return FALSE;
536   for (uint32_t i = 0; i < m_nOutputs; i++)
537     results[m_nOutputs - i - 1] = PS.Pop();
538   return TRUE;
539 }
540 
541 }  // namespace
542 
CPDF_SampledFunc()543 CPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) {}
544 
~CPDF_SampledFunc()545 CPDF_SampledFunc::~CPDF_SampledFunc() {}
546 
v_Init(CPDF_Object * pObj)547 FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) {
548   CPDF_Stream* pStream = pObj->AsStream();
549   if (!pStream)
550     return false;
551 
552   CPDF_Dictionary* pDict = pStream->GetDict();
553   CPDF_Array* pSize = pDict->GetArrayBy("Size");
554   CPDF_Array* pEncode = pDict->GetArrayBy("Encode");
555   CPDF_Array* pDecode = pDict->GetArrayBy("Decode");
556   m_nBitsPerSample = pDict->GetIntegerBy("BitsPerSample");
557   if (!IsValidBitsPerSample(m_nBitsPerSample))
558     return FALSE;
559 
560   m_SampleMax = 0xffffffff >> (32 - m_nBitsPerSample);
561   m_pSampleStream.reset(new CPDF_StreamAcc);
562   m_pSampleStream->LoadAllData(pStream, FALSE);
563   FX_SAFE_UINT32 nTotalSampleBits = 1;
564   m_EncodeInfo.resize(m_nInputs);
565   for (uint32_t i = 0; i < m_nInputs; i++) {
566     m_EncodeInfo[i].sizes = pSize ? pSize->GetIntegerAt(i) : 0;
567     if (!pSize && i == 0)
568       m_EncodeInfo[i].sizes = pDict->GetIntegerBy("Size");
569     nTotalSampleBits *= m_EncodeInfo[i].sizes;
570     if (pEncode) {
571       m_EncodeInfo[i].encode_min = pEncode->GetFloatAt(i * 2);
572       m_EncodeInfo[i].encode_max = pEncode->GetFloatAt(i * 2 + 1);
573     } else {
574       m_EncodeInfo[i].encode_min = 0;
575       m_EncodeInfo[i].encode_max =
576           m_EncodeInfo[i].sizes == 1 ? 1 : (FX_FLOAT)m_EncodeInfo[i].sizes - 1;
577     }
578   }
579   nTotalSampleBits *= m_nBitsPerSample;
580   nTotalSampleBits *= m_nOutputs;
581   FX_SAFE_UINT32 nTotalSampleBytes = nTotalSampleBits;
582   nTotalSampleBytes += 7;
583   nTotalSampleBytes /= 8;
584   if (!nTotalSampleBytes.IsValid() || nTotalSampleBytes.ValueOrDie() == 0 ||
585       nTotalSampleBytes.ValueOrDie() > m_pSampleStream->GetSize()) {
586     return FALSE;
587   }
588   m_DecodeInfo.resize(m_nOutputs);
589   for (uint32_t i = 0; i < m_nOutputs; i++) {
590     if (pDecode) {
591       m_DecodeInfo[i].decode_min = pDecode->GetFloatAt(2 * i);
592       m_DecodeInfo[i].decode_max = pDecode->GetFloatAt(2 * i + 1);
593     } else {
594       m_DecodeInfo[i].decode_min = m_pRanges[i * 2];
595       m_DecodeInfo[i].decode_max = m_pRanges[i * 2 + 1];
596     }
597   }
598   return TRUE;
599 }
600 
v_Call(FX_FLOAT * inputs,FX_FLOAT * results) const601 FX_BOOL CPDF_SampledFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const {
602   int pos = 0;
603   CFX_FixedBufGrow<FX_FLOAT, 16> encoded_input_buf(m_nInputs);
604   FX_FLOAT* encoded_input = encoded_input_buf;
605   CFX_FixedBufGrow<uint32_t, 32> int_buf(m_nInputs * 2);
606   uint32_t* index = int_buf;
607   uint32_t* blocksize = index + m_nInputs;
608   for (uint32_t i = 0; i < m_nInputs; i++) {
609     if (i == 0)
610       blocksize[i] = 1;
611     else
612       blocksize[i] = blocksize[i - 1] * m_EncodeInfo[i - 1].sizes;
613     encoded_input[i] =
614         PDF_Interpolate(inputs[i], m_pDomains[i * 2], m_pDomains[i * 2 + 1],
615                         m_EncodeInfo[i].encode_min, m_EncodeInfo[i].encode_max);
616     index[i] = std::min((uint32_t)std::max(0.f, encoded_input[i]),
617                         m_EncodeInfo[i].sizes - 1);
618     pos += index[i] * blocksize[i];
619   }
620   FX_SAFE_INT32 bits_to_output = m_nOutputs;
621   bits_to_output *= m_nBitsPerSample;
622   if (!bits_to_output.IsValid())
623     return FALSE;
624 
625   FX_SAFE_INT32 bitpos = pos;
626   bitpos *= bits_to_output.ValueOrDie();
627   if (!bitpos.IsValid())
628     return FALSE;
629 
630   FX_SAFE_INT32 range_check = bitpos;
631   range_check += bits_to_output.ValueOrDie();
632   if (!range_check.IsValid())
633     return FALSE;
634 
635   const uint8_t* pSampleData = m_pSampleStream->GetData();
636   if (!pSampleData)
637     return FALSE;
638 
639   for (uint32_t j = 0; j < m_nOutputs; j++) {
640     uint32_t sample =
641         GetBits32(pSampleData, bitpos.ValueOrDie() + j * m_nBitsPerSample,
642                   m_nBitsPerSample);
643     FX_FLOAT encoded = (FX_FLOAT)sample;
644     for (uint32_t i = 0; i < m_nInputs; i++) {
645       if (index[i] == m_EncodeInfo[i].sizes - 1) {
646         if (index[i] == 0)
647           encoded = encoded_input[i] * (FX_FLOAT)sample;
648       } else {
649         FX_SAFE_INT32 bitpos2 = blocksize[i];
650         bitpos2 += pos;
651         bitpos2 *= m_nOutputs;
652         bitpos2 += j;
653         bitpos2 *= m_nBitsPerSample;
654         if (!bitpos2.IsValid())
655           return FALSE;
656         uint32_t sample1 =
657             GetBits32(pSampleData, bitpos2.ValueOrDie(), m_nBitsPerSample);
658         encoded += (encoded_input[i] - index[i]) *
659                    ((FX_FLOAT)sample1 - (FX_FLOAT)sample);
660       }
661     }
662     results[j] =
663         PDF_Interpolate(encoded, 0, (FX_FLOAT)m_SampleMax,
664                         m_DecodeInfo[j].decode_min, m_DecodeInfo[j].decode_max);
665   }
666   return TRUE;
667 }
668 
CPDF_ExpIntFunc()669 CPDF_ExpIntFunc::CPDF_ExpIntFunc()
670     : CPDF_Function(Type::kType2ExpotentialInterpolation),
671       m_pBeginValues(nullptr),
672       m_pEndValues(nullptr) {}
673 
~CPDF_ExpIntFunc()674 CPDF_ExpIntFunc::~CPDF_ExpIntFunc() {
675   FX_Free(m_pBeginValues);
676   FX_Free(m_pEndValues);
677 }
v_Init(CPDF_Object * pObj)678 FX_BOOL CPDF_ExpIntFunc::v_Init(CPDF_Object* pObj) {
679   CPDF_Dictionary* pDict = pObj->GetDict();
680   if (!pDict) {
681     return FALSE;
682   }
683   CPDF_Array* pArray0 = pDict->GetArrayBy("C0");
684   if (m_nOutputs == 0) {
685     m_nOutputs = 1;
686     if (pArray0) {
687       m_nOutputs = pArray0->GetCount();
688     }
689   }
690   CPDF_Array* pArray1 = pDict->GetArrayBy("C1");
691   m_pBeginValues = FX_Alloc2D(FX_FLOAT, m_nOutputs, 2);
692   m_pEndValues = FX_Alloc2D(FX_FLOAT, m_nOutputs, 2);
693   for (uint32_t i = 0; i < m_nOutputs; i++) {
694     m_pBeginValues[i] = pArray0 ? pArray0->GetFloatAt(i) : 0.0f;
695     m_pEndValues[i] = pArray1 ? pArray1->GetFloatAt(i) : 1.0f;
696   }
697   m_Exponent = pDict->GetFloatBy("N");
698   m_nOrigOutputs = m_nOutputs;
699   if (m_nOutputs && m_nInputs > INT_MAX / m_nOutputs) {
700     return FALSE;
701   }
702   m_nOutputs *= m_nInputs;
703   return TRUE;
704 }
v_Call(FX_FLOAT * inputs,FX_FLOAT * results) const705 FX_BOOL CPDF_ExpIntFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const {
706   for (uint32_t i = 0; i < m_nInputs; i++)
707     for (uint32_t j = 0; j < m_nOrigOutputs; j++) {
708       results[i * m_nOrigOutputs + j] =
709           m_pBeginValues[j] +
710           (FX_FLOAT)FXSYS_pow(inputs[i], m_Exponent) *
711               (m_pEndValues[j] - m_pBeginValues[j]);
712     }
713   return TRUE;
714 }
715 
CPDF_StitchFunc()716 CPDF_StitchFunc::CPDF_StitchFunc()
717     : CPDF_Function(Type::kType3Stitching),
718       m_pBounds(nullptr),
719       m_pEncode(nullptr) {}
720 
~CPDF_StitchFunc()721 CPDF_StitchFunc::~CPDF_StitchFunc() {
722   FX_Free(m_pBounds);
723   FX_Free(m_pEncode);
724 }
725 
v_Init(CPDF_Object * pObj)726 FX_BOOL CPDF_StitchFunc::v_Init(CPDF_Object* pObj) {
727   CPDF_Dictionary* pDict = pObj->GetDict();
728   if (!pDict) {
729     return FALSE;
730   }
731   if (m_nInputs != kRequiredNumInputs) {
732     return FALSE;
733   }
734   CPDF_Array* pArray = pDict->GetArrayBy("Functions");
735   if (!pArray) {
736     return FALSE;
737   }
738   uint32_t nSubs = pArray->GetCount();
739   if (nSubs == 0)
740     return FALSE;
741   m_nOutputs = 0;
742   for (uint32_t i = 0; i < nSubs; i++) {
743     CPDF_Object* pSub = pArray->GetDirectObjectAt(i);
744     if (pSub == pObj)
745       return FALSE;
746     std::unique_ptr<CPDF_Function> pFunc(CPDF_Function::Load(pSub));
747     if (!pFunc)
748       return FALSE;
749     // Check that the input dimensionality is 1, and that all output
750     // dimensionalities are the same.
751     if (pFunc->CountInputs() != kRequiredNumInputs)
752       return FALSE;
753     if (pFunc->CountOutputs() != m_nOutputs) {
754       if (m_nOutputs)
755         return FALSE;
756 
757       m_nOutputs = pFunc->CountOutputs();
758     }
759 
760     m_pSubFunctions.push_back(std::move(pFunc));
761   }
762   m_pBounds = FX_Alloc(FX_FLOAT, nSubs + 1);
763   m_pBounds[0] = m_pDomains[0];
764   pArray = pDict->GetArrayBy("Bounds");
765   if (!pArray)
766     return FALSE;
767   for (uint32_t i = 0; i < nSubs - 1; i++)
768     m_pBounds[i + 1] = pArray->GetFloatAt(i);
769   m_pBounds[nSubs] = m_pDomains[1];
770   m_pEncode = FX_Alloc2D(FX_FLOAT, nSubs, 2);
771   pArray = pDict->GetArrayBy("Encode");
772   if (!pArray)
773     return FALSE;
774 
775   for (uint32_t i = 0; i < nSubs * 2; i++)
776     m_pEncode[i] = pArray->GetFloatAt(i);
777   return TRUE;
778 }
779 
v_Call(FX_FLOAT * inputs,FX_FLOAT * outputs) const780 FX_BOOL CPDF_StitchFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* outputs) const {
781   FX_FLOAT input = inputs[0];
782   size_t i;
783   for (i = 0; i < m_pSubFunctions.size() - 1; i++) {
784     if (input < m_pBounds[i + 1])
785       break;
786   }
787   input = PDF_Interpolate(input, m_pBounds[i], m_pBounds[i + 1],
788                           m_pEncode[i * 2], m_pEncode[i * 2 + 1]);
789   int nresults;
790   m_pSubFunctions[i]->Call(&input, kRequiredNumInputs, outputs, nresults);
791   return TRUE;
792 }
793 
794 // static
Load(CPDF_Object * pFuncObj)795 std::unique_ptr<CPDF_Function> CPDF_Function::Load(CPDF_Object* pFuncObj) {
796   std::unique_ptr<CPDF_Function> pFunc;
797   if (!pFuncObj)
798     return pFunc;
799 
800   int iType = -1;
801   if (CPDF_Stream* pStream = pFuncObj->AsStream())
802     iType = pStream->GetDict()->GetIntegerBy("FunctionType");
803   else if (CPDF_Dictionary* pDict = pFuncObj->AsDictionary())
804     iType = pDict->GetIntegerBy("FunctionType");
805 
806   Type type = IntegerToFunctionType(iType);
807   if (type == Type::kType0Sampled)
808     pFunc.reset(new CPDF_SampledFunc());
809   else if (type == Type::kType2ExpotentialInterpolation)
810     pFunc.reset(new CPDF_ExpIntFunc());
811   else if (type == Type::kType3Stitching)
812     pFunc.reset(new CPDF_StitchFunc());
813   else if (type == Type::kType4PostScript)
814     pFunc.reset(new CPDF_PSFunc());
815 
816   if (!pFunc || !pFunc->Init(pFuncObj))
817     return std::unique_ptr<CPDF_Function>();
818   return pFunc;
819 }
820 
821 // static
IntegerToFunctionType(int iType)822 CPDF_Function::Type CPDF_Function::IntegerToFunctionType(int iType) {
823   switch (iType) {
824     case 0:
825     case 2:
826     case 3:
827     case 4:
828       return static_cast<Type>(iType);
829     default:
830       return Type::kTypeInvalid;
831   }
832 }
833 
CPDF_Function(Type type)834 CPDF_Function::CPDF_Function(Type type)
835     : m_pDomains(nullptr), m_pRanges(nullptr), m_Type(type) {}
836 
~CPDF_Function()837 CPDF_Function::~CPDF_Function() {
838   FX_Free(m_pDomains);
839   FX_Free(m_pRanges);
840 }
841 
Init(CPDF_Object * pObj)842 FX_BOOL CPDF_Function::Init(CPDF_Object* pObj) {
843   CPDF_Stream* pStream = pObj->AsStream();
844   CPDF_Dictionary* pDict = pStream ? pStream->GetDict() : pObj->AsDictionary();
845 
846   CPDF_Array* pDomains = pDict->GetArrayBy("Domain");
847   if (!pDomains)
848     return FALSE;
849 
850   m_nInputs = pDomains->GetCount() / 2;
851   if (m_nInputs == 0)
852     return FALSE;
853 
854   m_pDomains = FX_Alloc2D(FX_FLOAT, m_nInputs, 2);
855   for (uint32_t i = 0; i < m_nInputs * 2; i++) {
856     m_pDomains[i] = pDomains->GetFloatAt(i);
857   }
858   CPDF_Array* pRanges = pDict->GetArrayBy("Range");
859   m_nOutputs = 0;
860   if (pRanges) {
861     m_nOutputs = pRanges->GetCount() / 2;
862     m_pRanges = FX_Alloc2D(FX_FLOAT, m_nOutputs, 2);
863     for (uint32_t i = 0; i < m_nOutputs * 2; i++)
864       m_pRanges[i] = pRanges->GetFloatAt(i);
865   }
866   uint32_t old_outputs = m_nOutputs;
867   if (!v_Init(pObj))
868     return FALSE;
869   if (m_pRanges && m_nOutputs > old_outputs) {
870     m_pRanges = FX_Realloc(FX_FLOAT, m_pRanges, m_nOutputs * 2);
871     if (m_pRanges) {
872       FXSYS_memset(m_pRanges + (old_outputs * 2), 0,
873                    sizeof(FX_FLOAT) * (m_nOutputs - old_outputs) * 2);
874     }
875   }
876   return TRUE;
877 }
878 
Call(FX_FLOAT * inputs,uint32_t ninputs,FX_FLOAT * results,int & nresults) const879 FX_BOOL CPDF_Function::Call(FX_FLOAT* inputs,
880                             uint32_t ninputs,
881                             FX_FLOAT* results,
882                             int& nresults) const {
883   if (m_nInputs != ninputs) {
884     return FALSE;
885   }
886   nresults = m_nOutputs;
887   for (uint32_t i = 0; i < m_nInputs; i++) {
888     if (inputs[i] < m_pDomains[i * 2])
889       inputs[i] = m_pDomains[i * 2];
890     else if (inputs[i] > m_pDomains[i * 2 + 1])
891       inputs[i] = m_pDomains[i * 2] + 1;
892   }
893   v_Call(inputs, results);
894   if (m_pRanges) {
895     for (uint32_t i = 0; i < m_nOutputs; i++) {
896       if (results[i] < m_pRanges[i * 2])
897         results[i] = m_pRanges[i * 2];
898       else if (results[i] > m_pRanges[i * 2 + 1])
899         results[i] = m_pRanges[i * 2 + 1];
900     }
901   }
902   return TRUE;
903 }
904 
ToSampledFunc() const905 const CPDF_SampledFunc* CPDF_Function::ToSampledFunc() const {
906   return m_Type == Type::kType0Sampled
907              ? static_cast<const CPDF_SampledFunc*>(this)
908              : nullptr;
909 }
910 
ToExpIntFunc() const911 const CPDF_ExpIntFunc* CPDF_Function::ToExpIntFunc() const {
912   return m_Type == Type::kType2ExpotentialInterpolation
913              ? static_cast<const CPDF_ExpIntFunc*>(this)
914              : nullptr;
915 }
916 
ToStitchFunc() const917 const CPDF_StitchFunc* CPDF_Function::ToStitchFunc() const {
918   return m_Type == Type::kType3Stitching
919              ? static_cast<const CPDF_StitchFunc*>(this)
920              : nullptr;
921 }
922