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