| OLD | NEW |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include "parser_int.h" | 7 #include "parser_int.h" |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 if (m_V5Type[objnum] == 1) { | 331 if (m_V5Type[objnum] == 1) { |
| 332 return m_CrossRef[objnum]; | 332 return m_CrossRef[objnum]; |
| 333 } | 333 } |
| 334 if (m_V5Type[objnum] == 2) { | 334 if (m_V5Type[objnum] == 2) { |
| 335 return m_CrossRef[(int32_t)m_CrossRef[objnum]]; | 335 return m_CrossRef[(int32_t)m_CrossRef[objnum]]; |
| 336 } | 336 } |
| 337 return 0; | 337 return 0; |
| 338 } | 338 } |
| 339 | 339 |
| 340 FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) { | 340 FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) { |
| 341 if (!LoadCrossRefV4(xrefpos, 0, TRUE, FALSE)) { | 341 if (!LoadCrossRefV4(xrefpos, 0, TRUE)) { |
| 342 return FALSE; | 342 return FALSE; |
| 343 } | 343 } |
| 344 m_pTrailer = LoadTrailerV4(); | 344 m_pTrailer = LoadTrailerV4(); |
| 345 if (m_pTrailer == NULL) { | 345 if (m_pTrailer == NULL) { |
| 346 return FALSE; | 346 return FALSE; |
| 347 } | 347 } |
| 348 int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size")); | 348 int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size")); |
| 349 if (xrefsize <= 0 || xrefsize > (1 << 20)) { | 349 if (xrefsize <= 0 || xrefsize > (1 << 20)) { |
| 350 return FALSE; | 350 return FALSE; |
| 351 } | 351 } |
| 352 m_CrossRef.SetSize(xrefsize); | 352 m_CrossRef.SetSize(xrefsize); |
| 353 m_V5Type.SetSize(xrefsize); | 353 m_V5Type.SetSize(xrefsize); |
| 354 CFX_FileSizeArray CrossRefList, XRefStreamList; | 354 CFX_FileSizeArray CrossRefList, XRefStreamList; |
| 355 CrossRefList.Add(xrefpos); | 355 CrossRefList.Add(xrefpos); |
| 356 XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm"))); | 356 XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm"))); |
| 357 if (!CheckDirectType(m_pTrailer, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) { | 357 if (!CheckDirectType(m_pTrailer, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) { |
| 358 return FALSE; | 358 return FALSE; |
| 359 } | 359 } |
| 360 FX_FILESIZE newxrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev")); | 360 FX_FILESIZE newxrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev")); |
| 361 if (newxrefpos == xrefpos) { | 361 if (newxrefpos == xrefpos) { |
| 362 return FALSE; | 362 return FALSE; |
| 363 } | 363 } |
| 364 xrefpos = newxrefpos; | 364 xrefpos = newxrefpos; |
| 365 while (xrefpos) { | 365 while (xrefpos) { |
| 366 CrossRefList.InsertAt(0, xrefpos); | 366 CrossRefList.InsertAt(0, xrefpos); |
| 367 LoadCrossRefV4(xrefpos, 0, TRUE, FALSE); | 367 LoadCrossRefV4(xrefpos, 0, TRUE); |
| 368 nonstd::unique_ptr<CPDF_Dictionary, ReleaseDeleter<CPDF_Dictionary>> pDict( | 368 nonstd::unique_ptr<CPDF_Dictionary, ReleaseDeleter<CPDF_Dictionary>> pDict( |
| 369 LoadTrailerV4()); | 369 LoadTrailerV4()); |
| 370 if (!pDict) | 370 if (!pDict) |
| 371 return FALSE; | 371 return FALSE; |
| 372 | 372 |
| 373 if (!CheckDirectType(pDict.get(), FX_BSTRC("Prev"), PDFOBJ_NUMBER)) | 373 if (!CheckDirectType(pDict.get(), FX_BSTRC("Prev"), PDFOBJ_NUMBER)) |
| 374 return FALSE; | 374 return FALSE; |
| 375 | 375 |
| 376 newxrefpos = GetDirectInteger(pDict.get(), FX_BSTRC("Prev")); | 376 newxrefpos = GetDirectInteger(pDict.get(), FX_BSTRC("Prev")); |
| 377 if (newxrefpos == xrefpos) | 377 if (newxrefpos == xrefpos) |
| 378 return FALSE; | 378 return FALSE; |
| 379 | 379 |
| 380 xrefpos = newxrefpos; | 380 xrefpos = newxrefpos; |
| 381 XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm"))); | 381 XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm"))); |
| 382 m_Trailers.Add(pDict.release()); | 382 m_Trailers.Add(pDict.release()); |
| 383 } | 383 } |
| 384 for (int32_t i = 0; i < CrossRefList.GetSize(); i++) { | 384 for (int32_t i = 0; i < CrossRefList.GetSize(); i++) { |
| 385 if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) | 385 if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE)) |
| 386 return FALSE; | 386 return FALSE; |
| 387 } | 387 } |
| 388 return TRUE; | 388 return TRUE; |
| 389 } | 389 } |
| 390 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, | 390 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, |
| 391 FX_DWORD dwObjCount) { | 391 FX_DWORD dwObjCount) { |
| 392 if (!LoadLinearizedCrossRefV4(xrefpos, dwObjCount)) { | 392 if (!LoadLinearizedCrossRefV4(xrefpos, dwObjCount)) { |
| 393 return FALSE; | 393 return FALSE; |
| 394 } | 394 } |
| 395 m_pTrailer = LoadTrailerV4(); | 395 m_pTrailer = LoadTrailerV4(); |
| 396 if (m_pTrailer == NULL) { | 396 if (m_pTrailer == NULL) { |
| 397 return FALSE; | 397 return FALSE; |
| 398 } | 398 } |
| 399 int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size")); | 399 int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size")); |
| 400 if (xrefsize == 0) { | 400 if (xrefsize == 0) { |
| 401 return FALSE; | 401 return FALSE; |
| 402 } | 402 } |
| 403 CFX_FileSizeArray CrossRefList, XRefStreamList; | 403 CFX_FileSizeArray CrossRefList, XRefStreamList; |
| 404 CrossRefList.Add(xrefpos); | 404 CrossRefList.Add(xrefpos); |
| 405 XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm"))); | 405 XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm"))); |
| 406 xrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev")); | 406 xrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev")); |
| 407 while (xrefpos) { | 407 while (xrefpos) { |
| 408 CrossRefList.InsertAt(0, xrefpos); | 408 CrossRefList.InsertAt(0, xrefpos); |
| 409 LoadCrossRefV4(xrefpos, 0, TRUE, FALSE); | 409 LoadCrossRefV4(xrefpos, 0, TRUE); |
| 410 CPDF_Dictionary* pDict = LoadTrailerV4(); | 410 CPDF_Dictionary* pDict = LoadTrailerV4(); |
| 411 if (pDict == NULL) { | 411 if (pDict == NULL) { |
| 412 return FALSE; | 412 return FALSE; |
| 413 } | 413 } |
| 414 xrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev")); | 414 xrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev")); |
| 415 XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm"))); | 415 XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm"))); |
| 416 m_Trailers.Add(pDict); | 416 m_Trailers.Add(pDict); |
| 417 } | 417 } |
| 418 for (int32_t i = 1; i < CrossRefList.GetSize(); i++) | 418 for (int32_t i = 1; i < CrossRefList.GetSize(); i++) |
| 419 if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) { | 419 if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE)) { |
| 420 return FALSE; | 420 return FALSE; |
| 421 } | 421 } |
| 422 return TRUE; | 422 return TRUE; |
| 423 } | 423 } |
| 424 FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, | 424 FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, |
| 425 FX_DWORD dwObjCount) { | 425 FX_DWORD dwObjCount) { |
| 426 FX_FILESIZE dwStartPos = pos - m_Syntax.m_HeaderOffset; | 426 FX_FILESIZE dwStartPos = pos - m_Syntax.m_HeaderOffset; |
| 427 m_Syntax.RestorePos(dwStartPos); | 427 m_Syntax.RestorePos(dwStartPos); |
| 428 void* pResult = | 428 void* pResult = |
| 429 FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), | 429 FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 return TRUE; | 484 return TRUE; |
| 485 } | 485 } |
| 486 | 486 |
| 487 bool CPDF_Parser::FindPosInOffsets(FX_FILESIZE pos) const { | 487 bool CPDF_Parser::FindPosInOffsets(FX_FILESIZE pos) const { |
| 488 return FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), | 488 return FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), |
| 489 sizeof(FX_FILESIZE), CompareFileSize); | 489 sizeof(FX_FILESIZE), CompareFileSize); |
| 490 } | 490 } |
| 491 | 491 |
| 492 bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, | 492 bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, |
| 493 FX_FILESIZE streampos, | 493 FX_FILESIZE streampos, |
| 494 FX_BOOL bSkip, | 494 FX_BOOL bSkip) { |
| 495 FX_BOOL bFirst) { | |
| 496 m_Syntax.RestorePos(pos); | 495 m_Syntax.RestorePos(pos); |
| 497 if (m_Syntax.GetKeyword() != FX_BSTRC("xref")) | 496 if (m_Syntax.GetKeyword() != FX_BSTRC("xref")) |
| 498 return false; | 497 return false; |
| 499 | 498 |
| 500 if (!FindPosInOffsets(pos)) | 499 if (!FindPosInOffsets(pos)) |
| 501 m_SortedOffset.Add(pos); | 500 m_SortedOffset.Add(pos); |
| 502 | 501 |
| 503 if (streampos && !FindPosInOffsets(streampos)) | 502 if (streampos && !FindPosInOffsets(streampos)) |
| 504 m_SortedOffset.Add(streampos); | 503 m_SortedOffset.Add(streampos); |
| 505 | 504 |
| 506 while (1) { | 505 while (1) { |
| 507 FX_FILESIZE SavedPos = m_Syntax.SavePos(); | 506 FX_FILESIZE SavedPos = m_Syntax.SavePos(); |
| 508 FX_BOOL bIsNumber; | 507 FX_BOOL bIsNumber; |
| 509 CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber); | 508 CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber); |
| 510 if (word.IsEmpty()) | 509 if (word.IsEmpty()) |
| 511 return false; | 510 return false; |
| 512 | 511 |
| 513 if (!bIsNumber) { | 512 if (!bIsNumber) { |
| 514 m_Syntax.RestorePos(SavedPos); | 513 m_Syntax.RestorePos(SavedPos); |
| 515 break; | 514 break; |
| 516 } | 515 } |
| 517 FX_DWORD start_objnum = FXSYS_atoi(word); | 516 FX_DWORD start_objnum = FXSYS_atoi(word); |
| 518 if (start_objnum >= (1 << 20)) | 517 if (start_objnum >= (1 << 20)) |
| 519 return false; | 518 return false; |
| 520 | 519 |
| 521 FX_DWORD count = m_Syntax.GetDirectNum(); | 520 FX_DWORD count = m_Syntax.GetDirectNum(); |
| 522 m_Syntax.ToNextWord(); | 521 m_Syntax.ToNextWord(); |
| 523 SavedPos = m_Syntax.SavePos(); | 522 SavedPos = m_Syntax.SavePos(); |
| 524 FX_BOOL bFirstItem = FALSE; | |
| 525 const int32_t recordsize = 20; | 523 const int32_t recordsize = 20; |
| 526 if (bFirst) | |
| 527 bFirstItem = TRUE; | |
| 528 m_dwXrefStartObjNum = start_objnum; | 524 m_dwXrefStartObjNum = start_objnum; |
| 529 if (!bSkip) { | 525 if (!bSkip) { |
| 530 std::vector<char> buf(1024 * recordsize + 1); | 526 std::vector<char> buf(1024 * recordsize + 1); |
| 531 char* pBuf = pdfium::vector_as_array(&buf); | 527 char* pBuf = pdfium::vector_as_array(&buf); |
| 532 pBuf[1024 * recordsize] = '\0'; | 528 pBuf[1024 * recordsize] = '\0'; |
| 533 int32_t nBlocks = count / 1024 + 1; | 529 int32_t nBlocks = count / 1024 + 1; |
| 534 FX_BOOL bFirstBlock = TRUE; | |
| 535 for (int32_t block = 0; block < nBlocks; block++) { | 530 for (int32_t block = 0; block < nBlocks; block++) { |
| 536 int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024; | 531 int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024; |
| 537 m_Syntax.ReadBlock(reinterpret_cast<uint8_t*>(pBuf), | 532 m_Syntax.ReadBlock(reinterpret_cast<uint8_t*>(pBuf), |
| 538 block_size * recordsize); | 533 block_size * recordsize); |
| 539 for (int32_t i = 0; i < block_size; i++) { | 534 for (int32_t i = 0; i < block_size; i++) { |
| 540 FX_DWORD objnum = start_objnum + block * 1024 + i; | 535 FX_DWORD objnum = start_objnum + block * 1024 + i; |
| 541 char* pEntry = pBuf + i * recordsize; | 536 char* pEntry = pBuf + i * recordsize; |
| 542 if (pEntry[17] == 'f') { | 537 if (pEntry[17] == 'f') { |
| 543 if (bFirstItem) { | |
| 544 objnum = 0; | |
| 545 bFirstItem = FALSE; | |
| 546 } | |
| 547 if (bFirstBlock) { | |
| 548 FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry); | |
| 549 int32_t version = FXSYS_atoi(pEntry + 11); | |
| 550 if (offset == 0 && version == 65535 && start_objnum != 0) { | |
| 551 start_objnum--; | |
| 552 objnum = 0; | |
| 553 } | |
| 554 } | |
| 555 m_CrossRef.SetAtGrow(objnum, 0); | 538 m_CrossRef.SetAtGrow(objnum, 0); |
| 556 m_V5Type.SetAtGrow(objnum, 0); | 539 m_V5Type.SetAtGrow(objnum, 0); |
| 557 } else { | 540 } else { |
| 558 FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry); | 541 FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry); |
| 559 if (offset == 0) { | 542 if (offset == 0) { |
| 560 for (int32_t c = 0; c < 10; c++) { | 543 for (int32_t c = 0; c < 10; c++) { |
| 561 if (!std::isdigit(pEntry[c])) | 544 if (!std::isdigit(pEntry[c])) |
| 562 return false; | 545 return false; |
| 563 } | 546 } |
| 564 } | 547 } |
| 565 m_CrossRef.SetAtGrow(objnum, offset); | 548 m_CrossRef.SetAtGrow(objnum, offset); |
| 566 int32_t version = FXSYS_atoi(pEntry + 11); | 549 int32_t version = FXSYS_atoi(pEntry + 11); |
| 567 if (version >= 1) { | 550 if (version >= 1) { |
| 568 m_bVersionUpdated = TRUE; | 551 m_bVersionUpdated = TRUE; |
| 569 } | 552 } |
| 570 m_ObjVersion.SetAtGrow(objnum, version); | 553 m_ObjVersion.SetAtGrow(objnum, version); |
| 571 if (m_CrossRef[objnum] < m_Syntax.m_FileLen && | 554 if (m_CrossRef[objnum] < m_Syntax.m_FileLen && |
| 572 !FindPosInOffsets(m_CrossRef[objnum])) { | 555 !FindPosInOffsets(m_CrossRef[objnum])) { |
| 573 m_SortedOffset.Add(m_CrossRef[objnum]); | 556 m_SortedOffset.Add(m_CrossRef[objnum]); |
| 574 } | 557 } |
| 575 m_V5Type.SetAtGrow(objnum, 1); | 558 m_V5Type.SetAtGrow(objnum, 1); |
| 576 } | 559 } |
| 577 if (bFirstBlock) { | |
| 578 bFirstBlock = FALSE; | |
| 579 } | |
| 580 } | 560 } |
| 581 } | 561 } |
| 582 } | 562 } |
| 583 m_Syntax.RestorePos(SavedPos + count * recordsize); | 563 m_Syntax.RestorePos(SavedPos + count * recordsize); |
| 584 } | 564 } |
| 585 return !streampos || LoadCrossRefV5(&streampos, FALSE); | 565 return !streampos || LoadCrossRefV5(&streampos, FALSE); |
| 586 } | 566 } |
| 587 | 567 |
| 588 FX_BOOL CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) { | 568 FX_BOOL CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) { |
| 589 if (!LoadCrossRefV5(&xrefpos, TRUE)) { | 569 if (!LoadCrossRefV5(&xrefpos, TRUE)) { |
| (...skipping 971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1561 if (!IsLinearizedFile(pFileAccess, offset)) { | 1541 if (!IsLinearizedFile(pFileAccess, offset)) { |
| 1562 m_Syntax.m_pFileAccess = NULL; | 1542 m_Syntax.m_pFileAccess = NULL; |
| 1563 return StartParse(pFileAccess, bReParse, bOwnFileRead); | 1543 return StartParse(pFileAccess, bReParse, bOwnFileRead); |
| 1564 } | 1544 } |
| 1565 if (!bReParse) { | 1545 if (!bReParse) { |
| 1566 m_pDocument = new CPDF_Document(this); | 1546 m_pDocument = new CPDF_Document(this); |
| 1567 } | 1547 } |
| 1568 FX_FILESIZE dwFirstXRefOffset = m_Syntax.SavePos(); | 1548 FX_FILESIZE dwFirstXRefOffset = m_Syntax.SavePos(); |
| 1569 FX_BOOL bXRefRebuilt = FALSE; | 1549 FX_BOOL bXRefRebuilt = FALSE; |
| 1570 FX_BOOL bLoadV4 = FALSE; | 1550 FX_BOOL bLoadV4 = FALSE; |
| 1571 if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE, FALSE)) && | 1551 if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE)) && |
| 1572 !LoadCrossRefV5(&dwFirstXRefOffset, TRUE)) { | 1552 !LoadCrossRefV5(&dwFirstXRefOffset, TRUE)) { |
| 1573 if (!RebuildCrossRef()) { | 1553 if (!RebuildCrossRef()) { |
| 1574 return PDFPARSE_ERROR_FORMAT; | 1554 return PDFPARSE_ERROR_FORMAT; |
| 1575 } | 1555 } |
| 1576 bXRefRebuilt = TRUE; | 1556 bXRefRebuilt = TRUE; |
| 1577 m_LastXRefOffset = 0; | 1557 m_LastXRefOffset = 0; |
| 1578 } | 1558 } |
| 1579 if (bLoadV4) { | 1559 if (bLoadV4) { |
| 1580 m_pTrailer = LoadTrailerV4(); | 1560 m_pTrailer = LoadTrailerV4(); |
| 1581 if (m_pTrailer == NULL) { | 1561 if (m_pTrailer == NULL) { |
| (...skipping 3368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4950 if (!m_pLinearizedDict) | 4930 if (!m_pLinearizedDict) |
| 4951 return -1; | 4931 return -1; |
| 4952 CPDF_Array* pRange = m_pLinearizedDict->GetArray(FX_BSTRC("H")); | 4932 CPDF_Array* pRange = m_pLinearizedDict->GetArray(FX_BSTRC("H")); |
| 4953 if (!pRange) | 4933 if (!pRange) |
| 4954 return -1; | 4934 return -1; |
| 4955 CPDF_Object* pStreamLen = pRange->GetElementValue(1); | 4935 CPDF_Object* pStreamLen = pRange->GetElementValue(1); |
| 4956 if (!pStreamLen) | 4936 if (!pStreamLen) |
| 4957 return -1; | 4937 return -1; |
| 4958 return pStreamLen->GetInteger(); | 4938 return pStreamLen->GetInteger(); |
| 4959 } | 4939 } |
| OLD | NEW |