Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(676)

Side by Side Diff: core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp

Issue 1527823003: Fix free entry handling for cross reference v4 reading. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « core/include/fpdfapi/fpdf_parser.h ('k') | core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_unittest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698