Remove unneeded checks for CPDF_Object::GetDict() return values.
[pdfium.git] / core / src / fpdfapi / fpdf_parser / fpdf_parser_parser.cpp
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 <set>
8 #include <utility>
9 #include <vector>
10
11 #include "../../../include/fpdfapi/fpdf_module.h"
12 #include "../../../include/fpdfapi/fpdf_page.h"
13 #include "../../../include/fpdfapi/fpdf_parser.h"
14 #include "../../../include/fxcrt/fx_safe_types.h"
15 #include "../fpdf_page/pageint.h"
16
17 FX_BOOL IsSignatureDict(const CPDF_Dictionary* pDict) {
18   CPDF_Object* pType = pDict->GetElementValue(FX_BSTRC("Type"));
19   if (!pType) {
20     pType = pDict->GetElementValue(FX_BSTRC("FT"));
21     if (!pType) {
22       return FALSE;
23     }
24   }
25   if (pType->GetString() == FX_BSTRC("Sig")) {
26     return TRUE;
27   }
28   return FALSE;
29 }
30 static int _CompareFileSize(const void* p1, const void* p2) {
31   FX_FILESIZE ret = (*(FX_FILESIZE*)p1) - (*(FX_FILESIZE*)p2);
32   if (ret > 0) {
33     return 1;
34   }
35   if (ret < 0) {
36     return -1;
37   }
38   return 0;
39 }
40
41 CPDF_Parser::CPDF_Parser() {
42   m_pDocument = NULL;
43   m_pTrailer = NULL;
44   m_pEncryptDict = NULL;
45   m_pSecurityHandler = NULL;
46   m_pLinearized = NULL;
47   m_dwFirstPageNo = 0;
48   m_dwXrefStartObjNum = 0;
49   m_bOwnFileRead = TRUE;
50   m_FileVersion = 0;
51   m_bForceUseSecurityHandler = FALSE;
52 }
53 CPDF_Parser::~CPDF_Parser() {
54   CloseParser(FALSE);
55 }
56 FX_DWORD CPDF_Parser::GetLastObjNum() {
57   FX_DWORD dwSize = m_CrossRef.GetSize();
58   return dwSize ? dwSize - 1 : 0;
59 }
60 void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict) {
61   m_pEncryptDict = pDict;
62 }
63 void CPDF_Parser::CloseParser(FX_BOOL bReParse) {
64   m_bVersionUpdated = FALSE;
65   if (!bReParse) {
66     delete m_pDocument;
67     m_pDocument = NULL;
68   }
69   if (m_pTrailer) {
70     m_pTrailer->Release();
71     m_pTrailer = NULL;
72   }
73   ReleaseEncryptHandler();
74   SetEncryptDictionary(NULL);
75   if (m_bOwnFileRead && m_Syntax.m_pFileAccess) {
76     m_Syntax.m_pFileAccess->Release();
77     m_Syntax.m_pFileAccess = NULL;
78   }
79   FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
80   while (pos) {
81     void* objnum;
82     CPDF_StreamAcc* pStream;
83     m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream);
84     delete pStream;
85   }
86   m_ObjectStreamMap.RemoveAll();
87   m_SortedOffset.RemoveAll();
88   m_CrossRef.RemoveAll();
89   m_V5Type.RemoveAll();
90   m_ObjVersion.RemoveAll();
91   int32_t iLen = m_Trailers.GetSize();
92   for (int32_t i = 0; i < iLen; ++i) {
93     if (CPDF_Dictionary* trailer = m_Trailers.GetAt(i))
94       trailer->Release();
95   }
96   m_Trailers.RemoveAll();
97   if (m_pLinearized) {
98     m_pLinearized->Release();
99     m_pLinearized = NULL;
100   }
101 }
102 static int32_t GetHeaderOffset(IFX_FileRead* pFile) {
103   FX_DWORD tag = FXDWORD_FROM_LSBFIRST(0x46445025);
104   uint8_t buf[4];
105   int32_t offset = 0;
106   while (1) {
107     if (!pFile->ReadBlock(buf, offset, 4)) {
108       return -1;
109     }
110     if (*(FX_DWORD*)buf == tag) {
111       return offset;
112     }
113     offset++;
114     if (offset > 1024) {
115       return -1;
116     }
117   }
118   return -1;
119 }
120 CPDF_SecurityHandler* FPDF_CreateStandardSecurityHandler();
121 CPDF_SecurityHandler* FPDF_CreatePubKeyHandler(void*);
122 FX_DWORD CPDF_Parser::StartParse(IFX_FileRead* pFileAccess,
123                                  FX_BOOL bReParse,
124                                  FX_BOOL bOwnFileRead) {
125   CloseParser(bReParse);
126   m_bXRefStream = FALSE;
127   m_LastXRefOffset = 0;
128   m_bOwnFileRead = bOwnFileRead;
129   int32_t offset = GetHeaderOffset(pFileAccess);
130   if (offset == -1) {
131     if (bOwnFileRead && pFileAccess) {
132       pFileAccess->Release();
133     }
134     return PDFPARSE_ERROR_FORMAT;
135   }
136   m_Syntax.InitParser(pFileAccess, offset);
137   uint8_t ch;
138   if (!m_Syntax.GetCharAt(5, ch)) {
139     return PDFPARSE_ERROR_FORMAT;
140   }
141   if (ch >= '0' && ch <= '9') {
142     m_FileVersion = (ch - '0') * 10;
143   }
144   if (!m_Syntax.GetCharAt(7, ch)) {
145     return PDFPARSE_ERROR_FORMAT;
146   }
147   if (ch >= '0' && ch <= '9') {
148     m_FileVersion += ch - '0';
149   }
150   if (m_Syntax.m_FileLen < m_Syntax.m_HeaderOffset + 9) {
151     return PDFPARSE_ERROR_FORMAT;
152   }
153   m_Syntax.RestorePos(m_Syntax.m_FileLen - m_Syntax.m_HeaderOffset - 9);
154   if (!bReParse) {
155     m_pDocument = new CPDF_Document(this);
156   }
157   FX_BOOL bXRefRebuilt = FALSE;
158   if (m_Syntax.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, 4096)) {
159     FX_FILESIZE startxref_offset = m_Syntax.SavePos();
160     void* pResult = FXSYS_bsearch(&startxref_offset, m_SortedOffset.GetData(),
161                                   m_SortedOffset.GetSize(), sizeof(FX_FILESIZE),
162                                   _CompareFileSize);
163     if (pResult == NULL) {
164       m_SortedOffset.Add(startxref_offset);
165     }
166     m_Syntax.GetKeyword();
167     FX_BOOL bNumber;
168     CFX_ByteString xrefpos_str = m_Syntax.GetNextWord(bNumber);
169     if (!bNumber) {
170       return PDFPARSE_ERROR_FORMAT;
171     }
172     m_LastXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str);
173     if (!LoadAllCrossRefV4(m_LastXRefOffset) &&
174         !LoadAllCrossRefV5(m_LastXRefOffset)) {
175       if (!RebuildCrossRef()) {
176         return PDFPARSE_ERROR_FORMAT;
177       }
178       bXRefRebuilt = TRUE;
179       m_LastXRefOffset = 0;
180     }
181   } else {
182     if (!RebuildCrossRef()) {
183       return PDFPARSE_ERROR_FORMAT;
184     }
185     bXRefRebuilt = TRUE;
186   }
187   FX_DWORD dwRet = SetEncryptHandler();
188   if (dwRet != PDFPARSE_ERROR_SUCCESS) {
189     return dwRet;
190   }
191   m_pDocument->LoadDoc();
192   if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) {
193     if (bXRefRebuilt) {
194       return PDFPARSE_ERROR_FORMAT;
195     }
196     ReleaseEncryptHandler();
197     if (!RebuildCrossRef()) {
198       return PDFPARSE_ERROR_FORMAT;
199     }
200     dwRet = SetEncryptHandler();
201     if (dwRet != PDFPARSE_ERROR_SUCCESS) {
202       return dwRet;
203     }
204     m_pDocument->LoadDoc();
205     if (m_pDocument->GetRoot() == NULL) {
206       return PDFPARSE_ERROR_FORMAT;
207     }
208   }
209   FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(),
210               sizeof(FX_FILESIZE), _CompareFileSize);
211   FX_DWORD RootObjNum = GetRootObjNum();
212   if (RootObjNum == 0) {
213     ReleaseEncryptHandler();
214     RebuildCrossRef();
215     RootObjNum = GetRootObjNum();
216     if (RootObjNum == 0) {
217       return PDFPARSE_ERROR_FORMAT;
218     }
219     dwRet = SetEncryptHandler();
220     if (dwRet != PDFPARSE_ERROR_SUCCESS) {
221       return dwRet;
222     }
223   }
224   if (m_pSecurityHandler && !m_pSecurityHandler->IsMetadataEncrypted()) {
225     CPDF_Reference* pMetadata =
226         (CPDF_Reference*)m_pDocument->GetRoot()->GetElement(
227             FX_BSTRC("Metadata"));
228     if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) {
229       m_Syntax.m_MetadataObjnum = pMetadata->GetRefObjNum();
230     }
231   }
232   return PDFPARSE_ERROR_SUCCESS;
233 }
234 FX_DWORD CPDF_Parser::SetEncryptHandler() {
235   ReleaseEncryptHandler();
236   SetEncryptDictionary(NULL);
237   if (m_pTrailer == NULL) {
238     return PDFPARSE_ERROR_FORMAT;
239   }
240   CPDF_Object* pEncryptObj = m_pTrailer->GetElement(FX_BSTRC("Encrypt"));
241   if (pEncryptObj) {
242     if (pEncryptObj->GetType() == PDFOBJ_DICTIONARY) {
243       SetEncryptDictionary((CPDF_Dictionary*)pEncryptObj);
244     } else if (pEncryptObj->GetType() == PDFOBJ_REFERENCE) {
245       pEncryptObj = m_pDocument->GetIndirectObject(
246           ((CPDF_Reference*)pEncryptObj)->GetRefObjNum());
247       if (pEncryptObj) {
248         SetEncryptDictionary(pEncryptObj->GetDict());
249       }
250     }
251   }
252   if (m_bForceUseSecurityHandler) {
253     FX_DWORD err = PDFPARSE_ERROR_HANDLER;
254     if (m_pSecurityHandler == NULL) {
255       return PDFPARSE_ERROR_HANDLER;
256     }
257     if (!m_pSecurityHandler->OnInit(this, m_pEncryptDict)) {
258       return err;
259     }
260     CPDF_CryptoHandler* pCryptoHandler =
261         m_pSecurityHandler->CreateCryptoHandler();
262     if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler)) {
263       delete pCryptoHandler;
264       pCryptoHandler = NULL;
265       return PDFPARSE_ERROR_HANDLER;
266     }
267     m_Syntax.SetEncrypt(pCryptoHandler);
268   } else if (m_pEncryptDict) {
269     CFX_ByteString filter = m_pEncryptDict->GetString(FX_BSTRC("Filter"));
270     CPDF_SecurityHandler* pSecurityHandler = NULL;
271     FX_DWORD err = PDFPARSE_ERROR_HANDLER;
272     if (filter == FX_BSTRC("Standard")) {
273       pSecurityHandler = FPDF_CreateStandardSecurityHandler();
274       err = PDFPARSE_ERROR_PASSWORD;
275     }
276     if (pSecurityHandler == NULL) {
277       return PDFPARSE_ERROR_HANDLER;
278     }
279     if (!pSecurityHandler->OnInit(this, m_pEncryptDict)) {
280       delete pSecurityHandler;
281       pSecurityHandler = NULL;
282       return err;
283     }
284     m_pSecurityHandler = pSecurityHandler;
285     CPDF_CryptoHandler* pCryptoHandler =
286         pSecurityHandler->CreateCryptoHandler();
287     if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler)) {
288       delete pCryptoHandler;
289       pCryptoHandler = NULL;
290       return PDFPARSE_ERROR_HANDLER;
291     }
292     m_Syntax.SetEncrypt(pCryptoHandler);
293   }
294   return PDFPARSE_ERROR_SUCCESS;
295 }
296 void CPDF_Parser::ReleaseEncryptHandler() {
297   delete m_Syntax.m_pCryptoHandler;
298   m_Syntax.m_pCryptoHandler = NULL;
299   if (!m_bForceUseSecurityHandler) {
300     delete m_pSecurityHandler;
301     m_pSecurityHandler = NULL;
302   }
303 }
304 FX_FILESIZE CPDF_Parser::GetObjectOffset(FX_DWORD objnum) {
305   if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
306     return 0;
307   }
308   if (m_V5Type[objnum] == 1) {
309     return m_CrossRef[objnum];
310   }
311   if (m_V5Type[objnum] == 2) {
312     return m_CrossRef[(int32_t)m_CrossRef[objnum]];
313   }
314   return 0;
315 }
316 static int32_t GetDirectInteger(CPDF_Dictionary* pDict,
317                                 const CFX_ByteStringC& key) {
318   CPDF_Object* pObj = pDict->GetElement(key);
319   if (pObj == NULL) {
320     return 0;
321   }
322   if (pObj->GetType() == PDFOBJ_NUMBER) {
323     return ((CPDF_Number*)pObj)->GetInteger();
324   }
325   return 0;
326 }
327 static FX_BOOL CheckDirectType(CPDF_Dictionary* pDict,
328                                const CFX_ByteStringC& key,
329                                int32_t iType) {
330   CPDF_Object* pObj = pDict->GetElement(key);
331   if (!pObj) {
332     return TRUE;
333   }
334   return pObj->GetType() == iType;
335 }
336 FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) {
337   if (!LoadCrossRefV4(xrefpos, 0, TRUE, FALSE)) {
338     return FALSE;
339   }
340   m_pTrailer = LoadTrailerV4();
341   if (m_pTrailer == NULL) {
342     return FALSE;
343   }
344   int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
345   if (xrefsize <= 0 || xrefsize > (1 << 20)) {
346     return FALSE;
347   }
348   m_CrossRef.SetSize(xrefsize);
349   m_V5Type.SetSize(xrefsize);
350   CFX_FileSizeArray CrossRefList, XRefStreamList;
351   CrossRefList.Add(xrefpos);
352   XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm")));
353   if (!CheckDirectType(m_pTrailer, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) {
354     return FALSE;
355   }
356   FX_FILESIZE newxrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev"));
357   if (newxrefpos == xrefpos) {
358     return FALSE;
359   }
360   xrefpos = newxrefpos;
361   while (xrefpos) {
362     CrossRefList.InsertAt(0, xrefpos);
363     LoadCrossRefV4(xrefpos, 0, TRUE, FALSE);
364     CPDF_Dictionary* pDict = LoadTrailerV4();
365     if (pDict == NULL) {
366       return FALSE;
367     }
368     if (!CheckDirectType(pDict, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) {
369       pDict->Release();
370       return FALSE;
371     }
372     newxrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev"));
373     if (newxrefpos == xrefpos) {
374       pDict->Release();
375       return FALSE;
376     }
377     xrefpos = newxrefpos;
378     XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm")));
379     m_Trailers.Add(pDict);
380   }
381   for (int32_t i = 0; i < CrossRefList.GetSize(); i++)
382     if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) {
383       return FALSE;
384     }
385   return TRUE;
386 }
387 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos,
388                                                  FX_DWORD dwObjCount) {
389   if (!LoadLinearizedCrossRefV4(xrefpos, dwObjCount)) {
390     return FALSE;
391   }
392   m_pTrailer = LoadTrailerV4();
393   if (m_pTrailer == NULL) {
394     return FALSE;
395   }
396   int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
397   if (xrefsize == 0) {
398     return FALSE;
399   }
400   CFX_FileSizeArray CrossRefList, XRefStreamList;
401   CrossRefList.Add(xrefpos);
402   XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm")));
403   xrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev"));
404   while (xrefpos) {
405     CrossRefList.InsertAt(0, xrefpos);
406     LoadCrossRefV4(xrefpos, 0, TRUE, FALSE);
407     CPDF_Dictionary* pDict = LoadTrailerV4();
408     if (pDict == NULL) {
409       return FALSE;
410     }
411     xrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev"));
412     XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm")));
413     m_Trailers.Add(pDict);
414   }
415   for (int32_t i = 1; i < CrossRefList.GetSize(); i++)
416     if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) {
417       return FALSE;
418     }
419   return TRUE;
420 }
421 FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos,
422                                               FX_DWORD dwObjCount) {
423   FX_FILESIZE dwStartPos = pos - m_Syntax.m_HeaderOffset;
424   m_Syntax.RestorePos(dwStartPos);
425   void* pResult =
426       FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(),
427                     sizeof(FX_FILESIZE), _CompareFileSize);
428   if (pResult == NULL) {
429     m_SortedOffset.Add(pos);
430   }
431   FX_DWORD start_objnum = 0;
432   FX_DWORD count = dwObjCount;
433   FX_FILESIZE SavedPos = m_Syntax.SavePos();
434   int32_t recordsize = 20;
435   char* pBuf = FX_Alloc(char, 1024 * recordsize + 1);
436   pBuf[1024 * recordsize] = '\0';
437   int32_t nBlocks = count / 1024 + 1;
438   for (int32_t block = 0; block < nBlocks; block++) {
439     int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024;
440     FX_DWORD dwReadSize = block_size * recordsize;
441     if ((FX_FILESIZE)(dwStartPos + dwReadSize) > m_Syntax.m_FileLen) {
442       FX_Free(pBuf);
443       return FALSE;
444     }
445     if (!m_Syntax.ReadBlock((uint8_t*)pBuf, dwReadSize)) {
446       FX_Free(pBuf);
447       return FALSE;
448     }
449     for (int32_t i = 0; i < block_size; i++) {
450       FX_DWORD objnum = start_objnum + block * 1024 + i;
451       char* pEntry = pBuf + i * recordsize;
452       if (pEntry[17] == 'f') {
453         m_CrossRef.SetAtGrow(objnum, 0);
454         m_V5Type.SetAtGrow(objnum, 0);
455       } else {
456         int32_t offset = FXSYS_atoi(pEntry);
457         if (offset == 0) {
458           for (int32_t c = 0; c < 10; c++) {
459             if (pEntry[c] < '0' || pEntry[c] > '9') {
460               FX_Free(pBuf);
461               return FALSE;
462             }
463           }
464         }
465         m_CrossRef.SetAtGrow(objnum, offset);
466         int32_t version = FXSYS_atoi(pEntry + 11);
467         if (version >= 1) {
468           m_bVersionUpdated = TRUE;
469         }
470         m_ObjVersion.SetAtGrow(objnum, version);
471         if (m_CrossRef[objnum] < m_Syntax.m_FileLen) {
472           void* pResult = FXSYS_bsearch(
473               &m_CrossRef[objnum], m_SortedOffset.GetData(),
474               m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
475           if (pResult == NULL) {
476             m_SortedOffset.Add(m_CrossRef[objnum]);
477           }
478         }
479         m_V5Type.SetAtGrow(objnum, 1);
480       }
481     }
482   }
483   FX_Free(pBuf);
484   m_Syntax.RestorePos(SavedPos + count * recordsize);
485   return TRUE;
486 }
487 FX_BOOL CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos,
488                                     FX_FILESIZE streampos,
489                                     FX_BOOL bSkip,
490                                     FX_BOOL bFirst) {
491   m_Syntax.RestorePos(pos);
492   if (m_Syntax.GetKeyword() != FX_BSTRC("xref")) {
493     return FALSE;
494   }
495   void* pResult =
496       FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(),
497                     sizeof(FX_FILESIZE), _CompareFileSize);
498   if (pResult == NULL) {
499     m_SortedOffset.Add(pos);
500   }
501   if (streampos) {
502     void* pResult = FXSYS_bsearch(&streampos, m_SortedOffset.GetData(),
503                                   m_SortedOffset.GetSize(), sizeof(FX_FILESIZE),
504                                   _CompareFileSize);
505     if (pResult == NULL) {
506       m_SortedOffset.Add(streampos);
507     }
508   }
509   while (1) {
510     FX_FILESIZE SavedPos = m_Syntax.SavePos();
511     FX_BOOL bIsNumber;
512     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
513     if (word.IsEmpty()) {
514       return FALSE;
515     }
516     if (!bIsNumber) {
517       m_Syntax.RestorePos(SavedPos);
518       break;
519     }
520     FX_DWORD start_objnum = FXSYS_atoi(word);
521     if (start_objnum >= (1 << 20)) {
522       return FALSE;
523     }
524     FX_DWORD count = m_Syntax.GetDirectNum();
525     m_Syntax.ToNextWord();
526     SavedPos = m_Syntax.SavePos();
527     FX_BOOL bFirstItem = FALSE;
528     int32_t recordsize = 20;
529     if (bFirst) {
530       bFirstItem = TRUE;
531     }
532     m_dwXrefStartObjNum = start_objnum;
533     if (!bSkip) {
534       char* pBuf = FX_Alloc(char, 1024 * recordsize + 1);
535       pBuf[1024 * recordsize] = '\0';
536       int32_t nBlocks = count / 1024 + 1;
537       FX_BOOL bFirstBlock = TRUE;
538       for (int32_t block = 0; block < nBlocks; block++) {
539         int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024;
540         m_Syntax.ReadBlock((uint8_t*)pBuf, block_size * recordsize);
541         for (int32_t i = 0; i < block_size; i++) {
542           FX_DWORD objnum = start_objnum + block * 1024 + i;
543           char* pEntry = pBuf + i * recordsize;
544           if (pEntry[17] == 'f') {
545             if (bFirstItem) {
546               objnum = 0;
547               bFirstItem = FALSE;
548             }
549             if (bFirstBlock) {
550               FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry);
551               int32_t version = FXSYS_atoi(pEntry + 11);
552               if (offset == 0 && version == 65535 && start_objnum != 0) {
553                 start_objnum--;
554                 objnum = 0;
555               }
556             }
557             m_CrossRef.SetAtGrow(objnum, 0);
558             m_V5Type.SetAtGrow(objnum, 0);
559           } else {
560             FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry);
561             if (offset == 0) {
562               for (int32_t c = 0; c < 10; c++) {
563                 if (pEntry[c] < '0' || pEntry[c] > '9') {
564                   FX_Free(pBuf);
565                   return FALSE;
566                 }
567               }
568             }
569             m_CrossRef.SetAtGrow(objnum, offset);
570             int32_t version = FXSYS_atoi(pEntry + 11);
571             if (version >= 1) {
572               m_bVersionUpdated = TRUE;
573             }
574             m_ObjVersion.SetAtGrow(objnum, version);
575             if (m_CrossRef[objnum] < m_Syntax.m_FileLen) {
576               void* pResult =
577                   FXSYS_bsearch(&m_CrossRef[objnum], m_SortedOffset.GetData(),
578                                 m_SortedOffset.GetSize(), sizeof(FX_FILESIZE),
579                                 _CompareFileSize);
580               if (pResult == NULL) {
581                 m_SortedOffset.Add(m_CrossRef[objnum]);
582               }
583             }
584             m_V5Type.SetAtGrow(objnum, 1);
585           }
586           if (bFirstBlock) {
587             bFirstBlock = FALSE;
588           }
589         }
590       }
591       FX_Free(pBuf);
592     }
593     m_Syntax.RestorePos(SavedPos + count * recordsize);
594   }
595   if (streampos)
596     if (!LoadCrossRefV5(streampos, streampos, FALSE)) {
597       return FALSE;
598     }
599   return TRUE;
600 }
601 FX_BOOL CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) {
602   if (!LoadCrossRefV5(xrefpos, xrefpos, TRUE)) {
603     return FALSE;
604   }
605   while (xrefpos)
606     if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
607       return FALSE;
608     }
609   m_ObjectStreamMap.InitHashTable(101, FALSE);
610   m_bXRefStream = TRUE;
611   return TRUE;
612 }
613 FX_BOOL CPDF_Parser::RebuildCrossRef() {
614   m_CrossRef.RemoveAll();
615   m_V5Type.RemoveAll();
616   m_SortedOffset.RemoveAll();
617   m_ObjVersion.RemoveAll();
618   if (m_pTrailer) {
619     m_pTrailer->Release();
620     m_pTrailer = NULL;
621   }
622   int32_t status = 0;
623   int32_t inside_index = 0;
624   FX_DWORD objnum = 0, gennum = 0;
625   int32_t depth = 0;
626   uint8_t* buffer = FX_Alloc(uint8_t, 4096);
627   FX_FILESIZE pos = m_Syntax.m_HeaderOffset;
628   FX_FILESIZE start_pos = 0, start_pos1 = 0;
629   FX_FILESIZE last_obj = -1, last_xref = -1, last_trailer = -1;
630   while (pos < m_Syntax.m_FileLen) {
631     FX_BOOL bOverFlow = FALSE;
632     FX_DWORD size = (FX_DWORD)(m_Syntax.m_FileLen - pos);
633     if (size > 4096) {
634       size = 4096;
635     }
636     if (!m_Syntax.m_pFileAccess->ReadBlock(buffer, pos, size)) {
637       break;
638     }
639     for (FX_DWORD i = 0; i < size; i++) {
640       uint8_t byte = buffer[i];
641       switch (status) {
642         case 0:
643           if (PDF_CharType[byte] == 'W') {
644             status = 1;
645           }
646           if (byte <= '9' && byte >= '0') {
647             --i;
648             status = 1;
649           }
650           if (byte == '%') {
651             inside_index = 0;
652             status = 9;
653           }
654           if (byte == '(') {
655             status = 10;
656             depth = 1;
657           }
658           if (byte == '<') {
659             inside_index = 1;
660             status = 11;
661           }
662           if (byte == '\\') {
663             status = 13;
664           }
665           if (byte == 't') {
666             status = 7;
667             inside_index = 1;
668           }
669           break;
670         case 1:
671           if (PDF_CharType[byte] == 'W') {
672             break;
673           } else if (byte <= '9' && byte >= '0') {
674             start_pos = pos + i;
675             status = 2;
676             objnum = byte - '0';
677           } else if (byte == 't') {
678             status = 7;
679             inside_index = 1;
680           } else if (byte == 'x') {
681             status = 8;
682             inside_index = 1;
683           } else {
684             --i;
685             status = 0;
686           }
687           break;
688         case 2:
689           if (byte <= '9' && byte >= '0') {
690             objnum = objnum * 10 + byte - '0';
691             break;
692           } else if (PDF_CharType[byte] == 'W') {
693             status = 3;
694           } else {
695             --i;
696             status = 14;
697             inside_index = 0;
698           }
699           break;
700         case 3:
701           if (byte <= '9' && byte >= '0') {
702             start_pos1 = pos + i;
703             status = 4;
704             gennum = byte - '0';
705           } else if (PDF_CharType[byte] == 'W') {
706             break;
707           } else if (byte == 't') {
708             status = 7;
709             inside_index = 1;
710           } else {
711             --i;
712             status = 0;
713           }
714           break;
715         case 4:
716           if (byte <= '9' && byte >= '0') {
717             gennum = gennum * 10 + byte - '0';
718             break;
719           } else if (PDF_CharType[byte] == 'W') {
720             status = 5;
721           } else {
722             --i;
723             status = 0;
724           }
725           break;
726         case 5:
727           if (byte == 'o') {
728             status = 6;
729             inside_index = 1;
730           } else if (PDF_CharType[byte] == 'W') {
731             break;
732           } else if (byte <= '9' && byte >= '0') {
733             objnum = gennum;
734             gennum = byte - '0';
735             start_pos = start_pos1;
736             start_pos1 = pos + i;
737             status = 4;
738           } else if (byte == 't') {
739             status = 7;
740             inside_index = 1;
741           } else {
742             --i;
743             status = 0;
744           }
745           break;
746         case 6:
747           switch (inside_index) {
748             case 1:
749               if (byte != 'b') {
750                 --i;
751                 status = 0;
752               } else {
753                 inside_index++;
754               }
755               break;
756             case 2:
757               if (byte != 'j') {
758                 --i;
759                 status = 0;
760               } else {
761                 inside_index++;
762               }
763               break;
764             case 3:
765               if (PDF_CharType[byte] == 'W' || PDF_CharType[byte] == 'D') {
766                 if (objnum > 0x1000000) {
767                   status = 0;
768                   break;
769                 }
770                 FX_FILESIZE obj_pos = start_pos - m_Syntax.m_HeaderOffset;
771                 last_obj = start_pos;
772                 void* pResult =
773                     FXSYS_bsearch(&obj_pos, m_SortedOffset.GetData(),
774                                   m_SortedOffset.GetSize(), sizeof(FX_FILESIZE),
775                                   _CompareFileSize);
776                 if (pResult == NULL) {
777                   m_SortedOffset.Add(obj_pos);
778                 }
779                 FX_FILESIZE obj_end = 0;
780                 CPDF_Object* pObject = ParseIndirectObjectAtByStrict(
781                     m_pDocument, obj_pos, objnum, NULL, &obj_end);
782                 if (pObject) {
783                   int iType = pObject->GetType();
784                   if (iType == PDFOBJ_STREAM) {
785                     CPDF_Stream* pStream = (CPDF_Stream*)pObject;
786                     CPDF_Dictionary* pDict = pStream->GetDict();
787                     if (pDict) {
788                       if (pDict->KeyExist(FX_BSTRC("Type"))) {
789                         CFX_ByteString bsValue =
790                             pDict->GetString(FX_BSTRC("Type"));
791                         if (bsValue == FX_BSTRC("XRef") &&
792                             pDict->KeyExist(FX_BSTRC("Size"))) {
793                           CPDF_Object* pRoot =
794                               pDict->GetElement(FX_BSTRC("Root"));
795                           if (pRoot && pRoot->GetDict() &&
796                               pRoot->GetDict()->GetElement(FX_BSTRC("Pages"))) {
797                             if (m_pTrailer) {
798                               m_pTrailer->Release();
799                             }
800                             m_pTrailer = (CPDF_Dictionary*)pDict->Clone();
801                           }
802                         }
803                       }
804                     }
805                   }
806                 }
807                 FX_FILESIZE offset = 0;
808                 m_Syntax.RestorePos(obj_pos);
809                 offset = m_Syntax.FindTag(FX_BSTRC("obj"), 0);
810                 if (offset == -1) {
811                   offset = 0;
812                 } else {
813                   offset += 3;
814                 }
815                 FX_FILESIZE nLen = obj_end - obj_pos - offset;
816                 if ((FX_DWORD)nLen > size - i) {
817                   pos = obj_end + m_Syntax.m_HeaderOffset;
818                   bOverFlow = TRUE;
819                 } else {
820                   i += (FX_DWORD)nLen;
821                 }
822                 if (m_CrossRef.GetSize() > (int32_t)objnum &&
823                     m_CrossRef[objnum]) {
824                   if (pObject) {
825                     FX_DWORD oldgen = m_ObjVersion.GetAt(objnum);
826                     m_CrossRef[objnum] = obj_pos;
827                     m_ObjVersion.SetAt(objnum, (int16_t)gennum);
828                     if (oldgen != gennum) {
829                       m_bVersionUpdated = TRUE;
830                     }
831                   }
832                 } else {
833                   m_CrossRef.SetAtGrow(objnum, obj_pos);
834                   m_V5Type.SetAtGrow(objnum, 1);
835                   m_ObjVersion.SetAtGrow(objnum, (int16_t)gennum);
836                 }
837                 if (pObject) {
838                   pObject->Release();
839                 }
840               }
841               --i;
842               status = 0;
843               break;
844           }
845           break;
846         case 7:
847           if (inside_index == 7) {
848             if (PDF_CharType[byte] == 'W' || PDF_CharType[byte] == 'D') {
849               last_trailer = pos + i - 7;
850               m_Syntax.RestorePos(pos + i - m_Syntax.m_HeaderOffset);
851               CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0);
852               if (pObj) {
853                 if (pObj->GetType() != PDFOBJ_DICTIONARY &&
854                     pObj->GetType() != PDFOBJ_STREAM) {
855                   pObj->Release();
856                 } else {
857                   CPDF_Dictionary* pTrailer = NULL;
858                   if (pObj->GetType() == PDFOBJ_STREAM) {
859                     pTrailer = ((CPDF_Stream*)pObj)->GetDict();
860                   } else {
861                     pTrailer = (CPDF_Dictionary*)pObj;
862                   }
863                   if (pTrailer) {
864                     if (m_pTrailer) {
865                       CPDF_Object* pRoot =
866                           pTrailer->GetElement(FX_BSTRC("Root"));
867                       if (pRoot == NULL ||
868                           (pRoot->GetType() == PDFOBJ_REFERENCE &&
869                            (FX_DWORD)m_CrossRef.GetSize() >
870                                ((CPDF_Reference*)pRoot)->GetRefObjNum() &&
871                            m_CrossRef.GetAt(((CPDF_Reference*)pRoot)
872                                                 ->GetRefObjNum()) != 0)) {
873                         FX_POSITION pos = pTrailer->GetStartPos();
874                         while (pos) {
875                           CFX_ByteString key;
876                           CPDF_Object* pObj =
877                               pTrailer->GetNextElement(pos, key);
878                           m_pTrailer->SetAt(key, pObj->Clone(), m_pDocument);
879                         }
880                         pObj->Release();
881                       } else {
882                         pObj->Release();
883                       }
884                     } else {
885                       if (pObj->GetType() == PDFOBJ_STREAM) {
886                         m_pTrailer = (CPDF_Dictionary*)pTrailer->Clone();
887                         pObj->Release();
888                       } else {
889                         m_pTrailer = pTrailer;
890                       }
891                       FX_FILESIZE dwSavePos = m_Syntax.SavePos();
892                       CFX_ByteString strWord = m_Syntax.GetKeyword();
893                       if (!strWord.Compare(FX_BSTRC("startxref"))) {
894                         FX_BOOL bNumber = FALSE;
895                         CFX_ByteString bsOffset = m_Syntax.GetNextWord(bNumber);
896                         if (bNumber) {
897                           m_LastXRefOffset = FXSYS_atoi(bsOffset);
898                         }
899                       }
900                       m_Syntax.RestorePos(dwSavePos);
901                     }
902                   } else {
903                     pObj->Release();
904                   }
905                 }
906               }
907             }
908             --i;
909             status = 0;
910           } else if (byte == "trailer"[inside_index]) {
911             inside_index++;
912           } else {
913             --i;
914             status = 0;
915           }
916           break;
917         case 8:
918           if (inside_index == 4) {
919             last_xref = pos + i - 4;
920             status = 1;
921           } else if (byte == "xref"[inside_index]) {
922             inside_index++;
923           } else {
924             --i;
925             status = 0;
926           }
927           break;
928         case 9:
929           if (byte == '\r' || byte == '\n') {
930             status = 0;
931           }
932           break;
933         case 10:
934           if (byte == ')') {
935             if (depth > 0) {
936               depth--;
937             }
938           } else if (byte == '(') {
939             depth++;
940           }
941           if (!depth) {
942             status = 0;
943           }
944           break;
945         case 11:
946           if (byte == '<' && inside_index == 1) {
947             status = 12;
948           } else if (byte == '>') {
949             status = 0;
950           }
951           inside_index = 0;
952           break;
953         case 12:
954           --i;
955           status = 0;
956           break;
957         case 13:
958           if (PDF_CharType[byte] == 'D' || PDF_CharType[byte] == 'W') {
959             --i;
960             status = 0;
961           }
962           break;
963         case 14:
964           if (PDF_CharType[byte] == 'W') {
965             status = 0;
966           } else if (byte == '%' || byte == '(' || byte == '<' ||
967                      byte == '\\') {
968             status = 0;
969             --i;
970           } else if (inside_index == 6) {
971             status = 0;
972             --i;
973           } else if (byte == "endobj"[inside_index]) {
974             inside_index++;
975           }
976           break;
977       }
978       if (bOverFlow) {
979         size = 0;
980         break;
981       }
982     }
983     pos += size;
984   }
985   if (last_xref != -1 && last_xref > last_obj) {
986     last_trailer = last_xref;
987   } else if (last_trailer == -1 || last_xref < last_obj) {
988     last_trailer = m_Syntax.m_FileLen;
989   }
990   FX_FILESIZE offset = last_trailer - m_Syntax.m_HeaderOffset;
991   void* pResult =
992       FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(),
993                     sizeof(FX_FILESIZE), _CompareFileSize);
994   if (pResult == NULL) {
995     m_SortedOffset.Add(offset);
996   }
997   FX_Free(buffer);
998   return TRUE;
999 }
1000 static FX_DWORD _GetVarInt(const uint8_t* p, int32_t n) {
1001   FX_DWORD result = 0;
1002   for (int32_t i = 0; i < n; i++) {
1003     result = result * 256 + p[i];
1004   }
1005   return result;
1006 }
1007 FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos,
1008                                     FX_FILESIZE& prev,
1009                                     FX_BOOL bMainXRef) {
1010   CPDF_Stream* pStream =
1011       (CPDF_Stream*)ParseIndirectObjectAt(m_pDocument, pos, 0, NULL);
1012   if (!pStream) {
1013     return FALSE;
1014   }
1015   if (m_pDocument) {
1016     CPDF_Dictionary* pDict = m_pDocument->GetRoot();
1017     if (!pDict || pDict->GetObjNum() != pStream->m_ObjNum) {
1018       m_pDocument->InsertIndirectObject(pStream->m_ObjNum, pStream);
1019     } else {
1020       if (pStream->GetType() == PDFOBJ_STREAM) {
1021         pStream->Release();
1022       }
1023       return FALSE;
1024     }
1025   }
1026   if (pStream->GetType() != PDFOBJ_STREAM) {
1027     return FALSE;
1028   }
1029   prev = pStream->GetDict()->GetInteger(FX_BSTRC("Prev"));
1030   int32_t size = pStream->GetDict()->GetInteger(FX_BSTRC("Size"));
1031   if (size < 0) {
1032     pStream->Release();
1033     return FALSE;
1034   }
1035   if (bMainXRef) {
1036     m_pTrailer = (CPDF_Dictionary*)pStream->GetDict()->Clone();
1037     m_CrossRef.SetSize(size);
1038     if (m_V5Type.SetSize(size)) {
1039       FXSYS_memset(m_V5Type.GetData(), 0, size);
1040     }
1041   } else {
1042     m_Trailers.Add((CPDF_Dictionary*)pStream->GetDict()->Clone());
1043   }
1044   std::vector<std::pair<int32_t, int32_t> > arrIndex;
1045   CPDF_Array* pArray = pStream->GetDict()->GetArray(FX_BSTRC("Index"));
1046   if (pArray) {
1047     FX_DWORD nPairSize = pArray->GetCount() / 2;
1048     for (FX_DWORD i = 0; i < nPairSize; i++) {
1049       CPDF_Object* pStartNumObj = pArray->GetElement(i * 2);
1050       CPDF_Object* pCountObj = pArray->GetElement(i * 2 + 1);
1051       if (pStartNumObj && pStartNumObj->GetType() == PDFOBJ_NUMBER &&
1052           pCountObj && pCountObj->GetType() == PDFOBJ_NUMBER) {
1053         int nStartNum = pStartNumObj->GetInteger();
1054         int nCount = pCountObj->GetInteger();
1055         if (nStartNum >= 0 && nCount > 0) {
1056           arrIndex.push_back(std::make_pair(nStartNum, nCount));
1057         }
1058       }
1059     }
1060   }
1061   if (arrIndex.size() == 0) {
1062     arrIndex.push_back(std::make_pair(0, size));
1063   }
1064   pArray = pStream->GetDict()->GetArray(FX_BSTRC("W"));
1065   if (pArray == NULL) {
1066     pStream->Release();
1067     return FALSE;
1068   }
1069   CFX_DWordArray WidthArray;
1070   FX_SAFE_DWORD dwAccWidth = 0;
1071   for (FX_DWORD i = 0; i < pArray->GetCount(); i++) {
1072     WidthArray.Add(pArray->GetInteger(i));
1073     dwAccWidth += WidthArray[i];
1074   }
1075   if (!dwAccWidth.IsValid() || WidthArray.GetSize() < 3) {
1076     pStream->Release();
1077     return FALSE;
1078   }
1079   FX_DWORD totalWidth = dwAccWidth.ValueOrDie();
1080   CPDF_StreamAcc acc;
1081   acc.LoadAllData(pStream);
1082   const uint8_t* pData = acc.GetData();
1083   FX_DWORD dwTotalSize = acc.GetSize();
1084   FX_DWORD segindex = 0;
1085   for (FX_DWORD i = 0; i < arrIndex.size(); i++) {
1086     int32_t startnum = arrIndex[i].first;
1087     if (startnum < 0) {
1088       continue;
1089     }
1090     m_dwXrefStartObjNum =
1091         pdfium::base::checked_cast<FX_DWORD, int32_t>(startnum);
1092     FX_DWORD count =
1093         pdfium::base::checked_cast<FX_DWORD, int32_t>(arrIndex[i].second);
1094     FX_SAFE_DWORD dwCaculatedSize = segindex;
1095     dwCaculatedSize += count;
1096     dwCaculatedSize *= totalWidth;
1097     if (!dwCaculatedSize.IsValid() ||
1098         dwCaculatedSize.ValueOrDie() > dwTotalSize) {
1099       continue;
1100     }
1101     const uint8_t* segstart = pData + segindex * totalWidth;
1102     FX_SAFE_DWORD dwMaxObjNum = startnum;
1103     dwMaxObjNum += count;
1104     FX_DWORD dwV5Size =
1105         pdfium::base::checked_cast<FX_DWORD, int32_t>(m_V5Type.GetSize());
1106     if (!dwMaxObjNum.IsValid() || dwMaxObjNum.ValueOrDie() > dwV5Size) {
1107       continue;
1108     }
1109     for (FX_DWORD j = 0; j < count; j++) {
1110       int32_t type = 1;
1111       const uint8_t* entrystart = segstart + j * totalWidth;
1112       if (WidthArray[0]) {
1113         type = _GetVarInt(entrystart, WidthArray[0]);
1114       }
1115       if (m_V5Type[startnum + j] == 255) {
1116         FX_FILESIZE offset =
1117             _GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
1118         m_CrossRef[startnum + j] = offset;
1119         void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(),
1120                                       m_SortedOffset.GetSize(),
1121                                       sizeof(FX_FILESIZE), _CompareFileSize);
1122         if (pResult == NULL) {
1123           m_SortedOffset.Add(offset);
1124         }
1125         continue;
1126       }
1127       if (m_V5Type[startnum + j]) {
1128         continue;
1129       }
1130       m_V5Type[startnum + j] = type;
1131       if (type == 0) {
1132         m_CrossRef[startnum + j] = 0;
1133       } else {
1134         FX_FILESIZE offset =
1135             _GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
1136         m_CrossRef[startnum + j] = offset;
1137         if (type == 1) {
1138           void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(),
1139                                         m_SortedOffset.GetSize(),
1140                                         sizeof(FX_FILESIZE), _CompareFileSize);
1141           if (pResult == NULL) {
1142             m_SortedOffset.Add(offset);
1143           }
1144         } else {
1145           if (offset < 0 || offset >= m_V5Type.GetSize()) {
1146             pStream->Release();
1147             return FALSE;
1148           }
1149           m_V5Type[offset] = 255;
1150         }
1151       }
1152     }
1153     segindex += count;
1154   }
1155   pStream->Release();
1156   return TRUE;
1157 }
1158 CPDF_Array* CPDF_Parser::GetIDArray() {
1159   CPDF_Object* pID = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("ID")) : NULL;
1160   if (pID == NULL) {
1161     return NULL;
1162   }
1163   if (pID->GetType() == PDFOBJ_REFERENCE) {
1164     pID = ParseIndirectObject(NULL, ((CPDF_Reference*)pID)->GetRefObjNum());
1165     m_pTrailer->SetAt(FX_BSTRC("ID"), pID);
1166   }
1167   if (pID == NULL || pID->GetType() != PDFOBJ_ARRAY) {
1168     return NULL;
1169   }
1170   return (CPDF_Array*)pID;
1171 }
1172 FX_DWORD CPDF_Parser::GetRootObjNum() {
1173   CPDF_Object* pRef =
1174       m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("Root")) : NULL;
1175   if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
1176     return 0;
1177   }
1178   return ((CPDF_Reference*)pRef)->GetRefObjNum();
1179 }
1180 FX_DWORD CPDF_Parser::GetInfoObjNum() {
1181   CPDF_Object* pRef =
1182       m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("Info")) : NULL;
1183   if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
1184     return 0;
1185   }
1186   return ((CPDF_Reference*)pRef)->GetRefObjNum();
1187 }
1188 FX_BOOL CPDF_Parser::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) {
1189   bForm = FALSE;
1190   if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1191     return TRUE;
1192   }
1193   if (m_V5Type[objnum] == 0) {
1194     return TRUE;
1195   }
1196   if (m_V5Type[objnum] == 2) {
1197     return TRUE;
1198   }
1199   FX_FILESIZE pos = m_CrossRef[objnum];
1200   void* pResult =
1201       FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(),
1202                     sizeof(FX_FILESIZE), _CompareFileSize);
1203   if (pResult == NULL) {
1204     return TRUE;
1205   }
1206   if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() ==
1207       m_SortedOffset.GetSize() - 1) {
1208     return FALSE;
1209   }
1210   FX_FILESIZE size = ((FX_FILESIZE*)pResult)[1] - pos;
1211   FX_FILESIZE SavedPos = m_Syntax.SavePos();
1212   m_Syntax.RestorePos(pos);
1213   bForm = m_Syntax.SearchMultiWord(FX_BSTRC("/Form\0stream"), TRUE, size) == 0;
1214   m_Syntax.RestorePos(SavedPos);
1215   return TRUE;
1216 }
1217 CPDF_Object* CPDF_Parser::ParseIndirectObject(CPDF_IndirectObjects* pObjList,
1218                                               FX_DWORD objnum,
1219                                               PARSE_CONTEXT* pContext) {
1220   if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1221     return NULL;
1222   }
1223   if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
1224     FX_FILESIZE pos = m_CrossRef[objnum];
1225     if (pos <= 0) {
1226       return NULL;
1227     }
1228     return ParseIndirectObjectAt(pObjList, pos, objnum, pContext);
1229   }
1230   if (m_V5Type[objnum] == 2) {
1231     CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
1232     if (pObjStream == NULL) {
1233       return NULL;
1234     }
1235     int32_t n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
1236     int32_t offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
1237     CPDF_SyntaxParser syntax;
1238     CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(
1239         (uint8_t*)pObjStream->GetData(), (size_t)pObjStream->GetSize(), FALSE));
1240     syntax.InitParser(file.Get(), 0);
1241     CPDF_Object* pRet = NULL;
1242     while (n) {
1243       FX_DWORD thisnum = syntax.GetDirectNum();
1244       FX_DWORD thisoff = syntax.GetDirectNum();
1245       if (thisnum == objnum) {
1246         syntax.RestorePos(offset + thisoff);
1247         pRet = syntax.GetObject(pObjList, 0, 0, pContext);
1248         break;
1249       }
1250       n--;
1251     }
1252     return pRet;
1253   }
1254   return NULL;
1255 }
1256 CPDF_StreamAcc* CPDF_Parser::GetObjectStream(FX_DWORD objnum) {
1257   CPDF_StreamAcc* pStreamAcc = NULL;
1258   if (m_ObjectStreamMap.Lookup((void*)(uintptr_t)objnum, (void*&)pStreamAcc)) {
1259     return pStreamAcc;
1260   }
1261   const CPDF_Stream* pStream =
1262       m_pDocument ? (CPDF_Stream*)m_pDocument->GetIndirectObject(objnum) : NULL;
1263   if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) {
1264     return NULL;
1265   }
1266   pStreamAcc = new CPDF_StreamAcc;
1267   pStreamAcc->LoadAllData(pStream);
1268   m_ObjectStreamMap.SetAt((void*)(uintptr_t)objnum, pStreamAcc);
1269   return pStreamAcc;
1270 }
1271 FX_FILESIZE CPDF_Parser::GetObjectSize(FX_DWORD objnum) {
1272   if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1273     return 0;
1274   }
1275   if (m_V5Type[objnum] == 2) {
1276     objnum = (FX_DWORD)m_CrossRef[objnum];
1277   }
1278   if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
1279     FX_FILESIZE offset = m_CrossRef[objnum];
1280     if (offset == 0) {
1281       return 0;
1282     }
1283     void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(),
1284                                   m_SortedOffset.GetSize(), sizeof(FX_FILESIZE),
1285                                   _CompareFileSize);
1286     if (pResult == NULL) {
1287       return 0;
1288     }
1289     if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() ==
1290         m_SortedOffset.GetSize() - 1) {
1291       return 0;
1292     }
1293     return ((FX_FILESIZE*)pResult)[1] - offset;
1294   }
1295   return 0;
1296 }
1297 void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum,
1298                                     uint8_t*& pBuffer,
1299                                     FX_DWORD& size) {
1300   pBuffer = NULL;
1301   size = 0;
1302   if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1303     return;
1304   }
1305   if (m_V5Type[objnum] == 2) {
1306     CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
1307     if (pObjStream == NULL) {
1308       return;
1309     }
1310     int32_t n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
1311     int32_t offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
1312     CPDF_SyntaxParser syntax;
1313     const uint8_t* pData = pObjStream->GetData();
1314     FX_DWORD totalsize = pObjStream->GetSize();
1315     CFX_SmartPointer<IFX_FileStream> file(
1316         FX_CreateMemoryStream((uint8_t*)pData, (size_t)totalsize, FALSE));
1317     syntax.InitParser(file.Get(), 0);
1318     while (n) {
1319       FX_DWORD thisnum = syntax.GetDirectNum();
1320       FX_DWORD thisoff = syntax.GetDirectNum();
1321       if (thisnum == objnum) {
1322         if (n == 1) {
1323           size = totalsize - (thisoff + offset);
1324         } else {
1325           syntax.GetDirectNum();  // Skip nextnum.
1326           FX_DWORD nextoff = syntax.GetDirectNum();
1327           size = nextoff - thisoff;
1328         }
1329         pBuffer = FX_Alloc(uint8_t, size);
1330         FXSYS_memcpy(pBuffer, pData + thisoff + offset, size);
1331         return;
1332       }
1333       n--;
1334     }
1335     return;
1336   }
1337   if (m_V5Type[objnum] == 1) {
1338     FX_FILESIZE pos = m_CrossRef[objnum];
1339     if (pos == 0) {
1340       return;
1341     }
1342     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1343     m_Syntax.RestorePos(pos);
1344     FX_BOOL bIsNumber;
1345     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1346     if (!bIsNumber) {
1347       m_Syntax.RestorePos(SavedPos);
1348       return;
1349     }
1350     FX_DWORD parser_objnum = FXSYS_atoi(word);
1351     if (parser_objnum && parser_objnum != objnum) {
1352       m_Syntax.RestorePos(SavedPos);
1353       return;
1354     }
1355     word = m_Syntax.GetNextWord(bIsNumber);
1356     if (!bIsNumber) {
1357       m_Syntax.RestorePos(SavedPos);
1358       return;
1359     }
1360     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1361       m_Syntax.RestorePos(SavedPos);
1362       return;
1363     }
1364     void* pResult =
1365         FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(),
1366                       sizeof(FX_FILESIZE), _CompareFileSize);
1367     if (pResult == NULL) {
1368       m_Syntax.RestorePos(SavedPos);
1369       return;
1370     }
1371     FX_FILESIZE nextoff = ((FX_FILESIZE*)pResult)[1];
1372     FX_BOOL bNextOffValid = FALSE;
1373     if (nextoff != pos) {
1374       m_Syntax.RestorePos(nextoff);
1375       word = m_Syntax.GetNextWord(bIsNumber);
1376       if (word == FX_BSTRC("xref")) {
1377         bNextOffValid = TRUE;
1378       } else if (bIsNumber) {
1379         word = m_Syntax.GetNextWord(bIsNumber);
1380         if (bIsNumber && m_Syntax.GetKeyword() == FX_BSTRC("obj")) {
1381           bNextOffValid = TRUE;
1382         }
1383       }
1384     }
1385     if (!bNextOffValid) {
1386       m_Syntax.RestorePos(pos);
1387       while (1) {
1388         if (m_Syntax.GetKeyword() == FX_BSTRC("endobj")) {
1389           break;
1390         }
1391         if (m_Syntax.SavePos() == m_Syntax.m_FileLen) {
1392           break;
1393         }
1394       }
1395       nextoff = m_Syntax.SavePos();
1396     }
1397     size = (FX_DWORD)(nextoff - pos);
1398     pBuffer = FX_Alloc(uint8_t, size);
1399     m_Syntax.RestorePos(pos);
1400     m_Syntax.ReadBlock(pBuffer, size);
1401     m_Syntax.RestorePos(SavedPos);
1402   }
1403 }
1404 CPDF_Object* CPDF_Parser::ParseIndirectObjectAt(CPDF_IndirectObjects* pObjList,
1405                                                 FX_FILESIZE pos,
1406                                                 FX_DWORD objnum,
1407                                                 PARSE_CONTEXT* pContext) {
1408   FX_FILESIZE SavedPos = m_Syntax.SavePos();
1409   m_Syntax.RestorePos(pos);
1410   FX_BOOL bIsNumber;
1411   CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1412   if (!bIsNumber) {
1413     m_Syntax.RestorePos(SavedPos);
1414     return NULL;
1415   }
1416   FX_FILESIZE objOffset = m_Syntax.SavePos();
1417   objOffset -= word.GetLength();
1418   FX_DWORD parser_objnum = FXSYS_atoi(word);
1419   if (objnum && parser_objnum != objnum) {
1420     m_Syntax.RestorePos(SavedPos);
1421     return NULL;
1422   }
1423   word = m_Syntax.GetNextWord(bIsNumber);
1424   if (!bIsNumber) {
1425     m_Syntax.RestorePos(SavedPos);
1426     return NULL;
1427   }
1428   FX_DWORD parser_gennum = FXSYS_atoi(word);
1429   if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1430     m_Syntax.RestorePos(SavedPos);
1431     return NULL;
1432   }
1433   CPDF_Object* pObj =
1434       m_Syntax.GetObject(pObjList, objnum, parser_gennum, pContext);
1435   m_Syntax.SavePos();
1436   CFX_ByteString bsWord = m_Syntax.GetKeyword();
1437   if (bsWord == FX_BSTRC("endobj")) {
1438     m_Syntax.SavePos();
1439   }
1440   m_Syntax.RestorePos(SavedPos);
1441   if (pObj) {
1442     if (!objnum) {
1443       pObj->m_ObjNum = parser_objnum;
1444     }
1445     pObj->m_GenNum = parser_gennum;
1446   }
1447   return pObj;
1448 }
1449 CPDF_Object* CPDF_Parser::ParseIndirectObjectAtByStrict(
1450     CPDF_IndirectObjects* pObjList,
1451     FX_FILESIZE pos,
1452     FX_DWORD objnum,
1453     struct PARSE_CONTEXT* pContext,
1454     FX_FILESIZE* pResultPos) {
1455   FX_FILESIZE SavedPos = m_Syntax.SavePos();
1456   m_Syntax.RestorePos(pos);
1457   FX_BOOL bIsNumber;
1458   CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1459   if (!bIsNumber) {
1460     m_Syntax.RestorePos(SavedPos);
1461     return NULL;
1462   }
1463   FX_DWORD parser_objnum = FXSYS_atoi(word);
1464   if (objnum && parser_objnum != objnum) {
1465     m_Syntax.RestorePos(SavedPos);
1466     return NULL;
1467   }
1468   word = m_Syntax.GetNextWord(bIsNumber);
1469   if (!bIsNumber) {
1470     m_Syntax.RestorePos(SavedPos);
1471     return NULL;
1472   }
1473   FX_DWORD gennum = FXSYS_atoi(word);
1474   if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1475     m_Syntax.RestorePos(SavedPos);
1476     return NULL;
1477   }
1478   CPDF_Object* pObj =
1479       m_Syntax.GetObjectByStrict(pObjList, objnum, gennum, pContext);
1480   if (pResultPos) {
1481     *pResultPos = m_Syntax.m_Pos;
1482   }
1483   m_Syntax.RestorePos(SavedPos);
1484   return pObj;
1485 }
1486 CPDF_Dictionary* CPDF_Parser::LoadTrailerV4() {
1487   if (m_Syntax.GetKeyword() != FX_BSTRC("trailer")) {
1488     return NULL;
1489   }
1490   CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0);
1491   if (pObj == NULL || pObj->GetType() != PDFOBJ_DICTIONARY) {
1492     if (pObj) {
1493       pObj->Release();
1494     }
1495     return NULL;
1496   }
1497   return (CPDF_Dictionary*)pObj;
1498 }
1499 FX_DWORD CPDF_Parser::GetPermissions(FX_BOOL bCheckRevision) {
1500   if (m_pSecurityHandler == NULL) {
1501     return (FX_DWORD)-1;
1502   }
1503   FX_DWORD dwPermission = m_pSecurityHandler->GetPermissions();
1504   if (m_pEncryptDict &&
1505       m_pEncryptDict->GetString(FX_BSTRC("Filter")) == FX_BSTRC("Standard")) {
1506     dwPermission &= 0xFFFFFFFC;
1507     dwPermission |= 0xFFFFF0C0;
1508     if (bCheckRevision && m_pEncryptDict->GetInteger(FX_BSTRC("R")) == 2) {
1509       dwPermission &= 0xFFFFF0FF;
1510     }
1511   }
1512   return dwPermission;
1513 }
1514 FX_BOOL CPDF_Parser::IsOwner() {
1515   return m_pSecurityHandler == NULL ? TRUE : m_pSecurityHandler->IsOwner();
1516 }
1517 void CPDF_Parser::SetSecurityHandler(CPDF_SecurityHandler* pSecurityHandler,
1518                                      FX_BOOL bForced) {
1519   ASSERT(m_pSecurityHandler == NULL);
1520   if (!m_bForceUseSecurityHandler) {
1521     delete m_pSecurityHandler;
1522     m_pSecurityHandler = NULL;
1523   }
1524   m_bForceUseSecurityHandler = bForced;
1525   m_pSecurityHandler = pSecurityHandler;
1526   if (m_bForceUseSecurityHandler) {
1527     return;
1528   }
1529   m_Syntax.m_pCryptoHandler = pSecurityHandler->CreateCryptoHandler();
1530   m_Syntax.m_pCryptoHandler->Init(NULL, pSecurityHandler);
1531 }
1532 FX_BOOL CPDF_Parser::IsLinearizedFile(IFX_FileRead* pFileAccess,
1533                                       FX_DWORD offset) {
1534   m_Syntax.InitParser(pFileAccess, offset);
1535   m_Syntax.RestorePos(m_Syntax.m_HeaderOffset + 9);
1536   FX_FILESIZE SavedPos = m_Syntax.SavePos();
1537   FX_BOOL bIsNumber;
1538   CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1539   if (!bIsNumber) {
1540     return FALSE;
1541   }
1542   FX_DWORD objnum = FXSYS_atoi(word);
1543   word = m_Syntax.GetNextWord(bIsNumber);
1544   if (!bIsNumber) {
1545     return FALSE;
1546   }
1547   FX_DWORD gennum = FXSYS_atoi(word);
1548   if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1549     m_Syntax.RestorePos(SavedPos);
1550     return FALSE;
1551   }
1552   m_pLinearized = m_Syntax.GetObject(NULL, objnum, gennum, 0);
1553   if (!m_pLinearized) {
1554     return FALSE;
1555   }
1556   if (m_pLinearized->GetDict() &&
1557       m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) {
1558     m_Syntax.GetNextWord(bIsNumber);
1559     CPDF_Object* pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L"));
1560     if (!pLen) {
1561       m_pLinearized->Release();
1562       m_pLinearized = NULL;
1563       return FALSE;
1564     }
1565     if (pLen->GetInteger() != (int)pFileAccess->GetSize()) {
1566       return FALSE;
1567     }
1568     CPDF_Object* pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P"));
1569     if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {
1570       m_dwFirstPageNo = pNo->GetInteger();
1571     }
1572     CPDF_Object* pTable = m_pLinearized->GetDict()->GetElement(FX_BSTRC("T"));
1573     if (pTable && pTable->GetType() == PDFOBJ_NUMBER) {
1574       m_LastXRefOffset = pTable->GetInteger();
1575     }
1576     return TRUE;
1577   }
1578   m_pLinearized->Release();
1579   m_pLinearized = NULL;
1580   return FALSE;
1581 }
1582 FX_DWORD CPDF_Parser::StartAsynParse(IFX_FileRead* pFileAccess,
1583                                      FX_BOOL bReParse,
1584                                      FX_BOOL bOwnFileRead) {
1585   CloseParser(bReParse);
1586   m_bXRefStream = FALSE;
1587   m_LastXRefOffset = 0;
1588   m_bOwnFileRead = bOwnFileRead;
1589   int32_t offset = GetHeaderOffset(pFileAccess);
1590   if (offset == -1) {
1591     return PDFPARSE_ERROR_FORMAT;
1592   }
1593   if (!IsLinearizedFile(pFileAccess, offset)) {
1594     m_Syntax.m_pFileAccess = NULL;
1595     return StartParse(pFileAccess, bReParse, bOwnFileRead);
1596   }
1597   if (!bReParse) {
1598     m_pDocument = new CPDF_Document(this);
1599   }
1600   FX_FILESIZE dwFirstXRefOffset = m_Syntax.SavePos();
1601   FX_BOOL bXRefRebuilt = FALSE;
1602   FX_BOOL bLoadV4 = FALSE;
1603   if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE, FALSE)) &&
1604       !LoadCrossRefV5(dwFirstXRefOffset, dwFirstXRefOffset, TRUE)) {
1605     if (!RebuildCrossRef()) {
1606       return PDFPARSE_ERROR_FORMAT;
1607     }
1608     bXRefRebuilt = TRUE;
1609     m_LastXRefOffset = 0;
1610   }
1611   if (bLoadV4) {
1612     m_pTrailer = LoadTrailerV4();
1613     if (m_pTrailer == NULL) {
1614       return FALSE;
1615     }
1616     int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
1617     if (xrefsize > 0) {
1618       m_CrossRef.SetSize(xrefsize);
1619       m_V5Type.SetSize(xrefsize);
1620     }
1621   }
1622   FX_DWORD dwRet = SetEncryptHandler();
1623   if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1624     return dwRet;
1625   }
1626   m_pDocument->LoadAsynDoc(m_pLinearized->GetDict());
1627   if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) {
1628     if (bXRefRebuilt) {
1629       return PDFPARSE_ERROR_FORMAT;
1630     }
1631     ReleaseEncryptHandler();
1632     if (!RebuildCrossRef()) {
1633       return PDFPARSE_ERROR_FORMAT;
1634     }
1635     dwRet = SetEncryptHandler();
1636     if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1637       return dwRet;
1638     }
1639     m_pDocument->LoadAsynDoc(m_pLinearized->GetDict());
1640     if (m_pDocument->GetRoot() == NULL) {
1641       return PDFPARSE_ERROR_FORMAT;
1642     }
1643   }
1644   FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(),
1645               sizeof(FX_FILESIZE), _CompareFileSize);
1646   FX_DWORD RootObjNum = GetRootObjNum();
1647   if (RootObjNum == 0) {
1648     ReleaseEncryptHandler();
1649     RebuildCrossRef();
1650     RootObjNum = GetRootObjNum();
1651     if (RootObjNum == 0) {
1652       return PDFPARSE_ERROR_FORMAT;
1653     }
1654     dwRet = SetEncryptHandler();
1655     if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1656       return dwRet;
1657     }
1658   }
1659   if (m_pSecurityHandler && m_pSecurityHandler->IsMetadataEncrypted()) {
1660     CPDF_Object* pMetadata =
1661         m_pDocument->GetRoot()->GetElement(FX_BSTRC("Metadata"));
1662     if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) {
1663       m_Syntax.m_MetadataObjnum = ((CPDF_Reference*)pMetadata)->GetRefObjNum();
1664     }
1665   }
1666   return PDFPARSE_ERROR_SUCCESS;
1667 }
1668 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos) {
1669   if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
1670     return FALSE;
1671   }
1672   while (xrefpos)
1673     if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
1674       return FALSE;
1675     }
1676   m_ObjectStreamMap.InitHashTable(101, FALSE);
1677   m_bXRefStream = TRUE;
1678   return TRUE;
1679 }
1680 FX_DWORD CPDF_Parser::LoadLinearizedMainXRefTable() {
1681   FX_DWORD dwSaveMetadataObjnum = m_Syntax.m_MetadataObjnum;
1682   m_Syntax.m_MetadataObjnum = 0;
1683   if (m_pTrailer) {
1684     m_pTrailer->Release();
1685     m_pTrailer = NULL;
1686   }
1687   m_Syntax.RestorePos(m_LastXRefOffset - m_Syntax.m_HeaderOffset);
1688   uint8_t ch = 0;
1689   FX_DWORD dwCount = 0;
1690   m_Syntax.GetNextChar(ch);
1691   int32_t type = PDF_CharType[ch];
1692   while (type == 'W') {
1693     ++dwCount;
1694     if (m_Syntax.m_FileLen >=
1695         (FX_FILESIZE)(m_Syntax.SavePos() + m_Syntax.m_HeaderOffset)) {
1696       break;
1697     }
1698     m_Syntax.GetNextChar(ch);
1699     type = PDF_CharType[ch];
1700   }
1701   m_LastXRefOffset += dwCount;
1702   FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
1703   while (pos) {
1704     void* objnum;
1705     CPDF_StreamAcc* pStream;
1706     m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream);
1707     delete pStream;
1708   }
1709   m_ObjectStreamMap.RemoveAll();
1710   if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) &&
1711       !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) {
1712     m_LastXRefOffset = 0;
1713     m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum;
1714     return PDFPARSE_ERROR_FORMAT;
1715   }
1716   FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(),
1717               sizeof(FX_FILESIZE), _CompareFileSize);
1718   m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum;
1719   return PDFPARSE_ERROR_SUCCESS;
1720 }
1721
1722 // static
1723 int CPDF_SyntaxParser::s_CurrentRecursionDepth = 0;
1724
1725 CPDF_SyntaxParser::CPDF_SyntaxParser() {
1726   m_pFileAccess = NULL;
1727   m_pCryptoHandler = NULL;
1728   m_pFileBuf = NULL;
1729   m_BufSize = CPDF_ModuleMgr::kFileBufSize;
1730   m_pFileBuf = NULL;
1731   m_MetadataObjnum = 0;
1732   m_dwWordPos = 0;
1733   m_bFileStream = FALSE;
1734 }
1735 CPDF_SyntaxParser::~CPDF_SyntaxParser() {
1736   FX_Free(m_pFileBuf);
1737 }
1738 FX_BOOL CPDF_SyntaxParser::GetCharAt(FX_FILESIZE pos, uint8_t& ch) {
1739   FX_FILESIZE save_pos = m_Pos;
1740   m_Pos = pos;
1741   FX_BOOL ret = GetNextChar(ch);
1742   m_Pos = save_pos;
1743   return ret;
1744 }
1745 FX_BOOL CPDF_SyntaxParser::GetNextChar(uint8_t& ch) {
1746   FX_FILESIZE pos = m_Pos + m_HeaderOffset;
1747   if (pos >= m_FileLen) {
1748     return FALSE;
1749   }
1750   if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) {
1751     FX_FILESIZE read_pos = pos;
1752     FX_DWORD read_size = m_BufSize;
1753     if ((FX_FILESIZE)read_size > m_FileLen) {
1754       read_size = (FX_DWORD)m_FileLen;
1755     }
1756     if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) {
1757       if (m_FileLen < (FX_FILESIZE)read_size) {
1758         read_pos = 0;
1759         read_size = (FX_DWORD)m_FileLen;
1760       } else {
1761         read_pos = m_FileLen - read_size;
1762       }
1763     }
1764     if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) {
1765       return FALSE;
1766     }
1767     m_BufOffset = read_pos;
1768   }
1769   ch = m_pFileBuf[pos - m_BufOffset];
1770   m_Pos++;
1771   return TRUE;
1772 }
1773 FX_BOOL CPDF_SyntaxParser::GetCharAtBackward(FX_FILESIZE pos, uint8_t& ch) {
1774   pos += m_HeaderOffset;
1775   if (pos >= m_FileLen) {
1776     return FALSE;
1777   }
1778   if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) {
1779     FX_FILESIZE read_pos;
1780     if (pos < (FX_FILESIZE)m_BufSize) {
1781       read_pos = 0;
1782     } else {
1783       read_pos = pos - m_BufSize + 1;
1784     }
1785     FX_DWORD read_size = m_BufSize;
1786     if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) {
1787       if (m_FileLen < (FX_FILESIZE)read_size) {
1788         read_pos = 0;
1789         read_size = (FX_DWORD)m_FileLen;
1790       } else {
1791         read_pos = m_FileLen - read_size;
1792       }
1793     }
1794     if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) {
1795       return FALSE;
1796     }
1797     m_BufOffset = read_pos;
1798   }
1799   ch = m_pFileBuf[pos - m_BufOffset];
1800   return TRUE;
1801 }
1802 FX_BOOL CPDF_SyntaxParser::ReadBlock(uint8_t* pBuf, FX_DWORD size) {
1803   if (!m_pFileAccess->ReadBlock(pBuf, m_Pos + m_HeaderOffset, size)) {
1804     return FALSE;
1805   }
1806   m_Pos += size;
1807   return TRUE;
1808 }
1809 #define MAX_WORD_BUFFER 256
1810 void CPDF_SyntaxParser::GetNextWord() {
1811   m_WordSize = 0;
1812   m_bIsNumber = TRUE;
1813   uint8_t ch;
1814   if (!GetNextChar(ch)) {
1815     return;
1816   }
1817   uint8_t type = PDF_CharType[ch];
1818   while (1) {
1819     while (type == 'W') {
1820       if (!GetNextChar(ch)) {
1821         return;
1822       }
1823       type = PDF_CharType[ch];
1824     }
1825     if (ch != '%') {
1826       break;
1827     }
1828     while (1) {
1829       if (!GetNextChar(ch)) {
1830         return;
1831       }
1832       if (ch == '\r' || ch == '\n') {
1833         break;
1834       }
1835     }
1836     type = PDF_CharType[ch];
1837   }
1838   if (type == 'D') {
1839     m_bIsNumber = FALSE;
1840     m_WordBuffer[m_WordSize++] = ch;
1841     if (ch == '/') {
1842       while (1) {
1843         if (!GetNextChar(ch)) {
1844           return;
1845         }
1846         type = PDF_CharType[ch];
1847         if (type != 'R' && type != 'N') {
1848           m_Pos--;
1849           return;
1850         }
1851         if (m_WordSize < MAX_WORD_BUFFER) {
1852           m_WordBuffer[m_WordSize++] = ch;
1853         }
1854       }
1855     } else if (ch == '<') {
1856       if (!GetNextChar(ch)) {
1857         return;
1858       }
1859       if (ch == '<') {
1860         m_WordBuffer[m_WordSize++] = ch;
1861       } else {
1862         m_Pos--;
1863       }
1864     } else if (ch == '>') {
1865       if (!GetNextChar(ch)) {
1866         return;
1867       }
1868       if (ch == '>') {
1869         m_WordBuffer[m_WordSize++] = ch;
1870       } else {
1871         m_Pos--;
1872       }
1873     }
1874     return;
1875   }
1876   while (1) {
1877     if (m_WordSize < MAX_WORD_BUFFER) {
1878       m_WordBuffer[m_WordSize++] = ch;
1879     }
1880     if (type != 'N') {
1881       m_bIsNumber = FALSE;
1882     }
1883     if (!GetNextChar(ch)) {
1884       return;
1885     }
1886     type = PDF_CharType[ch];
1887     if (type == 'D' || type == 'W') {
1888       m_Pos--;
1889       break;
1890     }
1891   }
1892 }
1893 CFX_ByteString CPDF_SyntaxParser::ReadString() {
1894   uint8_t ch;
1895   if (!GetNextChar(ch)) {
1896     return CFX_ByteString();
1897   }
1898   CFX_ByteTextBuf buf;
1899   int32_t parlevel = 0;
1900   int32_t status = 0, iEscCode = 0;
1901   while (1) {
1902     switch (status) {
1903       case 0:
1904         if (ch == ')') {
1905           if (parlevel == 0) {
1906             return buf.GetByteString();
1907           }
1908           parlevel--;
1909           buf.AppendChar(')');
1910         } else if (ch == '(') {
1911           parlevel++;
1912           buf.AppendChar('(');
1913         } else if (ch == '\\') {
1914           status = 1;
1915         } else {
1916           buf.AppendChar(ch);
1917         }
1918         break;
1919       case 1:
1920         if (ch >= '0' && ch <= '7') {
1921           iEscCode = ch - '0';
1922           status = 2;
1923           break;
1924         }
1925         if (ch == 'n') {
1926           buf.AppendChar('\n');
1927         } else if (ch == 'r') {
1928           buf.AppendChar('\r');
1929         } else if (ch == 't') {
1930           buf.AppendChar('\t');
1931         } else if (ch == 'b') {
1932           buf.AppendChar('\b');
1933         } else if (ch == 'f') {
1934           buf.AppendChar('\f');
1935         } else if (ch == '\r') {
1936           status = 4;
1937           break;
1938         } else if (ch == '\n') {
1939         } else {
1940           buf.AppendChar(ch);
1941         }
1942         status = 0;
1943         break;
1944       case 2:
1945         if (ch >= '0' && ch <= '7') {
1946           iEscCode = iEscCode * 8 + ch - '0';
1947           status = 3;
1948         } else {
1949           buf.AppendChar(iEscCode);
1950           status = 0;
1951           continue;
1952         }
1953         break;
1954       case 3:
1955         if (ch >= '0' && ch <= '7') {
1956           iEscCode = iEscCode * 8 + ch - '0';
1957           buf.AppendChar(iEscCode);
1958           status = 0;
1959         } else {
1960           buf.AppendChar(iEscCode);
1961           status = 0;
1962           continue;
1963         }
1964         break;
1965       case 4:
1966         status = 0;
1967         if (ch != '\n') {
1968           continue;
1969         }
1970         break;
1971     }
1972     if (!GetNextChar(ch)) {
1973       break;
1974     }
1975   }
1976   GetNextChar(ch);
1977   return buf.GetByteString();
1978 }
1979 CFX_ByteString CPDF_SyntaxParser::ReadHexString() {
1980   uint8_t ch;
1981   if (!GetNextChar(ch)) {
1982     return CFX_ByteString();
1983   }
1984   CFX_BinaryBuf buf;
1985   FX_BOOL bFirst = TRUE;
1986   uint8_t code = 0;
1987   while (1) {
1988     if (ch == '>') {
1989       break;
1990     }
1991     if (ch >= '0' && ch <= '9') {
1992       if (bFirst) {
1993         code = (ch - '0') * 16;
1994       } else {
1995         code += ch - '0';
1996         buf.AppendByte((uint8_t)code);
1997       }
1998       bFirst = !bFirst;
1999     } else if (ch >= 'A' && ch <= 'F') {
2000       if (bFirst) {
2001         code = (ch - 'A' + 10) * 16;
2002       } else {
2003         code += ch - 'A' + 10;
2004         buf.AppendByte((uint8_t)code);
2005       }
2006       bFirst = !bFirst;
2007     } else if (ch >= 'a' && ch <= 'f') {
2008       if (bFirst) {
2009         code = (ch - 'a' + 10) * 16;
2010       } else {
2011         code += ch - 'a' + 10;
2012         buf.AppendByte((uint8_t)code);
2013       }
2014       bFirst = !bFirst;
2015     }
2016     if (!GetNextChar(ch)) {
2017       break;
2018     }
2019   }
2020   if (!bFirst) {
2021     buf.AppendByte((uint8_t)code);
2022   }
2023   return buf.GetByteString();
2024 }
2025 void CPDF_SyntaxParser::ToNextLine() {
2026   uint8_t ch;
2027   while (GetNextChar(ch)) {
2028     if (ch == '\n') {
2029       break;
2030     }
2031     if (ch == '\r') {
2032       GetNextChar(ch);
2033       if (ch != '\n') {
2034         --m_Pos;
2035       }
2036       break;
2037     }
2038   }
2039 }
2040 void CPDF_SyntaxParser::ToNextWord() {
2041   uint8_t ch;
2042   if (!GetNextChar(ch)) {
2043     return;
2044   }
2045   uint8_t type = PDF_CharType[ch];
2046   while (1) {
2047     while (type == 'W') {
2048       m_dwWordPos = m_Pos;
2049       if (!GetNextChar(ch)) {
2050         return;
2051       }
2052       type = PDF_CharType[ch];
2053     }
2054     if (ch != '%') {
2055       break;
2056     }
2057     while (1) {
2058       if (!GetNextChar(ch)) {
2059         return;
2060       }
2061       if (ch == '\r' || ch == '\n') {
2062         break;
2063       }
2064     }
2065     type = PDF_CharType[ch];
2066   }
2067   m_Pos--;
2068 }
2069 CFX_ByteString CPDF_SyntaxParser::GetNextWord(FX_BOOL& bIsNumber) {
2070   GetNextWord();
2071   bIsNumber = m_bIsNumber;
2072   return CFX_ByteString((const FX_CHAR*)m_WordBuffer, m_WordSize);
2073 }
2074 CFX_ByteString CPDF_SyntaxParser::GetKeyword() {
2075   GetNextWord();
2076   return CFX_ByteString((const FX_CHAR*)m_WordBuffer, m_WordSize);
2077 }
2078 CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList,
2079                                           FX_DWORD objnum,
2080                                           FX_DWORD gennum,
2081                                           PARSE_CONTEXT* pContext,
2082                                           FX_BOOL bDecrypt) {
2083   CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth);
2084   if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) {
2085     return NULL;
2086   }
2087   FX_FILESIZE SavedPos = m_Pos;
2088   FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY);
2089   FX_BOOL bIsNumber;
2090   CFX_ByteString word = GetNextWord(bIsNumber);
2091   if (word.GetLength() == 0) {
2092     if (bTypeOnly) {
2093       return (CPDF_Object*)PDFOBJ_INVALID;
2094     }
2095     return NULL;
2096   }
2097   if (bIsNumber) {
2098     FX_FILESIZE SavedPos = m_Pos;
2099     CFX_ByteString nextword = GetNextWord(bIsNumber);
2100     if (bIsNumber) {
2101       CFX_ByteString nextword2 = GetNextWord(bIsNumber);
2102       if (nextword2 == FX_BSTRC("R")) {
2103         FX_DWORD objnum = FXSYS_atoi(word);
2104         if (bTypeOnly) {
2105           return (CPDF_Object*)PDFOBJ_REFERENCE;
2106         }
2107         return new CPDF_Reference(pObjList, objnum);
2108       }
2109     }
2110     m_Pos = SavedPos;
2111     if (bTypeOnly) {
2112       return (CPDF_Object*)PDFOBJ_NUMBER;
2113     }
2114     return CPDF_Number::Create(word);
2115   }
2116   if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
2117     if (bTypeOnly) {
2118       return (CPDF_Object*)PDFOBJ_BOOLEAN;
2119     }
2120     return CPDF_Boolean::Create(word == FX_BSTRC("true"));
2121   }
2122   if (word == FX_BSTRC("null")) {
2123     if (bTypeOnly) {
2124       return (CPDF_Object*)PDFOBJ_NULL;
2125     }
2126     return CPDF_Null::Create();
2127   }
2128   if (word == FX_BSTRC("(")) {
2129     if (bTypeOnly) {
2130       return (CPDF_Object*)PDFOBJ_STRING;
2131     }
2132     CFX_ByteString str = ReadString();
2133     if (m_pCryptoHandler && bDecrypt) {
2134       m_pCryptoHandler->Decrypt(objnum, gennum, str);
2135     }
2136     return CPDF_String::Create(str, FALSE);
2137   }
2138   if (word == FX_BSTRC("<")) {
2139     if (bTypeOnly) {
2140       return (CPDF_Object*)PDFOBJ_STRING;
2141     }
2142     CFX_ByteString str = ReadHexString();
2143     if (m_pCryptoHandler && bDecrypt) {
2144       m_pCryptoHandler->Decrypt(objnum, gennum, str);
2145     }
2146     return CPDF_String::Create(str, TRUE);
2147   }
2148   if (word == FX_BSTRC("[")) {
2149     if (bTypeOnly) {
2150       return (CPDF_Object*)PDFOBJ_ARRAY;
2151     }
2152     CPDF_Array* pArray = CPDF_Array::Create();
2153     while (1) {
2154       CPDF_Object* pObj = GetObject(pObjList, objnum, gennum);
2155       if (pObj == NULL) {
2156         return pArray;
2157       }
2158       pArray->Add(pObj);
2159     }
2160   }
2161   if (word[0] == '/') {
2162     if (bTypeOnly) {
2163       return (CPDF_Object*)PDFOBJ_NAME;
2164     }
2165     return CPDF_Name::Create(
2166         PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
2167   }
2168   if (word == FX_BSTRC("<<")) {
2169     if (bTypeOnly) {
2170       return (CPDF_Object*)PDFOBJ_DICTIONARY;
2171     }
2172     if (pContext) {
2173       pContext->m_DictStart = SavedPos;
2174     }
2175     CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
2176     int32_t nKeys = 0;
2177     FX_FILESIZE dwSignValuePos = 0;
2178     while (1) {
2179       FX_BOOL bIsNumber;
2180       CFX_ByteString key = GetNextWord(bIsNumber);
2181       if (key.IsEmpty()) {
2182         if (pDict)
2183           pDict->Release();
2184         return NULL;
2185       }
2186       FX_FILESIZE SavedPos = m_Pos - key.GetLength();
2187       if (key == FX_BSTRC(">>")) {
2188         break;
2189       }
2190       if (key == FX_BSTRC("endobj")) {
2191         m_Pos = SavedPos;
2192         break;
2193       }
2194       if (key[0] != '/') {
2195         continue;
2196       }
2197       nKeys++;
2198       key = PDF_NameDecode(key);
2199       if (key == FX_BSTRC("/Contents")) {
2200         dwSignValuePos = m_Pos;
2201       }
2202       CPDF_Object* pObj = GetObject(pObjList, objnum, gennum);
2203       if (pObj == NULL) {
2204         continue;
2205       }
2206       if (key.GetLength() >= 1) {
2207         if (nKeys < 32) {
2208           pDict->SetAt(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1),
2209                        pObj);
2210         } else {
2211           pDict->AddValue(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1),
2212                           pObj);
2213         }
2214       }
2215     }
2216     if (IsSignatureDict(pDict)) {
2217       FX_FILESIZE dwSavePos = m_Pos;
2218       m_Pos = dwSignValuePos;
2219       CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, NULL, FALSE);
2220       pDict->SetAt(FX_BSTRC("Contents"), pObj);
2221       m_Pos = dwSavePos;
2222     }
2223     if (pContext) {
2224       pContext->m_DictEnd = m_Pos;
2225       if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
2226         return pDict;
2227       }
2228     }
2229     FX_FILESIZE SavedPos = m_Pos;
2230     FX_BOOL bIsNumber;
2231     CFX_ByteString nextword = GetNextWord(bIsNumber);
2232     if (nextword == FX_BSTRC("stream")) {
2233       CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum);
2234       if (pStream) {
2235         return pStream;
2236       }
2237       if (pDict)
2238         pDict->Release();
2239       return NULL;
2240     } else {
2241       m_Pos = SavedPos;
2242       return pDict;
2243     }
2244   }
2245   if (word == FX_BSTRC(">>")) {
2246     m_Pos = SavedPos;
2247     return NULL;
2248   }
2249   if (bTypeOnly) {
2250     return (CPDF_Object*)PDFOBJ_INVALID;
2251   }
2252   return NULL;
2253 }
2254 CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(
2255     CPDF_IndirectObjects* pObjList,
2256     FX_DWORD objnum,
2257     FX_DWORD gennum,
2258     struct PARSE_CONTEXT* pContext) {
2259   CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth);
2260   if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) {
2261     return NULL;
2262   }
2263   FX_FILESIZE SavedPos = m_Pos;
2264   FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY);
2265   FX_BOOL bIsNumber;
2266   CFX_ByteString word = GetNextWord(bIsNumber);
2267   if (word.GetLength() == 0) {
2268     if (bTypeOnly) {
2269       return (CPDF_Object*)PDFOBJ_INVALID;
2270     }
2271     return NULL;
2272   }
2273   if (bIsNumber) {
2274     FX_FILESIZE SavedPos = m_Pos;
2275     CFX_ByteString nextword = GetNextWord(bIsNumber);
2276     if (bIsNumber) {
2277       CFX_ByteString nextword2 = GetNextWord(bIsNumber);
2278       if (nextword2 == FX_BSTRC("R")) {
2279         if (bTypeOnly) {
2280           return (CPDF_Object*)PDFOBJ_REFERENCE;
2281         }
2282         FX_DWORD objnum = FXSYS_atoi(word);
2283         return new CPDF_Reference(pObjList, objnum);
2284       }
2285     }
2286     m_Pos = SavedPos;
2287     if (bTypeOnly) {
2288       return (CPDF_Object*)PDFOBJ_NUMBER;
2289     }
2290     return CPDF_Number::Create(word);
2291   }
2292   if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
2293     if (bTypeOnly) {
2294       return (CPDF_Object*)PDFOBJ_BOOLEAN;
2295     }
2296     return CPDF_Boolean::Create(word == FX_BSTRC("true"));
2297   }
2298   if (word == FX_BSTRC("null")) {
2299     if (bTypeOnly) {
2300       return (CPDF_Object*)PDFOBJ_NULL;
2301     }
2302     return CPDF_Null::Create();
2303   }
2304   if (word == FX_BSTRC("(")) {
2305     if (bTypeOnly) {
2306       return (CPDF_Object*)PDFOBJ_STRING;
2307     }
2308     CFX_ByteString str = ReadString();
2309     if (m_pCryptoHandler) {
2310       m_pCryptoHandler->Decrypt(objnum, gennum, str);
2311     }
2312     return CPDF_String::Create(str, FALSE);
2313   }
2314   if (word == FX_BSTRC("<")) {
2315     if (bTypeOnly) {
2316       return (CPDF_Object*)PDFOBJ_STRING;
2317     }
2318     CFX_ByteString str = ReadHexString();
2319     if (m_pCryptoHandler) {
2320       m_pCryptoHandler->Decrypt(objnum, gennum, str);
2321     }
2322     return CPDF_String::Create(str, TRUE);
2323   }
2324   if (word == FX_BSTRC("[")) {
2325     if (bTypeOnly) {
2326       return (CPDF_Object*)PDFOBJ_ARRAY;
2327     }
2328     CPDF_Array* pArray = CPDF_Array::Create();
2329     while (1) {
2330       CPDF_Object* pObj = GetObject(pObjList, objnum, gennum);
2331       if (pObj == NULL) {
2332         if (m_WordBuffer[0] == ']') {
2333           return pArray;
2334         }
2335         if (pArray) {
2336           pArray->Release();
2337         }
2338         return NULL;
2339       }
2340       pArray->Add(pObj);
2341     }
2342   }
2343   if (word[0] == '/') {
2344     if (bTypeOnly) {
2345       return (CPDF_Object*)PDFOBJ_NAME;
2346     }
2347     return CPDF_Name::Create(
2348         PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
2349   }
2350   if (word == FX_BSTRC("<<")) {
2351     if (bTypeOnly) {
2352       return (CPDF_Object*)PDFOBJ_DICTIONARY;
2353     }
2354     if (pContext) {
2355       pContext->m_DictStart = SavedPos;
2356     }
2357     CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
2358     while (1) {
2359       FX_BOOL bIsNumber;
2360       FX_FILESIZE SavedPos = m_Pos;
2361       CFX_ByteString key = GetNextWord(bIsNumber);
2362       if (key.IsEmpty()) {
2363         if (pDict) {
2364           pDict->Release();
2365         }
2366         return NULL;
2367       }
2368       if (key == FX_BSTRC(">>")) {
2369         break;
2370       }
2371       if (key == FX_BSTRC("endobj")) {
2372         m_Pos = SavedPos;
2373         break;
2374       }
2375       if (key[0] != '/') {
2376         continue;
2377       }
2378       key = PDF_NameDecode(key);
2379       CPDF_Object* pObj = GetObject(pObjList, objnum, gennum);
2380       if (pObj == NULL) {
2381         if (pDict) {
2382           pDict->Release();
2383         }
2384         uint8_t ch;
2385         while (1) {
2386           if (!GetNextChar(ch)) {
2387             break;
2388           }
2389           if (ch == 0x0A || ch == 0x0D) {
2390             break;
2391           }
2392         }
2393         return NULL;
2394       }
2395       if (key.GetLength() > 1) {
2396         pDict->AddValue(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1),
2397                         pObj);
2398       }
2399     }
2400     if (pContext) {
2401       pContext->m_DictEnd = m_Pos;
2402       if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
2403         return pDict;
2404       }
2405     }
2406     FX_FILESIZE SavedPos = m_Pos;
2407     FX_BOOL bIsNumber;
2408     CFX_ByteString nextword = GetNextWord(bIsNumber);
2409     if (nextword == FX_BSTRC("stream")) {
2410       CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum);
2411       if (pStream) {
2412         return pStream;
2413       }
2414       if (pDict) {
2415         pDict->Release();
2416       }
2417       return NULL;
2418     } else {
2419       m_Pos = SavedPos;
2420       return pDict;
2421     }
2422   }
2423   if (word == FX_BSTRC(">>")) {
2424     m_Pos = SavedPos;
2425     return NULL;
2426   }
2427   if (bTypeOnly) {
2428     return (CPDF_Object*)PDFOBJ_INVALID;
2429   }
2430   return NULL;
2431 }
2432 unsigned int CPDF_SyntaxParser::ReadEOLMarkers(FX_FILESIZE pos) {
2433   unsigned char byte1 = 0;
2434   unsigned char byte2 = 0;
2435   GetCharAt(pos, byte1);
2436   GetCharAt(pos + 1, byte2);
2437   unsigned int markers = 0;
2438   if (byte1 == '\r' && byte2 == '\n') {
2439     markers = 2;
2440   } else if (byte1 == '\r' || byte1 == '\n') {
2441     markers = 1;
2442   }
2443   return markers;
2444 }
2445 CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict,
2446                                            PARSE_CONTEXT* pContext,
2447                                            FX_DWORD objnum,
2448                                            FX_DWORD gennum) {
2449   CPDF_Object* pLenObj = pDict->GetElement(FX_BSTRC("Length"));
2450   FX_FILESIZE len = -1;
2451   if (pLenObj && ((pLenObj->GetType() != PDFOBJ_REFERENCE) ||
2452                   ((((CPDF_Reference*)pLenObj)->GetObjList()) &&
2453                    ((CPDF_Reference*)pLenObj)->GetRefObjNum() != objnum))) {
2454     len = pLenObj->GetInteger();
2455   }
2456   // Check whether end of line markers follow the keyword 'stream'.
2457   unsigned int numMarkers = ReadEOLMarkers(m_Pos);
2458   m_Pos += numMarkers;
2459   FX_FILESIZE streamStartPos = m_Pos;
2460   if (pContext) {
2461     pContext->m_DataStart = streamStartPos;
2462   }
2463   const unsigned int ENDSTREAM_LEN = sizeof("endstream") - 1;
2464   const unsigned int ENDOBJ_LEN = sizeof("endobj") - 1;
2465   CPDF_CryptoHandler* pCryptoHandler =
2466       objnum == (FX_DWORD)m_MetadataObjnum ? nullptr : m_pCryptoHandler;
2467   if (!pCryptoHandler) {
2468     FX_BOOL bSearchForKeyword = TRUE;
2469     unsigned int prevMarkers = 0;
2470     unsigned int nextMarkers = 0;
2471     if (len >= 0) {
2472       pdfium::base::CheckedNumeric<FX_FILESIZE> pos = m_Pos;
2473       pos += len;
2474       if (pos.IsValid() && pos.ValueOrDie() < m_FileLen) {
2475         m_Pos = pos.ValueOrDie();
2476       }
2477       prevMarkers = ReadEOLMarkers(m_Pos);
2478       GetNextWord();
2479       nextMarkers = ReadEOLMarkers(m_Pos);
2480       if (m_WordSize == ENDSTREAM_LEN && prevMarkers != 0 && nextMarkers != 0 &&
2481           FXSYS_memcmp(m_WordBuffer, "endstream", ENDSTREAM_LEN) == 0) {
2482         bSearchForKeyword = FALSE;
2483       }
2484     }
2485     if (bSearchForKeyword) {
2486       // If len is not available, len needs to be calculated
2487       // by searching the keywords "endstream" or "endobj".
2488       m_Pos = streamStartPos;
2489       FX_FILESIZE endStreamOffset = 0;
2490       while (endStreamOffset >= 0) {
2491         endStreamOffset = FindTag(FX_BSTRC("endstream"), 0);
2492         if (endStreamOffset < 0) {
2493           // Can't find any "endstream".
2494           break;
2495         }
2496         prevMarkers = ReadEOLMarkers(streamStartPos + endStreamOffset - 1);
2497         nextMarkers =
2498             ReadEOLMarkers(streamStartPos + endStreamOffset + ENDSTREAM_LEN);
2499         if (prevMarkers != 0 && nextMarkers != 0) {
2500           // Stop searching when the keyword "endstream" is found.
2501           break;
2502         } else {
2503           unsigned char ch = 0x00;
2504           GetCharAt(streamStartPos + endStreamOffset + ENDSTREAM_LEN, ch);
2505           if (ch == 0x09 || ch == 0x20) {
2506             //"endstream" is treated as a keyword
2507             // when it is followed by a tab or whitespace
2508             break;
2509           }
2510         }
2511         m_Pos += ENDSTREAM_LEN;
2512       }
2513       m_Pos = streamStartPos;
2514       FX_FILESIZE endObjOffset = 0;
2515       while (endObjOffset >= 0) {
2516         endObjOffset = FindTag(FX_BSTRC("endobj"), 0);
2517         if (endObjOffset < 0) {
2518           // Can't find any "endobj".
2519           break;
2520         }
2521         prevMarkers = ReadEOLMarkers(streamStartPos + endObjOffset - 1);
2522         nextMarkers =
2523             ReadEOLMarkers(streamStartPos + endObjOffset + ENDOBJ_LEN);
2524         if (prevMarkers != 0 && nextMarkers != 0) {
2525           // Stop searching when the keyword "endobj" is found.
2526           break;
2527         }
2528         m_Pos += ENDOBJ_LEN;
2529       }
2530       if (endStreamOffset < 0 && endObjOffset < 0) {
2531         // Can't find "endstream" or "endobj".
2532         return nullptr;
2533       }
2534       if (endStreamOffset < 0 && endObjOffset >= 0) {
2535         // Correct the position of end stream.
2536         endStreamOffset = endObjOffset;
2537       } else if (endStreamOffset >= 0 && endObjOffset < 0) {
2538         // Correct the position of end obj.
2539         endObjOffset = endStreamOffset;
2540       } else if (endStreamOffset > endObjOffset) {
2541         endStreamOffset = endObjOffset;
2542       }
2543       len = endStreamOffset;
2544       numMarkers = ReadEOLMarkers(streamStartPos + endStreamOffset - 2);
2545       if (numMarkers == 2) {
2546         len -= 2;
2547       } else {
2548         numMarkers = ReadEOLMarkers(streamStartPos + endStreamOffset - 1);
2549         if (numMarkers == 1) {
2550           len -= 1;
2551         }
2552       }
2553       if (len <= 0) {
2554         return nullptr;
2555       }
2556       pDict->SetAtInteger(FX_BSTRC("Length"), len);
2557     }
2558     m_Pos = streamStartPos;
2559   }
2560   if (len <= 0) {
2561     return nullptr;
2562   }
2563   uint8_t* pData = FX_Alloc(uint8_t, len);
2564   ReadBlock(pData, len);
2565   if (pCryptoHandler) {
2566     CFX_BinaryBuf dest_buf;
2567     dest_buf.EstimateSize(pCryptoHandler->DecryptGetSize(len));
2568     void* context = pCryptoHandler->DecryptStart(objnum, gennum);
2569     pCryptoHandler->DecryptStream(context, pData, len, dest_buf);
2570     pCryptoHandler->DecryptFinish(context, dest_buf);
2571     FX_Free(pData);
2572     pData = dest_buf.GetBuffer();
2573     len = dest_buf.GetSize();
2574     dest_buf.DetachBuffer();
2575   }
2576   CPDF_Stream* pStream = new CPDF_Stream(pData, len, pDict);
2577   if (pContext) {
2578     pContext->m_DataEnd = pContext->m_DataStart + len;
2579   }
2580   streamStartPos = m_Pos;
2581   GetNextWord();
2582   numMarkers = ReadEOLMarkers(m_Pos);
2583   if (m_WordSize == ENDOBJ_LEN && numMarkers != 0 &&
2584       FXSYS_memcmp(m_WordBuffer, "endobj", ENDOBJ_LEN) == 0) {
2585     m_Pos = streamStartPos;
2586   }
2587   return pStream;
2588 }
2589 void CPDF_SyntaxParser::InitParser(IFX_FileRead* pFileAccess,
2590                                    FX_DWORD HeaderOffset) {
2591   FX_Free(m_pFileBuf);
2592   m_pFileBuf = FX_Alloc(uint8_t, m_BufSize);
2593   m_HeaderOffset = HeaderOffset;
2594   m_FileLen = pFileAccess->GetSize();
2595   m_Pos = 0;
2596   m_pFileAccess = pFileAccess;
2597   m_BufOffset = 0;
2598   pFileAccess->ReadBlock(
2599       m_pFileBuf, 0,
2600       (size_t)((FX_FILESIZE)m_BufSize > m_FileLen ? m_FileLen : m_BufSize));
2601 }
2602 int32_t CPDF_SyntaxParser::GetDirectNum() {
2603   GetNextWord();
2604   if (!m_bIsNumber) {
2605     return 0;
2606   }
2607   m_WordBuffer[m_WordSize] = 0;
2608   return FXSYS_atoi((const FX_CHAR*)m_WordBuffer);
2609 }
2610 FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos,
2611                                        FX_FILESIZE limit,
2612                                        const uint8_t* tag,
2613                                        FX_DWORD taglen) {
2614   uint8_t type = PDF_CharType[tag[0]];
2615   FX_BOOL bCheckLeft = type != 'D' && type != 'W';
2616   type = PDF_CharType[tag[taglen - 1]];
2617   FX_BOOL bCheckRight = type != 'D' && type != 'W';
2618   uint8_t ch;
2619   if (bCheckRight && startpos + (int32_t)taglen <= limit &&
2620       GetCharAt(startpos + (int32_t)taglen, ch)) {
2621     uint8_t type = PDF_CharType[ch];
2622     if (type == 'N' || type == 'R') {
2623       return FALSE;
2624     }
2625   }
2626   if (bCheckLeft && startpos > 0 && GetCharAt(startpos - 1, ch)) {
2627     uint8_t type = PDF_CharType[ch];
2628     if (type == 'N' || type == 'R') {
2629       return FALSE;
2630     }
2631   }
2632   return TRUE;
2633 }
2634 FX_BOOL CPDF_SyntaxParser::SearchWord(const CFX_ByteStringC& tag,
2635                                       FX_BOOL bWholeWord,
2636                                       FX_BOOL bForward,
2637                                       FX_FILESIZE limit) {
2638   int32_t taglen = tag.GetLength();
2639   if (taglen == 0) {
2640     return FALSE;
2641   }
2642   FX_FILESIZE pos = m_Pos;
2643   int32_t offset = 0;
2644   if (!bForward) {
2645     offset = taglen - 1;
2646   }
2647   const uint8_t* tag_data = tag.GetPtr();
2648   uint8_t byte;
2649   while (1) {
2650     if (bForward) {
2651       if (limit) {
2652         if (pos >= m_Pos + limit) {
2653           return FALSE;
2654         }
2655       }
2656       if (!GetCharAt(pos, byte)) {
2657         return FALSE;
2658       }
2659     } else {
2660       if (limit) {
2661         if (pos <= m_Pos - limit) {
2662           return FALSE;
2663         }
2664       }
2665       if (!GetCharAtBackward(pos, byte)) {
2666         return FALSE;
2667       }
2668     }
2669     if (byte == tag_data[offset]) {
2670       if (bForward) {
2671         offset++;
2672         if (offset < taglen) {
2673           pos++;
2674           continue;
2675         }
2676       } else {
2677         offset--;
2678         if (offset >= 0) {
2679           pos--;
2680           continue;
2681         }
2682       }
2683       FX_FILESIZE startpos = bForward ? pos - taglen + 1 : pos;
2684       if (!bWholeWord || IsWholeWord(startpos, limit, tag.GetPtr(), taglen)) {
2685         m_Pos = startpos;
2686         return TRUE;
2687       }
2688     }
2689     if (bForward) {
2690       offset = byte == tag_data[0] ? 1 : 0;
2691       pos++;
2692     } else {
2693       offset = byte == tag_data[taglen - 1] ? taglen - 2 : taglen - 1;
2694       pos--;
2695     }
2696     if (pos < 0) {
2697       return FALSE;
2698     }
2699   }
2700   return FALSE;
2701 }
2702 struct _SearchTagRecord {
2703   const uint8_t* m_pTag;
2704   FX_DWORD m_Len;
2705   FX_DWORD m_Offset;
2706 };
2707 int32_t CPDF_SyntaxParser::SearchMultiWord(const CFX_ByteStringC& tags,
2708                                            FX_BOOL bWholeWord,
2709                                            FX_FILESIZE limit) {
2710   int32_t ntags = 1, i;
2711   for (i = 0; i < tags.GetLength(); i++)
2712     if (tags[i] == 0) {
2713       ntags++;
2714     }
2715   _SearchTagRecord* pPatterns = FX_Alloc(_SearchTagRecord, ntags);
2716   FX_DWORD start = 0, itag = 0, max_len = 0;
2717   for (i = 0; i <= tags.GetLength(); i++) {
2718     if (tags[i] == 0) {
2719       FX_DWORD len = i - start;
2720       if (len > max_len) {
2721         max_len = len;
2722       }
2723       pPatterns[itag].m_pTag = tags.GetPtr() + start;
2724       pPatterns[itag].m_Len = len;
2725       pPatterns[itag].m_Offset = 0;
2726       start = i + 1;
2727       itag++;
2728     }
2729   }
2730   FX_FILESIZE pos = m_Pos;
2731   uint8_t byte;
2732   GetCharAt(pos++, byte);
2733   int32_t found = -1;
2734   while (1) {
2735     for (i = 0; i < ntags; i++) {
2736       if (pPatterns[i].m_pTag[pPatterns[i].m_Offset] == byte) {
2737         pPatterns[i].m_Offset++;
2738         if (pPatterns[i].m_Offset == pPatterns[i].m_Len) {
2739           if (!bWholeWord ||
2740               IsWholeWord(pos - pPatterns[i].m_Len, limit, pPatterns[i].m_pTag,
2741                           pPatterns[i].m_Len)) {
2742             found = i;
2743             goto end;
2744           } else {
2745             if (pPatterns[i].m_pTag[0] == byte) {
2746               pPatterns[i].m_Offset = 1;
2747             } else {
2748               pPatterns[i].m_Offset = 0;
2749             }
2750           }
2751         }
2752       } else {
2753         if (pPatterns[i].m_pTag[0] == byte) {
2754           pPatterns[i].m_Offset = 1;
2755         } else {
2756           pPatterns[i].m_Offset = 0;
2757         }
2758       }
2759     }
2760     if (limit && pos >= m_Pos + limit) {
2761       goto end;
2762     }
2763     if (!GetCharAt(pos, byte)) {
2764       goto end;
2765     }
2766     pos++;
2767   }
2768 end:
2769   FX_Free(pPatterns);
2770   return found;
2771 }
2772 FX_FILESIZE CPDF_SyntaxParser::FindTag(const CFX_ByteStringC& tag,
2773                                        FX_FILESIZE limit) {
2774   int32_t taglen = tag.GetLength();
2775   int32_t match = 0;
2776   limit += m_Pos;
2777   FX_FILESIZE startpos = m_Pos;
2778   while (1) {
2779     uint8_t ch;
2780     if (!GetNextChar(ch)) {
2781       return -1;
2782     }
2783     if (ch == tag[match]) {
2784       match++;
2785       if (match == taglen) {
2786         return m_Pos - startpos - taglen;
2787       }
2788     } else {
2789       match = ch == tag[0] ? 1 : 0;
2790     }
2791     if (limit && m_Pos == limit) {
2792       return -1;
2793     }
2794   }
2795   return -1;
2796 }
2797 void CPDF_SyntaxParser::GetBinary(uint8_t* buffer, FX_DWORD size) {
2798   FX_DWORD offset = 0;
2799   uint8_t ch;
2800   while (1) {
2801     if (!GetNextChar(ch)) {
2802       return;
2803     }
2804     buffer[offset++] = ch;
2805     if (offset == size) {
2806       break;
2807     }
2808   }
2809 }
2810
2811 class CPDF_DataAvail final : public IPDF_DataAvail {
2812  public:
2813   CPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead);
2814   ~CPDF_DataAvail() override;
2815
2816   virtual FX_BOOL IsDocAvail(IFX_DownloadHints* pHints) override;
2817
2818   virtual void SetDocument(CPDF_Document* pDoc) override;
2819
2820   virtual FX_BOOL IsPageAvail(int iPage, IFX_DownloadHints* pHints) override;
2821
2822   virtual int32_t IsFormAvail(IFX_DownloadHints* pHints) override;
2823
2824   virtual int32_t IsLinearizedPDF() override;
2825
2826   virtual FX_BOOL IsLinearized() override { return m_bLinearized; }
2827
2828   virtual void GetLinearizedMainXRefInfo(FX_FILESIZE* pPos,
2829                                          FX_DWORD* pSize) override;
2830
2831  protected:
2832   static const int kMaxDataAvailRecursionDepth = 64;
2833   static int s_CurrentDataAvailRecursionDepth;
2834
2835   FX_DWORD GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset);
2836   FX_BOOL IsObjectsAvail(CFX_PtrArray& obj_array,
2837                          FX_BOOL bParsePage,
2838                          IFX_DownloadHints* pHints,
2839                          CFX_PtrArray& ret_array);
2840   FX_BOOL CheckDocStatus(IFX_DownloadHints* pHints);
2841   FX_BOOL CheckHeader(IFX_DownloadHints* pHints);
2842   FX_BOOL CheckFirstPage(IFX_DownloadHints* pHints);
2843   FX_BOOL CheckEnd(IFX_DownloadHints* pHints);
2844   FX_BOOL CheckCrossRef(IFX_DownloadHints* pHints);
2845   FX_BOOL CheckCrossRefItem(IFX_DownloadHints* pHints);
2846   FX_BOOL CheckTrailer(IFX_DownloadHints* pHints);
2847   FX_BOOL CheckRoot(IFX_DownloadHints* pHints);
2848   FX_BOOL CheckInfo(IFX_DownloadHints* pHints);
2849   FX_BOOL CheckPages(IFX_DownloadHints* pHints);
2850   FX_BOOL CheckPage(IFX_DownloadHints* pHints);
2851   FX_BOOL CheckResources(IFX_DownloadHints* pHints);
2852   FX_BOOL CheckAnnots(IFX_DownloadHints* pHints);
2853   FX_BOOL CheckAcroForm(IFX_DownloadHints* pHints);
2854   FX_BOOL CheckAcroFormSubObject(IFX_DownloadHints* pHints);
2855   FX_BOOL CheckTrailerAppend(IFX_DownloadHints* pHints);
2856   FX_BOOL CheckPageStatus(IFX_DownloadHints* pHints);
2857   FX_BOOL CheckAllCrossRefStream(IFX_DownloadHints* pHints);
2858
2859   int32_t CheckCrossRefStream(IFX_DownloadHints* pHints,
2860                               FX_FILESIZE& xref_offset);
2861   FX_BOOL IsLinearizedFile(uint8_t* pData, FX_DWORD dwLen);
2862   void SetStartOffset(FX_FILESIZE dwOffset);
2863   FX_BOOL GetNextToken(CFX_ByteString& token);
2864   FX_BOOL GetNextChar(uint8_t& ch);
2865   CPDF_Object* ParseIndirectObjectAt(FX_FILESIZE pos, FX_DWORD objnum);
2866   CPDF_Object* GetObject(FX_DWORD objnum,
2867                          IFX_DownloadHints* pHints,
2868                          FX_BOOL* pExistInFile);
2869   FX_BOOL GetPageKids(CPDF_Parser* pParser, CPDF_Object* pPages);
2870   FX_BOOL PreparePageItem();
2871   FX_BOOL LoadPages(IFX_DownloadHints* pHints);
2872   FX_BOOL LoadAllXref(IFX_DownloadHints* pHints);
2873   FX_BOOL LoadAllFile(IFX_DownloadHints* pHints);
2874   FX_BOOL CheckLinearizedData(IFX_DownloadHints* pHints);
2875   FX_BOOL CheckFileResources(IFX_DownloadHints* pHints);
2876   FX_BOOL CheckPageAnnots(int iPage, IFX_DownloadHints* pHints);
2877
2878   FX_BOOL CheckLinearizedFirstPage(int iPage, IFX_DownloadHints* pHints);
2879   FX_BOOL HaveResourceAncestor(CPDF_Dictionary* pDict);
2880   FX_BOOL CheckPage(int32_t iPage, IFX_DownloadHints* pHints);
2881   FX_BOOL LoadDocPages(IFX_DownloadHints* pHints);
2882   FX_BOOL LoadDocPage(int32_t iPage, IFX_DownloadHints* pHints);
2883   FX_BOOL CheckPageNode(CPDF_PageNode& pageNodes,
2884                         int32_t iPage,
2885                         int32_t& iCount,
2886                         IFX_DownloadHints* pHints);
2887   FX_BOOL CheckUnkownPageNode(FX_DWORD dwPageNo,
2888                               CPDF_PageNode* pPageNode,
2889                               IFX_DownloadHints* pHints);
2890   FX_BOOL CheckArrayPageNode(FX_DWORD dwPageNo,
2891                              CPDF_PageNode* pPageNode,
2892                              IFX_DownloadHints* pHints);
2893   FX_BOOL CheckPageCount(IFX_DownloadHints* pHints);
2894   FX_BOOL IsFirstCheck(int iPage);
2895   void ResetFirstCheck(int iPage);
2896
2897   CPDF_Parser m_parser;
2898
2899   CPDF_SyntaxParser m_syntaxParser;
2900
2901   CPDF_Object* m_pRoot;
2902
2903   FX_DWORD m_dwRootObjNum;
2904
2905   FX_DWORD m_dwInfoObjNum;
2906
2907   CPDF_Object* m_pLinearized;
2908
2909   CPDF_Object* m_pTrailer;
2910
2911   FX_BOOL m_bDocAvail;
2912
2913   FX_FILESIZE m_dwHeaderOffset;
2914
2915   FX_FILESIZE m_dwLastXRefOffset;
2916
2917   FX_FILESIZE m_dwXRefOffset;
2918
2919   FX_FILESIZE m_dwTrailerOffset;
2920
2921   FX_FILESIZE m_dwCurrentOffset;
2922
2923   PDF_DATAAVAIL_STATUS m_docStatus;
2924
2925   FX_FILESIZE m_dwFileLen;
2926
2927   CPDF_Document* m_pDocument;
2928
2929   CPDF_SortObjNumArray m_objnum_array;
2930
2931   CFX_PtrArray m_objs_array;
2932
2933   FX_FILESIZE m_Pos;
2934
2935   FX_FILESIZE m_bufferOffset;
2936
2937   FX_DWORD m_bufferSize;
2938
2939   CFX_ByteString m_WordBuf;
2940
2941   uint8_t m_WordBuffer[257];
2942
2943   FX_DWORD m_WordSize;
2944
2945   uint8_t m_bufferData[512];
2946
2947   CFX_FileSizeArray m_CrossOffset;
2948
2949   CFX_DWordArray m_XRefStreamList;
2950
2951   CFX_DWordArray m_PageObjList;
2952
2953   FX_DWORD m_PagesObjNum;
2954
2955   FX_BOOL m_bLinearized;
2956
2957   FX_DWORD m_dwFirstPageNo;
2958
2959   FX_BOOL m_bLinearedDataOK;
2960
2961   FX_BOOL m_bMainXRefLoadTried;
2962
2963   FX_BOOL m_bMainXRefLoadedOK;
2964
2965   FX_BOOL m_bPagesTreeLoad;
2966
2967   FX_BOOL m_bPagesLoad;
2968
2969   CPDF_Parser* m_pCurrentParser;
2970
2971   FX_FILESIZE m_dwCurrentXRefSteam;
2972
2973   FX_BOOL m_bAnnotsLoad;
2974
2975   FX_BOOL m_bHaveAcroForm;
2976
2977   FX_DWORD m_dwAcroFormObjNum;
2978
2979   FX_BOOL m_bAcroFormLoad;
2980
2981   CPDF_Object* m_pAcroForm;
2982
2983   CFX_PtrArray m_arrayAcroforms;
2984
2985   CPDF_Dictionary* m_pPageDict;
2986
2987   CPDF_Object* m_pPageResource;
2988
2989   FX_BOOL m_bNeedDownLoadResource;
2990
2991   FX_BOOL m_bPageLoadedOK;
2992
2993   FX_BOOL m_bLinearizedFormParamLoad;
2994
2995   CFX_PtrArray m_PagesArray;
2996
2997   FX_DWORD m_dwEncryptObjNum;
2998
2999   FX_FILESIZE m_dwPrevXRefOffset;
3000
3001   FX_BOOL m_bTotalLoadPageTree;
3002
3003   FX_BOOL m_bCurPageDictLoadOK;
3004
3005   CPDF_PageNode m_pageNodes;
3006
3007   std::set<FX_DWORD> m_pageMapCheckState;
3008   std::set<FX_DWORD> m_pagesLoadState;
3009 };
3010
3011 IPDF_DataAvail::IPDF_DataAvail(IFX_FileAvail* pFileAvail,
3012                                IFX_FileRead* pFileRead)
3013     : m_pFileAvail(pFileAvail), m_pFileRead(pFileRead) {}
3014
3015 // static
3016 IPDF_DataAvail* IPDF_DataAvail::Create(IFX_FileAvail* pFileAvail,
3017                                        IFX_FileRead* pFileRead) {
3018   return new CPDF_DataAvail(pFileAvail, pFileRead);
3019 }
3020
3021 // static
3022 int CPDF_DataAvail::s_CurrentDataAvailRecursionDepth = 0;
3023
3024 CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail,
3025                                IFX_FileRead* pFileRead)
3026     : IPDF_DataAvail(pFileAvail, pFileRead) {
3027   m_Pos = 0;
3028   m_dwFileLen = 0;
3029   if (m_pFileRead) {
3030     m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize();
3031   }
3032   m_dwCurrentOffset = 0;
3033   m_WordSize = 0;
3034   m_dwXRefOffset = 0;
3035   m_bufferOffset = 0;
3036   m_dwFirstPageNo = 0;
3037   m_bufferSize = 0;
3038   m_PagesObjNum = 0;
3039   m_dwCurrentXRefSteam = 0;
3040   m_dwAcroFormObjNum = 0;
3041   m_dwInfoObjNum = 0;
3042   m_pDocument = 0;
3043   m_dwEncryptObjNum = 0;
3044   m_dwPrevXRefOffset = 0;
3045   m_dwLastXRefOffset = 0;
3046   m_bDocAvail = FALSE;
3047   m_bMainXRefLoadTried = FALSE;
3048   m_bDocAvail = FALSE;
3049   m_bLinearized = FALSE;
3050   m_bPagesLoad = FALSE;
3051   m_bPagesTreeLoad = FALSE;
3052   m_bMainXRefLoadedOK = FALSE;
3053   m_bAnnotsLoad = FALSE;
3054   m_bHaveAcroForm = FALSE;
3055   m_bAcroFormLoad = FALSE;
3056   m_bPageLoadedOK = FALSE;
3057   m_bNeedDownLoadResource = FALSE;
3058   m_bLinearizedFormParamLoad = FALSE;
3059   m_pLinearized = NULL;
3060   m_pRoot = NULL;
3061   m_pTrailer = NULL;
3062   m_pCurrentParser = NULL;
3063   m_pAcroForm = NULL;
3064   m_pPageDict = NULL;
3065   m_pPageResource = NULL;
3066   m_docStatus = PDF_DATAAVAIL_HEADER;
3067   m_parser.m_bOwnFileRead = FALSE;
3068   m_bTotalLoadPageTree = FALSE;
3069   m_bCurPageDictLoadOK = FALSE;
3070   m_bLinearedDataOK = FALSE;
3071 }
3072 CPDF_DataAvail::~CPDF_DataAvail() {
3073   if (m_pLinearized) {
3074     m_pLinearized->Release();
3075   }
3076   if (m_pRoot) {
3077     m_pRoot->Release();
3078   }
3079   if (m_pTrailer) {
3080     m_pTrailer->Release();
3081   }
3082   int32_t i = 0;
3083   int32_t iSize = m_arrayAcroforms.GetSize();
3084   for (i = 0; i < iSize; ++i) {
3085     ((CPDF_Object*)m_arrayAcroforms.GetAt(i))->Release();
3086   }
3087 }
3088 void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc) {
3089   m_pDocument = pDoc;
3090 }
3091 FX_DWORD CPDF_DataAvail::GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset) {
3092   CPDF_Parser* pParser = (CPDF_Parser*)(m_pDocument->GetParser());
3093   if (pParser == NULL) {
3094     return 0;
3095   }
3096   if (objnum >= (FX_DWORD)pParser->m_CrossRef.GetSize()) {
3097     return 0;
3098   }
3099   if (pParser->m_V5Type[objnum] == 2) {
3100     objnum = (FX_DWORD)pParser->m_CrossRef[objnum];
3101   }
3102   if (pParser->m_V5Type[objnum] == 1 || pParser->m_V5Type[objnum] == 255) {
3103     offset = pParser->m_CrossRef[objnum];
3104     if (offset == 0) {
3105       return 0;
3106     }
3107     void* pResult = FXSYS_bsearch(&offset, pParser->m_SortedOffset.GetData(),
3108                                   pParser->m_SortedOffset.GetSize(),
3109                                   sizeof(FX_FILESIZE), _CompareFileSize);
3110     if (pResult == NULL) {
3111       return 0;
3112     }
3113     if ((FX_FILESIZE*)pResult -
3114             (FX_FILESIZE*)pParser->m_SortedOffset.GetData() ==
3115         pParser->m_SortedOffset.GetSize() - 1) {
3116       return 0;
3117     }
3118     return (FX_DWORD)(((FX_FILESIZE*)pResult)[1] - offset);
3119   }
3120   return 0;
3121 }
3122 FX_BOOL CPDF_DataAvail::IsObjectsAvail(CFX_PtrArray& obj_array,
3123                                        FX_BOOL bParsePage,
3124                                        IFX_DownloadHints* pHints,
3125                                        CFX_PtrArray& ret_array) {
3126   if (!obj_array.GetSize()) {
3127     return TRUE;
3128   }
3129   FX_DWORD count = 0;
3130   CFX_PtrArray new_obj_array;
3131   int32_t i = 0;
3132   for (i = 0; i < obj_array.GetSize(); i++) {
3133     CPDF_Object* pObj = (CPDF_Object*)obj_array[i];
3134     if (!pObj) {
3135       continue;
3136     }
3137     int32_t type = pObj->GetType();
3138     switch (type) {
3139       case PDFOBJ_ARRAY: {
3140         CPDF_Array* pArray = pObj->GetArray();
3141         for (FX_DWORD k = 0; k < pArray->GetCount(); k++) {
3142           new_obj_array.Add(pArray->GetElement(k));
3143         }
3144       } break;
3145       case PDFOBJ_STREAM:
3146         pObj = pObj->GetDict();
3147       case PDFOBJ_DICTIONARY: {
3148         CPDF_Dictionary* pDict = pObj->GetDict();
3149         if (pDict && pDict->GetString("Type") == "Page" && !bParsePage) {
3150           continue;
3151         }
3152         FX_POSITION pos = pDict->GetStartPos();
3153         while (pos) {
3154           CPDF_Object* value;
3155           CFX_ByteString key;
3156           value = pDict->GetNextElement(pos, key);
3157           if (key != "Parent") {
3158             new_obj_array.Add(value);
3159           }
3160         }
3161       } break;
3162       case PDFOBJ_REFERENCE: {
3163         CPDF_Reference* pRef = (CPDF_Reference*)pObj;
3164         FX_DWORD dwNum = pRef->GetRefObjNum();
3165         FX_FILESIZE offset;
3166         FX_DWORD original_size = GetObjectSize(dwNum, offset);
3167         pdfium::base::CheckedNumeric<FX_DWORD> size = original_size;
3168         if (size.ValueOrDefault(0) == 0 || offset < 0 ||
3169             offset >= m_dwFileLen) {
3170           break;
3171         }
3172
3173         size += offset;
3174         size += 512;
3175         if (!size.IsValid()) {
3176           break;
3177         }
3178         if (size.ValueOrDie() > m_dwFileLen) {
3179           size = m_dwFileLen - offset;
3180         } else {
3181           size = original_size + 512;
3182         }
3183         if (!size.IsValid()) {
3184           break;
3185         }
3186         if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) {
3187           pHints->AddSegment(offset, size.ValueOrDie());
3188           ret_array.Add(pObj);
3189           count++;
3190         } else if (!m_objnum_array.Find(dwNum)) {
3191           m_objnum_array.AddObjNum(dwNum);
3192           CPDF_Object* pReferred =
3193               m_pDocument->GetIndirectObject(pRef->GetRefObjNum(), NULL);
3194           if (pReferred) {
3195             new_obj_array.Add(pReferred);
3196           }
3197         }
3198       } break;
3199     }
3200   }
3201   if (count > 0) {
3202     int32_t iSize = new_obj_array.GetSize();
3203     for (i = 0; i < iSize; ++i) {
3204       CPDF_Object* pObj = (CPDF_Object*)new_obj_array[i];
3205       int32_t type = pObj->GetType();
3206       if (type == PDFOBJ_REFERENCE) {
3207         CPDF_Reference* pRef = (CPDF_Reference*)pObj;
3208         FX_DWORD dwNum = pRef->GetRefObjNum();
3209         if (!m_objnum_array.Find(dwNum)) {
3210           ret_array.Add(pObj);
3211         }
3212       } else {
3213         ret_array.Add(pObj);
3214       }
3215     }
3216     return FALSE;
3217   }
3218   obj_array.RemoveAll();
3219   obj_array.Append(new_obj_array);
3220   return IsObjectsAvail(obj_array, FALSE, pHints, ret_array);
3221 }
3222 FX_BOOL CPDF_DataAvail::IsDocAvail(IFX_DownloadHints* pHints) {
3223   if (!m_dwFileLen && m_pFileRead) {
3224     m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize();
3225     if (!m_dwFileLen) {
3226       return TRUE;
3227     }
3228   }
3229   while (!m_bDocAvail) {
3230     if (!CheckDocStatus(pHints)) {
3231       return FALSE;
3232     }
3233   }
3234   return TRUE;
3235 }
3236 FX_BOOL CPDF_DataAvail::CheckAcroFormSubObject(IFX_DownloadHints* pHints) {
3237   if (!m_objs_array.GetSize()) {
3238     m_objs_array.RemoveAll();
3239     m_objnum_array.RemoveAll();
3240     CFX_PtrArray obj_array;
3241     obj_array.Append(m_arrayAcroforms);
3242     FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array);
3243     if (bRet) {
3244       m_objs_array.RemoveAll();
3245     }
3246     return bRet;
3247   }
3248   CFX_PtrArray new_objs_array;
3249   FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
3250   if (bRet) {
3251     int32_t iSize = m_arrayAcroforms.GetSize();
3252     for (int32_t i = 0; i < iSize; ++i) {
3253       ((CPDF_Object*)m_arrayAcroforms.GetAt(i))->Release();
3254     }
3255     m_arrayAcroforms.RemoveAll();
3256   } else {
3257     m_objs_array.RemoveAll();
3258     m_objs_array.Append(new_objs_array);
3259   }
3260   return bRet;
3261 }
3262 FX_BOOL CPDF_DataAvail::CheckAcroForm(IFX_DownloadHints* pHints) {
3263   FX_BOOL bExist = FALSE;
3264   m_pAcroForm = GetObject(m_dwAcroFormObjNum, pHints, &bExist);
3265   if (!bExist) {
3266     m_docStatus = PDF_DATAAVAIL_PAGETREE;
3267     return TRUE;
3268   }
3269   if (!m_pAcroForm) {
3270     if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3271       m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3272       return TRUE;
3273     }
3274     return FALSE;
3275   }
3276   m_arrayAcroforms.Add(m_pAcroForm);
3277   m_docStatus = PDF_DATAAVAIL_PAGETREE;
3278   return TRUE;
3279 }
3280 FX_BOOL CPDF_DataAvail::CheckDocStatus(IFX_DownloadHints* pHints) {
3281   switch (m_docStatus) {
3282     case PDF_DATAAVAIL_HEADER:
3283       return CheckHeader(pHints);
3284     case PDF_DATAAVAIL_FIRSTPAGE:
3285     case PDF_DATAAVAIL_FIRSTPAGE_PREPARE:
3286       return CheckFirstPage(pHints);
3287     case PDF_DATAAVAIL_END:
3288       return CheckEnd(pHints);
3289     case PDF_DATAAVAIL_CROSSREF:
3290       return CheckCrossRef(pHints);
3291     case PDF_DATAAVAIL_CROSSREF_ITEM:
3292       return CheckCrossRefItem(pHints);
3293     case PDF_DATAAVAIL_CROSSREF_STREAM:
3294       return CheckAllCrossRefStream(pHints);
3295     case PDF_DATAAVAIL_TRAILER:
3296       return CheckTrailer(pHints);
3297     case PDF_DATAAVAIL_TRAILER_APPEND:
3298       return CheckTrailerAppend(pHints);
3299     case PDF_DATAAVAIL_LOADALLCRSOSSREF:
3300       return LoadAllXref(pHints);
3301     case PDF_DATAAVAIL_LOADALLFILE:
3302       return LoadAllFile(pHints);
3303     case PDF_DATAAVAIL_ROOT:
3304       return CheckRoot(pHints);
3305     case PDF_DATAAVAIL_INFO:
3306       return CheckInfo(pHints);
3307     case PDF_DATAAVAIL_ACROFORM:
3308       return CheckAcroForm(pHints);
3309     case PDF_DATAAVAIL_PAGETREE:
3310       if (m_bTotalLoadPageTree) {
3311         return CheckPages(pHints);
3312       }
3313       return LoadDocPages(pHints);
3314     case PDF_DATAAVAIL_PAGE:
3315       if (m_bTotalLoadPageTree) {
3316         return CheckPage(pHints);
3317       }
3318       m_docStatus = PDF_DATAAVAIL_PAGE_LATERLOAD;
3319       return TRUE;
3320     case PDF_DATAAVAIL_ERROR:
3321       return LoadAllFile(pHints);
3322     case PDF_DATAAVAIL_PAGE_LATERLOAD:
3323       m_docStatus = PDF_DATAAVAIL_PAGE;
3324     default:
3325       m_bDocAvail = TRUE;
3326       return TRUE;
3327   }
3328 }
3329 FX_BOOL CPDF_DataAvail::CheckPageStatus(IFX_DownloadHints* pHints) {
3330   switch (m_docStatus) {
3331     case PDF_DATAAVAIL_PAGETREE:
3332       return CheckPages(pHints);
3333     case PDF_DATAAVAIL_PAGE:
3334       return CheckPage(pHints);
3335     case PDF_DATAAVAIL_ERROR:
3336       return LoadAllFile(pHints);
3337     default:
3338       m_bPagesTreeLoad = TRUE;
3339       m_bPagesLoad = TRUE;
3340       return TRUE;
3341   }
3342 }
3343 FX_BOOL CPDF_DataAvail::LoadAllFile(IFX_DownloadHints* pHints) {
3344   if (m_pFileAvail->IsDataAvail(0, (FX_DWORD)m_dwFileLen)) {
3345     m_docStatus = PDF_DATAAVAIL_DONE;
3346     return TRUE;
3347   }
3348   pHints->AddSegment(0, (FX_DWORD)m_dwFileLen);
3349   return FALSE;
3350 }
3351 FX_BOOL CPDF_DataAvail::LoadAllXref(IFX_DownloadHints* pHints) {
3352   m_parser.m_Syntax.InitParser(m_pFileRead, (FX_DWORD)m_dwHeaderOffset);
3353   m_parser.m_bOwnFileRead = FALSE;
3354   if (!m_parser.LoadAllCrossRefV4(m_dwLastXRefOffset) &&
3355       !m_parser.LoadAllCrossRefV5(m_dwLastXRefOffset)) {
3356     m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3357     return FALSE;
3358   }
3359   FXSYS_qsort(m_parser.m_SortedOffset.GetData(),
3360               m_parser.m_SortedOffset.GetSize(), sizeof(FX_FILESIZE),
3361               _CompareFileSize);
3362   m_dwRootObjNum = m_parser.GetRootObjNum();
3363   m_dwInfoObjNum = m_parser.GetInfoObjNum();
3364   m_pCurrentParser = &m_parser;
3365   m_docStatus = PDF_DATAAVAIL_ROOT;
3366   return TRUE;
3367 }
3368 CPDF_Object* CPDF_DataAvail::GetObject(FX_DWORD objnum,
3369                                        IFX_DownloadHints* pHints,
3370                                        FX_BOOL* pExistInFile) {
3371   CPDF_Object* pRet = NULL;
3372   FX_DWORD original_size = 0;
3373   FX_FILESIZE offset = 0;
3374   CPDF_Parser* pParser = NULL;
3375
3376   if (pExistInFile) {
3377     *pExistInFile = TRUE;
3378   }
3379
3380   if (m_pDocument == NULL) {
3381     original_size = (FX_DWORD)m_parser.GetObjectSize(objnum);
3382     offset = m_parser.GetObjectOffset(objnum);
3383     pParser = &m_parser;
3384   } else {
3385     original_size = GetObjectSize(objnum, offset);
3386     pParser = (CPDF_Parser*)(m_pDocument->GetParser());
3387   }
3388
3389   pdfium::base::CheckedNumeric<FX_DWORD> size = original_size;
3390   if (size.ValueOrDefault(0) == 0 || offset < 0 || offset >= m_dwFileLen) {
3391     if (pExistInFile)
3392       *pExistInFile = FALSE;
3393
3394     return NULL;
3395   }
3396
3397   size += offset;
3398   size += 512;
3399   if (!size.IsValid()) {
3400     return NULL;
3401   }
3402
3403   if (size.ValueOrDie() > m_dwFileLen) {
3404     size = m_dwFileLen - offset;
3405   } else {
3406     size = original_size + 512;
3407   }
3408
3409   if (!size.IsValid()) {
3410     return NULL;
3411   }
3412
3413   if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) {
3414     pHints->AddSegment(offset, size.ValueOrDie());
3415     return NULL;
3416   }
3417
3418   if (pParser) {
3419     pRet = pParser->ParseIndirectObject(NULL, objnum, NULL);
3420   }
3421
3422   if (!pRet && pExistInFile) {
3423     *pExistInFile = FALSE;
3424   }
3425
3426   return pRet;
3427 }
3428
3429 FX_BOOL CPDF_DataAvail::CheckInfo(IFX_DownloadHints* pHints) {
3430   FX_BOOL bExist = FALSE;
3431   CPDF_Object* pInfo = GetObject(m_dwInfoObjNum, pHints, &bExist);
3432   if (!bExist) {
3433     if (m_bHaveAcroForm) {
3434       m_docStatus = PDF_DATAAVAIL_ACROFORM;
3435     } else {
3436       m_docStatus = PDF_DATAAVAIL_PAGETREE;
3437     }
3438     return TRUE;
3439   }
3440   if (!pInfo) {
3441     if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3442       m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3443       return TRUE;
3444     }
3445     if (m_Pos == m_dwFileLen) {
3446       m_docStatus = PDF_DATAAVAIL_ERROR;
3447     }
3448     return FALSE;
3449   }
3450   if (pInfo) {
3451     pInfo->Release();
3452   }
3453   if (m_bHaveAcroForm) {
3454     m_docStatus = PDF_DATAAVAIL_ACROFORM;
3455   } else {
3456     m_docStatus = PDF_DATAAVAIL_PAGETREE;
3457   }
3458   return TRUE;
3459 }
3460 FX_BOOL CPDF_DataAvail::CheckRoot(IFX_DownloadHints* pHints) {
3461   FX_BOOL bExist = FALSE;
3462   m_pRoot = GetObject(m_dwRootObjNum, pHints, &bExist);
3463   if (!bExist) {
3464     m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3465     return TRUE;
3466   }
3467   if (!m_pRoot) {
3468     if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3469       m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3470       return TRUE;
3471     }
3472     return FALSE;
3473   }
3474   CPDF_Dictionary* pDict = m_pRoot->GetDict();
3475   if (!pDict) {
3476     m_docStatus = PDF_DATAAVAIL_ERROR;
3477     return FALSE;
3478   }
3479   CPDF_Reference* pRef = (CPDF_Reference*)pDict->GetElement(FX_BSTRC("Pages"));
3480   if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
3481     m_docStatus = PDF_DATAAVAIL_ERROR;
3482     return FALSE;
3483   }
3484   m_PagesObjNum = pRef->GetRefObjNum();
3485   CPDF_Reference* pAcroFormRef =
3486       (CPDF_Reference*)m_pRoot->GetDict()->GetElement(FX_BSTRC("AcroForm"));
3487   if (pAcroFormRef && pAcroFormRef->GetType() == PDFOBJ_REFERENCE) {
3488     m_bHaveAcroForm = TRUE;
3489     m_dwAcroFormObjNum = pAcroFormRef->GetRefObjNum();
3490   }
3491   if (m_dwInfoObjNum) {
3492     m_docStatus = PDF_DATAAVAIL_INFO;
3493   } else {
3494     if (m_bHaveAcroForm) {
3495       m_docStatus = PDF_DATAAVAIL_ACROFORM;
3496     } else {
3497       m_docStatus = PDF_DATAAVAIL_PAGETREE;
3498     }
3499   }
3500   return TRUE;
3501 }
3502 FX_BOOL CPDF_DataAvail::PreparePageItem() {
3503   CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
3504   CPDF_Reference* pRef =
3505       pRoot ? (CPDF_Reference*)pRoot->GetElement(FX_BSTRC("Pages")) : NULL;
3506   if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
3507     m_docStatus = PDF_DATAAVAIL_ERROR;
3508     return FALSE;
3509   }
3510   m_PagesObjNum = pRef->GetRefObjNum();
3511   m_pCurrentParser = (CPDF_Parser*)m_pDocument->GetParser();
3512   m_docStatus = PDF_DATAAVAIL_PAGETREE;
3513   return TRUE;
3514 }
3515 FX_BOOL CPDF_DataAvail::IsFirstCheck(int iPage) {
3516   if (m_pageMapCheckState.find(iPage) != m_pageMapCheckState.end())
3517     return FALSE;
3518
3519   m_pageMapCheckState.insert(iPage);
3520   return TRUE;
3521 }
3522 void CPDF_DataAvail::ResetFirstCheck(int iPage) {
3523   m_pageMapCheckState.erase(iPage);
3524 }
3525 FX_BOOL CPDF_DataAvail::CheckPage(IFX_DownloadHints* pHints) {
3526   FX_DWORD iPageObjs = m_PageObjList.GetSize();
3527   CFX_DWordArray UnavailObjList;
3528   for (FX_DWORD i = 0; i < iPageObjs; ++i) {
3529     FX_DWORD dwPageObjNum = m_PageObjList.GetAt(i);
3530     FX_BOOL bExist = FALSE;
3531     CPDF_Object* pObj = GetObject(dwPageObjNum, pHints, &bExist);
3532     if (!pObj) {
3533       if (bExist) {
3534         UnavailObjList.Add(dwPageObjNum);
3535       }
3536       continue;
3537     }
3538     if (pObj->GetType() == PDFOBJ_ARRAY) {
3539       CPDF_Array* pArray = pObj->GetArray();
3540       if (pArray) {
3541         int32_t iSize = pArray->GetCount();
3542         CPDF_Object* pItem = NULL;
3543         for (int32_t j = 0; j < iSize; ++j) {
3544           pItem = pArray->GetElement(j);
3545           if (pItem && pItem->GetType() == PDFOBJ_REFERENCE) {
3546             UnavailObjList.Add(((CPDF_Reference*)pItem)->GetRefObjNum());
3547           }
3548         }
3549       }
3550     }
3551     if (pObj->GetType() != PDFOBJ_DICTIONARY) {
3552       pObj->Release();
3553       continue;
3554     }
3555     CFX_ByteString type = pObj->GetDict()->GetString(FX_BSTRC("Type"));
3556     if (type == FX_BSTRC("Pages")) {
3557       m_PagesArray.Add(pObj);
3558       continue;
3559     }
3560     pObj->Release();
3561   }
3562   m_PageObjList.RemoveAll();
3563   if (UnavailObjList.GetSize()) {
3564     m_PageObjList.Append(UnavailObjList);
3565     return FALSE;
3566   }
3567   FX_DWORD iPages = m_PagesArray.GetSize();
3568   for (FX_DWORD i = 0; i < iPages; i++) {
3569     CPDF_Object* pPages = (CPDF_Object*)m_PagesArray.GetAt(i);
3570     if (!pPages) {
3571       continue;
3572     }
3573     if (!GetPageKids(m_pCurrentParser, pPages)) {
3574       pPages->Release();
3575       while (++i < iPages) {
3576         pPages = (CPDF_Object*)m_PagesArray.GetAt(i);
3577         pPages->Release();
3578       }
3579       m_PagesArray.RemoveAll();
3580       m_docStatus = PDF_DATAAVAIL_ERROR;
3581       return FALSE;
3582     }
3583     pPages->Release();
3584   }
3585   m_PagesArray.RemoveAll();
3586   if (!m_PageObjList.GetSize()) {
3587     m_docStatus = PDF_DATAAVAIL_DONE;
3588   }
3589   return TRUE;
3590 }
3591 FX_BOOL CPDF_DataAvail::GetPageKids(CPDF_Parser* pParser, CPDF_Object* pPages) {
3592   if (!pParser) {
3593     m_docStatus = PDF_DATAAVAIL_ERROR;
3594     return FALSE;
3595   }
3596   CPDF_Dictionary* pDict = pPages->GetDict();
3597   CPDF_Object* pKids = pDict ? pDict->GetElement(FX_BSTRC("Kids")) : NULL;
3598   if (!pKids) {
3599     return TRUE;
3600   }
3601   switch (pKids->GetType()) {
3602     case PDFOBJ_REFERENCE: {
3603       CPDF_Reference* pKid = (CPDF_Reference*)pKids;
3604       m_PageObjList.Add(pKid->GetRefObjNum());
3605     } break;
3606     case PDFOBJ_ARRAY: {
3607       CPDF_Array* pKidsArray = (CPDF_Array*)pKids;
3608       for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) {
3609         CPDF_Object* pKid = (CPDF_Object*)pKidsArray->GetElement(i);
3610         if (pKid && pKid->GetType() == PDFOBJ_REFERENCE) {
3611           m_PageObjList.Add(((CPDF_Reference*)pKid)->GetRefObjNum());
3612         }
3613       }
3614     } break;
3615     default:
3616       m_docStatus = PDF_DATAAVAIL_ERROR;
3617       return FALSE;
3618   }
3619   return TRUE;
3620 }
3621 FX_BOOL CPDF_DataAvail::CheckPages(IFX_DownloadHints* pHints) {
3622   FX_BOOL bExist = FALSE;
3623   CPDF_Object* pPages = GetObject(m_PagesObjNum, pHints, &bExist);
3624   if (!bExist) {
3625     m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3626     return TRUE;
3627   }
3628   if (!pPages) {
3629     if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3630       m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3631       return TRUE;
3632     }
3633     return FALSE;
3634   }
3635   if (!GetPageKids(m_pCurrentParser, pPages)) {
3636     pPages->Release();
3637     m_docStatus = PDF_DATAAVAIL_ERROR;
3638     return FALSE;
3639   }
3640   pPages->Release();
3641   m_docStatus = PDF_DATAAVAIL_PAGE;
3642   return TRUE;
3643 }
3644 FX_BOOL CPDF_DataAvail::CheckHeader(IFX_DownloadHints* pHints) {
3645   FX_DWORD req_size = 1024;
3646   if ((FX_FILESIZE)req_size > m_dwFileLen) {
3647     req_size = (FX_DWORD)m_dwFileLen;
3648   }
3649   if (m_pFileAvail->IsDataAvail(0, req_size)) {
3650     uint8_t buffer[1024];
3651     m_pFileRead->ReadBlock(buffer, 0, req_size);
3652     if (IsLinearizedFile(buffer, req_size)) {
3653       m_docStatus = PDF_DATAAVAIL_FIRSTPAGE;
3654     } else {
3655       if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3656         return FALSE;
3657       }
3658       m_docStatus = PDF_DATAAVAIL_END;
3659     }
3660     return TRUE;
3661   }
3662   pHints->AddSegment(0, req_size);
3663   return FALSE;
3664 }
3665 FX_BOOL CPDF_DataAvail::CheckFirstPage(IFX_DownloadHints* pHints) {
3666   CPDF_Dictionary* pDict = m_pLinearized->GetDict();
3667   CPDF_Object* pEndOffSet = pDict ? pDict->GetElement(FX_BSTRC("E")) : NULL;
3668   if (!pEndOffSet) {
3669     m_docStatus = PDF_DATAAVAIL_ERROR;
3670     return FALSE;
3671   }
3672   CPDF_Object* pXRefOffset = pDict ? pDict->GetElement(FX_BSTRC("T")) : NULL;
3673   if (!pXRefOffset) {
3674     m_docStatus = PDF_DATAAVAIL_ERROR;
3675     return FALSE;
3676   }
3677   CPDF_Object* pFileLen = pDict ? pDict->GetElement(FX_BSTRC("L")) : NULL;
3678   if (!pFileLen) {
3679     m_docStatus = PDF_DATAAVAIL_ERROR;
3680     return FALSE;
3681   }
3682   FX_BOOL bNeedDownLoad = FALSE;
3683   if (pEndOffSet->GetType() == PDFOBJ_NUMBER) {
3684     FX_DWORD dwEnd = pEndOffSet->GetInteger();
3685     dwEnd += 512;
3686     if ((FX_FILESIZE)dwEnd > m_dwFileLen) {
3687       dwEnd = (FX_DWORD)m_dwFileLen;
3688     }
3689     int32_t iStartPos = (int32_t)(m_dwFileLen > 1024 ? 1024 : m_dwFileLen);
3690     int32_t iSize = dwEnd > 1024 ? dwEnd - 1024 : 0;
3691     if (!m_pFileAvail->IsDataAvail(iStartPos, iSize)) {
3692       pHints->AddSegment(iStartPos, iSize);
3693       bNeedDownLoad = TRUE;
3694     }
3695   }
3696   m_dwLastXRefOffset = 0;
3697   FX_FILESIZE dwFileLen = 0;
3698   if (pXRefOffset->GetType() == PDFOBJ_NUMBER) {
3699     m_dwLastXRefOffset = pXRefOffset->GetInteger();
3700   }
3701   if (pFileLen->GetType() == PDFOBJ_NUMBER) {
3702     dwFileLen = pFileLen->GetInteger();
3703   }
3704   if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset,
3705                                  (FX_DWORD)(dwFileLen - m_dwLastXRefOffset))) {
3706     if (m_docStatus == PDF_DATAAVAIL_FIRSTPAGE) {
3707       FX_DWORD dwSize = (FX_DWORD)(dwFileLen - m_dwLastXRefOffset);
3708       FX_FILESIZE offset = m_dwLastXRefOffset;
3709       if (dwSize < 512 && dwFileLen > 512) {
3710         dwSize = 512;
3711         offset = dwFileLen - 512;
3712       }
3713       pHints->AddSegment(offset, dwSize);
3714     }
3715   } else {
3716     m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
3717   }
3718   if (!bNeedDownLoad && m_docStatus == PDF_DATAAVAIL_FIRSTPAGE_PREPARE) {
3719     m_docStatus = PDF_DATAAVAIL_DONE;
3720     return TRUE;
3721   }
3722   m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
3723   return FALSE;
3724 }
3725 CPDF_Object* CPDF_DataAvail::ParseIndirectObjectAt(FX_FILESIZE pos,
3726                                                    FX_DWORD objnum) {
3727   FX_FILESIZE SavedPos = m_syntaxParser.SavePos();
3728   m_syntaxParser.RestorePos(pos);
3729   FX_BOOL bIsNumber;
3730   CFX_ByteString word = m_syntaxParser.GetNextWord(bIsNumber);
3731   if (!bIsNumber) {
3732     return NULL;
3733   }
3734   FX_DWORD parser_objnum = FXSYS_atoi(word);
3735   if (objnum && parser_objnum != objnum) {
3736     return NULL;
3737   }
3738   word = m_syntaxParser.GetNextWord(bIsNumber);
3739   if (!bIsNumber) {
3740     return NULL;
3741   }
3742   FX_DWORD gennum = FXSYS_atoi(word);
3743   if (m_syntaxParser.GetKeyword() != FX_BSTRC("obj")) {
3744     m_syntaxParser.RestorePos(SavedPos);
3745     return NULL;
3746   }
3747   CPDF_Object* pObj = m_syntaxParser.GetObject(NULL, objnum, gennum, 0);
3748   m_syntaxParser.RestorePos(SavedPos);
3749   return pObj;
3750 }
3751 int32_t CPDF_DataAvail::IsLinearizedPDF() {
3752   FX_DWORD req_size = 1024;
3753   if (!m_pFileAvail->IsDataAvail(0, req_size)) {
3754     return PDF_UNKNOW_LINEARIZED;
3755   }
3756   if (!m_pFileRead) {
3757     return PDF_NOT_LINEARIZED;
3758   }
3759   FX_FILESIZE dwSize = m_pFileRead->GetSize();
3760   if (dwSize < (FX_FILESIZE)req_size) {
3761     return PDF_UNKNOW_LINEARIZED;
3762   }
3763   uint8_t buffer[1024];
3764   m_pFileRead->ReadBlock(buffer, 0, req_size);
3765   if (IsLinearizedFile(buffer, req_size)) {
3766     return PDF_IS_LINEARIZED;
3767   }
3768   return PDF_NOT_LINEARIZED;
3769 }
3770 FX_BOOL CPDF_DataAvail::IsLinearizedFile(uint8_t* pData, FX_DWORD dwLen) {
3771   CFX_SmartPointer<IFX_FileStream> file(
3772       FX_CreateMemoryStream(pData, (size_t)dwLen, FALSE));
3773   int32_t offset = GetHeaderOffset(file.Get());
3774   if (offset == -1) {
3775     m_docStatus = PDF_DATAAVAIL_ERROR;
3776     return FALSE;
3777   }
3778   m_dwHeaderOffset = offset;
3779   m_syntaxParser.InitParser(file.Get(), offset);
3780   m_syntaxParser.RestorePos(m_syntaxParser.m_HeaderOffset + 9);
3781   FX_BOOL bNumber = FALSE;
3782   CFX_ByteString wordObjNum = m_syntaxParser.GetNextWord(bNumber);
3783   if (!bNumber) {
3784     return FALSE;
3785   }
3786   FX_DWORD objnum = FXSYS_atoi(wordObjNum);
3787   if (m_pLinearized) {
3788     m_pLinearized->Release();
3789     m_pLinearized = NULL;
3790   }
3791   m_pLinearized =
3792       ParseIndirectObjectAt(m_syntaxParser.m_HeaderOffset + 9, objnum);
3793   if (!m_pLinearized) {
3794     return FALSE;
3795   }
3796   if (m_pLinearized->GetDict() &&
3797       m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) {
3798     CPDF_Object* pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L"));
3799     if (!pLen) {
3800       return FALSE;
3801     }
3802     if ((FX_FILESIZE)pLen->GetInteger() != m_pFileRead->GetSize()) {
3803       return FALSE;
3804     }
3805     m_bLinearized = TRUE;
3806     CPDF_Object* pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P"));
3807     if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {
3808       m_dwFirstPageNo = pNo->GetInteger();
3809     }
3810     return TRUE;
3811   }
3812   return FALSE;
3813 }
3814 FX_BOOL CPDF_DataAvail::CheckEnd(IFX_DownloadHints* pHints) {
3815   FX_DWORD req_pos = (FX_DWORD)(m_dwFileLen > 1024 ? m_dwFileLen - 1024 : 0);
3816   FX_DWORD dwSize = (FX_DWORD)(m_dwFileLen - req_pos);
3817   if (m_pFileAvail->IsDataAvail(req_pos, dwSize)) {
3818     uint8_t buffer[1024];
3819     m_pFileRead->ReadBlock(buffer, req_pos, dwSize);
3820     CFX_SmartPointer<IFX_FileStream> file(
3821         FX_CreateMemoryStream(buffer, (size_t)dwSize, FALSE));
3822     m_syntaxParser.InitParser(file.Get(), 0);
3823     m_syntaxParser.RestorePos(dwSize - 1);
3824     if (m_syntaxParser.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, dwSize)) {
3825       FX_BOOL bNumber;
3826       m_syntaxParser.GetNextWord(bNumber);
3827       CFX_ByteString xrefpos_str = m_syntaxParser.GetNextWord(bNumber);
3828       if (!bNumber) {
3829         m_docStatus = PDF_DATAAVAIL_ERROR;
3830         return FALSE;
3831       }
3832       m_dwXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str);
3833       if (!m_dwXRefOffset || m_dwXRefOffset > m_dwFileLen) {
3834         m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3835         return TRUE;
3836       }
3837       m_dwLastXRefOffset = m_dwXRefOffset;
3838       SetStartOffset(m_dwXRefOffset);
3839       m_docStatus = PDF_DATAAVAIL_CROSSREF;
3840       return TRUE;
3841     }
3842     m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3843     return TRUE;
3844   }
3845   pHints->AddSegment(req_pos, dwSize);
3846   return FALSE;
3847 }
3848 int32_t CPDF_DataAvail::CheckCrossRefStream(IFX_DownloadHints* pHints,
3849                                             FX_FILESIZE& xref_offset) {
3850   xref_offset = 0;
3851   FX_DWORD req_size =
3852       (FX_DWORD)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
3853   if (m_pFileAvail->IsDataAvail(m_Pos, req_size)) {
3854     int32_t iSize = (int32_t)(m_Pos + req_size - m_dwCurrentXRefSteam);
3855     CFX_BinaryBuf buf(iSize);
3856     uint8_t* pBuf = buf.GetBuffer();
3857     m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize);
3858     CFX_SmartPointer<IFX_FileStream> file(
3859         FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE));
3860     m_parser.m_Syntax.InitParser(file.Get(), 0);
3861     FX_BOOL bNumber = FALSE;
3862     CFX_ByteString objnum = m_parser.m_Syntax.GetNextWord(bNumber);
3863     if (!bNumber) {
3864       return -1;
3865     }
3866     FX_DWORD objNum = FXSYS_atoi(objnum);
3867     CPDF_Object* pObj = m_parser.ParseIndirectObjectAt(NULL, 0, objNum, NULL);
3868     if (!pObj) {
3869       m_Pos += m_parser.m_Syntax.SavePos();
3870       return 0;
3871     }
3872     CPDF_Dictionary* pDict = pObj->GetDict();
3873     CPDF_Object* pName = pDict ? pDict->GetElement(FX_BSTRC("Type")) : NULL;
3874     if (pName && pName->GetType() == PDFOBJ_NAME) {
3875       if (pName->GetString() == FX_BSTRC("XRef")) {
3876         m_Pos += m_parser.m_Syntax.SavePos();
3877         xref_offset = pObj->GetDict()->GetInteger(FX_BSTRC("Prev"));
3878         pObj->Release();
3879         return 1;
3880       }
3881     }
3882     pObj->Release();
3883     return -1;
3884   }
3885   pHints->AddSegment(m_Pos, req_size);
3886   return 0;
3887 }
3888 inline void CPDF_DataAvail::SetStartOffset(FX_FILESIZE dwOffset) {
3889   m_Pos = dwOffset;
3890 }
3891 #define MAX_WORD_BUFFER 256
3892 FX_BOOL CPDF_DataAvail::GetNextToken(CFX_ByteString& token) {
3893   m_WordSize = 0;
3894   uint8_t ch;
3895   if (!GetNextChar(ch)) {
3896     return FALSE;
3897   }
3898   uint8_t type = PDF_CharType[ch];
3899   while (1) {
3900     while (type == 'W') {
3901       if (!GetNextChar(ch)) {
3902         return FALSE;
3903       }
3904       type = PDF_CharType[ch];
3905     }
3906     if (ch != '%') {
3907       break;
3908     }
3909     while (1) {
3910       if (!GetNextChar(ch)) {
3911         return FALSE;
3912       }
3913       if (ch == '\r' || ch == '\n') {
3914         break;
3915       }
3916     }
3917     type = PDF_CharType[ch];
3918   }
3919   if (type == 'D') {
3920     m_WordBuffer[m_WordSize++] = ch;
3921     if (ch == '/') {
<