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