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