diff --git a/src/core/catalog.js b/src/core/catalog.js index 9a19e45e9..acb72328c 100644 --- a/src/core/catalog.js +++ b/src/core/catalog.js @@ -22,15 +22,16 @@ import { isRefsEqual, isStream, Name, + Ref, RefSet, RefSetCache, } from "./primitives.js"; import { collectActions, MissingDataException, - PageDictMissingException, recoverJsURL, toRomanNumerals, + XRefEntryException, } from "./core_utils.js"; import { createPromiseCapability, @@ -1212,14 +1213,96 @@ class Catalog { nodesToVisit.push(kids[last]); } } - capability.reject( - new PageDictMissingException(`Page index ${pageIndex} not found.`) - ); + capability.reject(new Error(`Page index ${pageIndex} not found.`)); } next(); return capability.promise; } + /** + * Eagerly fetches the entire /Pages-tree; should ONLY be used as a fallback. + * @returns {Map} + */ + getAllPageDicts() { + const queue = [{ currentNode: this.toplevelPagesDict, posInKids: 0 }]; + const visitedNodes = new RefSet(); + const map = new Map(); + let pageIndex = 0; + + function addPageDict(pageDict, pageRef) { + map.set(pageIndex++, [pageDict, pageRef]); + } + function addPageError(msg) { + map.set(pageIndex++, [new FormatError(msg), null]); + } + + while (queue.length > 0) { + const queueItem = queue[queue.length - 1]; + const { currentNode, posInKids } = queueItem; + + let kids; + try { + kids = currentNode.get("Kids"); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + if (ex instanceof XRefEntryException) { + throw ex; + } + } + if (!Array.isArray(kids)) { + addPageError("Page dictionary kids object is not an array."); + break; + } + + if (posInKids >= kids.length) { + queue.pop(); + continue; + } + + const kidObj = kids[posInKids]; + let obj; + if (kidObj instanceof Ref) { + try { + obj = this.xref.fetch(kidObj); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + if (ex instanceof XRefEntryException) { + throw ex; + } + } + // Prevent circular references in the /Pages tree. + if (visitedNodes.has(kidObj)) { + addPageError("Pages tree contains circular reference."); + break; + } + visitedNodes.put(kidObj); + } else { + // Prevent errors in corrupt PDF documents that violate the + // specification by *inlining* Page dicts directly in the Kids + // array, rather than using indirect objects (see issue9540.pdf). + obj = kidObj; + } + if (!(obj instanceof Dict)) { + addPageError( + "Page dictionary kid reference points to wrong type of object." + ); + break; + } + + if (isDict(obj, "Page") || !obj.has("Kids")) { + addPageDict(obj, kidObj instanceof Ref ? kidObj : null); + } else { + queue.push({ currentNode: obj, posInKids: 0 }); + } + queueItem.posInKids++; + } + return map; + } + getPageIndex(pageRef) { const cachedPageIndex = this.pageIndexCache.get(pageRef); if (cachedPageIndex !== undefined) { diff --git a/src/core/core_utils.js b/src/core/core_utils.js index 0fd7f3014..bea871789 100644 --- a/src/core/core_utils.js +++ b/src/core/core_utils.js @@ -60,12 +60,6 @@ class MissingDataException extends BaseException { } } -class PageDictMissingException extends BaseException { - constructor(msg) { - super(msg, "PageDictMissingException"); - } -} - class ParserEOFException extends BaseException { constructor(msg) { super(msg, "ParserEOFException"); @@ -547,7 +541,6 @@ export { isWhiteSpace, log2, MissingDataException, - PageDictMissingException, ParserEOFException, parseXFAPath, readInt8, diff --git a/src/core/document.js b/src/core/document.js index 21607253a..0706eb888 100644 --- a/src/core/document.js +++ b/src/core/document.js @@ -50,7 +50,6 @@ import { getInheritableProperty, isWhiteSpace, MissingDataException, - PageDictMissingException, validateCSSFont, XRefEntryException, XRefParseException, @@ -1354,14 +1353,16 @@ class PDFDocument { } async checkLastPage(recoveryMode = false) { - this.catalog.setActualNumPages(); // Ensure that it's always reset. + const { catalog, pdfManager } = this; + + catalog.setActualNumPages(); // Ensure that it's always reset. let numPages; try { await Promise.all([ - this.pdfManager.ensureDoc("xfaFactory"), - this.pdfManager.ensureDoc("linearization"), - this.pdfManager.ensureCatalog("numPages"), + pdfManager.ensureDoc("xfaFactory"), + pdfManager.ensureDoc("linearization"), + pdfManager.ensureCatalog("numPages"), ]); if (this.xfaFactory) { @@ -1369,13 +1370,13 @@ class PDFDocument { } else if (this.linearization) { numPages = this.linearization.numPages; } else { - numPages = this.catalog.numPages; + numPages = catalog.numPages; } - if (numPages === 1) { - return; - } else if (!Number.isInteger(numPages)) { + if (!Number.isInteger(numPages)) { throw new FormatError("Page count is not an integer."); + } else if (numPages <= 1) { + return; } await this.getPage(numPages - 1); } catch (reason) { @@ -1385,24 +1386,48 @@ class PDFDocument { // subsequent `this.getPage` calls. await this.cleanup(); - let pageIndex = 1; // The first page was already loaded. - while (true) { - try { - await this.getPage(pageIndex); - } catch (reasonLoop) { - if (reasonLoop instanceof PageDictMissingException) { - break; - } - if (reasonLoop instanceof XRefEntryException) { - if (!recoveryMode) { - throw new XRefParseException(); - } - break; + let pagesTree; + try { + pagesTree = await pdfManager.ensureCatalog("getAllPageDicts"); + } catch (reasonAll) { + if (reasonAll instanceof XRefEntryException) { + if (!recoveryMode) { + throw new XRefParseException(); } } - pageIndex++; + catalog.setActualNumPages(1); + return; } - this.catalog.setActualNumPages(pageIndex); + + for (const [pageIndex, [pageDict, ref]] of pagesTree) { + let promise; + if (pageDict instanceof Error) { + promise = Promise.reject(pageDict); + + // Prevent "uncaught exception: Object"-messages in the console. + promise.catch(() => {}); + } else { + promise = Promise.resolve( + new Page({ + pdfManager, + xref: this.xref, + pageIndex, + pageDict, + ref, + globalIdFactory: this._globalIdFactory, + fontCache: catalog.fontCache, + builtInCMapCache: catalog.builtInCMapCache, + standardFontDataCache: catalog.standardFontDataCache, + globalImageCache: catalog.globalImageCache, + nonBlendModesSet: catalog.nonBlendModesSet, + xfaFactory: null, + }) + ); + } + + this._pagePromises.set(pageIndex, promise); + } + catalog.setActualNumPages(pagesTree.size); } } diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index d8f7c6a11..3fd1026aa 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -492,6 +492,8 @@ !xfa_issue14315.pdf !poppler-67295-0.pdf !poppler-85140-0.pdf +!poppler-395-0-fuzzed.pdf +!GHOSTSCRIPT-698804-1-fuzzed.pdf !poppler-91414-0-53.pdf !poppler-91414-0-54.pdf !poppler-742-0-fuzzed.pdf diff --git a/test/pdfs/GHOSTSCRIPT-698804-1-fuzzed.pdf b/test/pdfs/GHOSTSCRIPT-698804-1-fuzzed.pdf new file mode 100644 index 000000000..d0457b26a --- /dev/null +++ b/test/pdfs/GHOSTSCRIPT-698804-1-fuzzed.pdf @@ -0,0 +1,69 @@ +%PDF-1.4 +% + +1 0 obj +<< + /Type /Catalog + /Outline 2 0 R + /Pages 3 0 R +>> +endobj + +2 0 obj +<< + /Type /Outlines + /Count 0 +>> +endobj + +3 0 obj +<< + /Type /Pages + /Kids [ 4 0 R ] + /Count 1 +>> +endobj + +4 0 obj +<< + /Type /Page + /Parent 3 0 R + /MediaBox [ 0 0 612 792 ] + /Contents 5 0 R + /Resources << + /ProcSet 6 0 R + >> +>> +endobj + +5 0 obj +<< + /Length 0 +>> +stream +endstream +endobj + +6 0 obj +[ /PDF ] +endobj + +xref +0 2 +0000000000 65536 f +0000000016 00000 n +00000004294967296 3 +0000000138 00000 n +0000000204 00000 n +0000000342 00000 n + + +trailer +<< + /Size 7 + /Root 1 0 R +>> + +startxref +418 +%%EOF diff --git a/test/pdfs/poppler-395-0-fuzzed.pdf b/test/pdfs/poppler-395-0-fuzzed.pdf new file mode 100644 index 000000000..24f5fff60 --- /dev/null +++ b/test/pdfs/poppler-395-0-fuzzed.pdf @@ -0,0 +1,262 @@ +%PDF-1.7 +% +1 0 obj +<< +/Type /Catalog +/Pages 2 0 R +/AcroForm 3 0 R +>> +endobj +4 0 obj +<< +/Creator +/Producer +>> +endobj +3 0 obj +<< +/Count 1 +/Kids [5 0 R] +/Type /Pages +>> +endobj +3 0 obj +<< +/Fields [6 0 R] +/SigFlags 3 +>> +endobj +5 0 obj +<< +/Type /Page +/Parent 2 0 R +/MediaBox [0 0 612 792] +/Contents 7 0 R +/Resources << +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +/Font << +/F1.0 8 0 R +/F2.0 9 0 R +>> +>> +/Annots [10 0 R 11 0 R 6 0 R] +>> +endobj +6 0 obj +<< +/Rect [88 651 540 604] +/Border [0 0 0] +/CreationDate (D:20140724183756-04'00') +/M (D:20140724183756-04'00') +/P 5 0 R +/V 12 0 R +/T (undef86349) +/Subtype /Widget +/FT /Sig +/DA (/F1 10 Tf 0 g) +>> +endobj +7 0 obj +<< +/Length 252 +/Filter [/FlateDecode] +>> +stream +x.2'4D 2s2cqT)3Ȁ>Is12V@~(rz1/b]7A PnM1 EwNPc໑"HЭ[-Э_jF|un.4'܃g +BuucN5 [~ŠQESq:gC7  TByS}ǡ:K5lb"͘hY.BF`™Uʑ-D< +endstream +endobj +8 0 obj +<< +/Type /Font +/BaseFont /AAAAAA+Rufscript +/Subtype /TrueType +/FontDescriptor 13 0 R +/FirstChar 32 +/LastChar 255 +/Widths [561 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 572 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 480 +324 591 479 171 591 591 591 591 487 387 +591 591 591 379 370 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591 591 591 591 591 591 591 +591 591 591 591] +/ToUnicode 14 0 R +>> +endobj +9 0 obj +<< +/Type /Font +/Subtype /Type1 +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +>> +endobj +10 0 obj +<< +/Rect [89 650 539 605] +/Contents <0A205068696C20536D697468> +/DA (/Rufscript 18 Tf 0 0 0.5 rg ) +/F 132 +/C [1 1 0.6] +/Border [1 1 1] +/CreationDate (D:20140724183756-04'00') +/M (D:20140724183756-04'00') +/P 1 0 R +/Subtype /FreeText +>> +endobj +11 0 obj +<< +/Rect [89 595 539 505] +/Contents <0A20726561736F6E3A205369676E65640A2062793A205068696C20536D6974680A20656D61696C3A207068696C2E736D69746840746573742E636F6E7365637465642E636F6D0A2061743A20323031342D30372D32345431383A33373A35362D30343A30300A2049443A203534393435363738330A20546F20636865636B207369676E61747572652076616C69646974792C207365653A2068747470733A2F2F7365637572652E72657073652E636F6D2F7365637572655F7265736F75726365732F6469677369672E68746D6C0A> +/DA (/Helv 10 Tf 0 0 0.2 rg) +/F 132 +/C [0.8 0.8 0.8] +/Border [1 1 1] +/CreationDate (D:20140724183756-04'00') +/M (D:20140724183756-04'00') +/P 5 0 R +/Subtype /FreeText +>> +endobj +12 0 obj +<< +/Prop_Build << +/Filter << +/Name /Adobe.PPKMS +/R 131101 +/Date (2014-07-24 18:37:56 -0400) +>> +/SigQ << +/Preview false +/R 131101 +>> +/PubSec << +/NonEFontNoWarn false +/Date (2014-07-24 18:37:56 -0400) +/R 131101 +>> +/App << +/TrustedMode false +/OS [/Win] +/R 458752 +/Name /Exchange-Pro +>> +>> +/M (D:20140724223756Z00'00) +/Contents <308207C506092A864886F70D010702A08207B6308207B2020101310F300D06096086480165030402010500302306092A864886F70D010701A0160414BD798053C80E2274B616F02A9FEFC2555E69D170A08204D3308204CF308202B7A003020102020101300D06092A864886F70D0101050500308185310B3009060355040613025553311630140603550408130D4D617373616368757365747473310F300D060355040713065175696E637931123010060355040A1309524550534520496E63311A301806035504031311524550534520496E63205369676E696E67311D301B06092A864886F70D010901160E696E666F4072657073652E636F6D301E170D3134303331383135303131375A170D3135303331383135303131375A3081AD311B3019060A0992268993F22C6401010C0B74657374757365723132333113301106035504030C0A5068696C20536D697468310C300A060355040B0C0343454F3111300F060355040A0C0854657374204C4C43310F300D06035504070C065175696E6379310B300906035504080C024D41310C300A06035504061303555341312C302A06092A864886F70D010901161D7068696C2E736D69746840746573742E636F6E7365637465642E636F6D30820122300D06092A864886F70D01010105000382010F003082010A0282010100E44C2EE08A6553265484B816EDE91D7E473A845E7D097A7CC8708F541D31A8CCD72068E0CFA080B88DFA2305C43E46527EEC5D53E7249FBE89A4CCD62A28FF98F25CC9D81F7663FEBE337476BA7E2422902FA4E083C10A62098D731898293F1825482BDB1626C9753E1137D4308DDD6F47F963D75D4622C9BCB9BDB260F3D2653475997A58D24510DE31E469A2F85347CA5DBA6E15B6B656E16EE8B525D96D73B9A93B9437EE71DF14D88E1C666B287BE47A23FAB18A9150D185301E7C859F5E4F366B9631646A6E999A6CEA6AC2B6EFCF2B0234F86A53E62E7AC3BD1D8A23DF9117B66E2B4A7D9015AF83FCA12F996CC5300154AADBD06CC533C23257E6B8D30203010001A320301E300C0603551D130101FF04023000300E0603551D0F0101FF040403020780300D06092A864886F70D01010505000382020100678A3957C00690993D344E933927B6867C0C75A41A83DA4A58E469C64D175D662559FACB91283070B0E2CEB178DCC6EF41BCC58767D9A3F549932D562522BF701F6584A665D74004BB70B9DD14E1DEEB8EE015872D378E0F0AA039F516B1F9D1BE6199D565884CA5D104DF67FCD238C463F026E07CE09A6D6C459A95C98B8CD5C483D0A8CF85529891FDF620C3682EB92B498FB2D99EFBD3D1FA3E223EF56C1B27CCB4C1067986B107A9965B19840673FB9CADC0C5056E0CD1F158DE1365D626866825D46D51D638ACA98D5C032D7163616B0FD106D6141A4394A04E7FA306840830130487A69A3CEF3A40E17544E9B64F423ECA41D6F4DA4774ED1A2CDA4D11C8E08C4778E2A230606A83D3F19823F742309BF93B0D7D64AF21C23F571540C13EF6C12041531E3D5614E0EB61A208CFB0CA788002BF0E29D5D2ECEDAA912BD76FA363F428A714D1A793E95B4A4C5D43B10DAC29D7EF73720474CA0E4312819869024ED02776DF6E3350E5B9A31EE117B1FF24F70A72E3B4572AAD10B6AFC09B0A42423714E489F73A3340CB59682B6F0671FEB01E79CCB678B71B7A70304DE2204A90FFC2F9F0BED4B3EBF6442473147D8347722356C911FA0A50B27DC20E00BF35C9833753795ED6F79403943288C51D993BAC15DEEB5F269C7715288085EF1666B30372DF33985F85BF0DAD4F1F4C2FA8AD5891134D491EF0F9EB2D81B4153182029E3082029A02010130818B308185310B3009060355040613025553311630140603550408130D4D617373616368757365747473310F300D060355040713065175696E637931123010060355040A1309524550534520496E63311A301806035504031311524550534520496E63205369676E696E67311D301B06092A864886F70D010901160E696E666F4072657073652E636F6D020101300D06096086480165030402010500A081E4301806092A864886F70D010903310B06092A864886F70D010701301C06092A864886F70D010905310F170D3134303732343232333735375A302F06092A864886F70D0109043122042079DD7CE8C93AC5AD655570F3F160B680554D1F1781FED651F075F499D6D7DBBB307906092A864886F70D01090F316C306A300B060960864801650304012A300B0609608648016503040116300B0609608648016503040102300A06082A864886F70D0307300E06082A864886F70D030202020080300D06082A864886F70D0302020140300706052B0E030207300D06082A864886F70D0302020128300D06092A864886F70D01010105000482010084EA4441BA1618C45BB6619E387BE3036693F5FBB539AEA0226283FFC24302445CDC385ABBC578D510BD6AD927D2C2E9A1A9DBCD44B2F6EB98E5F1047182D4B2E9751BB653AF1A877F17FC5893BA5D0D06D84879E3B381D89CC7901F76F99FAE08C47304EE4BBCF8525B5FC89E2CCBDF21F2EFC9BF3B2A1D9387F161958C613BD770F9399C789117359E447CBB4B51EAAB6FD4AF1B9F26E0B15491DFCC2C920E0CF07BFA3C6F9167F0B602F573C59D8EADCF35822E5F8D3758F2C425350076BA537940DFA26D1B925967CEEF9674F0CEE309EF611F549736EC47EDDA6FA00F5F830A955BE4FF5290976EE70D2A9C290AA53519B745496395B06867049B08BF4A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000> +/Filter /Adobe.PPKMS +/SubFilter /adbe.pkcs7.sha1 +/ByteRange [0 9001 13245 653] +/Location (Quincy, MA, USA) +/ContactInfo (phil.smith@test.consected.com) +/Reason (Signed) +/Type /Sig +>> +endobj +13 0 obj +<< +/Type /FontDescriptor +/FontName /AAAAAA+Rufscript +/FontFile2 15 0 R +/FontBBox [-88 -504 918 806] +/Flags 4 +/StemV 0 +/ItalicAngle 0 +/Ascent 800 +/Descent -199 +/CapHeight 800 +/XHeight 0 +>> +endobj +14 0 obj +<< +/Length 2439 +/Filter [/A85] +>> +stream +01/6Q-Aj/=20K!H+$9U4T5!1MQ2IScV40Aj/=20K!H+$9U4#5!1@V0+G4:4A]W4>8HD2*M@00fD3X0JG4>4pj!1M +Q2.JfW4>gY54>8HHA3L>0Aj/R$#$8HH2*HF2*M@01H%E4pjD-Aj/=20J[4>8I#3'I[33A=20J[4>8I#3'I[33A8HG0gfPZ0K(pT +$9U4T5!1MQ2IScV40Aj/=20K!H+$9U4#5!1@V0+G4:4A]W4>8HD=20K!H+$9U4#5!1@V0+G4:4pjD,1 +Hmo3HY0JGC?4pjD11HmoT0K(^N$>"*cMQ2D@<%4>noXZ0JG:4pjD22U4T5!1MQ2IScV4+(5!1MQ1H7Q*4>Su]44>8HD3Bdd40k!7.0JG4i4pjD,@Qln.0JR$#$8HH2*HF2*M@01H%E4pjD-Aj/=20J[4>8I#3'I[33A=20J[4>8I#3'I[33A8HG0gfPZ0K(pT +$9U4T5!1MQ2IScV40Aj/=20K!H+$9U4#5!1@V0+G4:4A]W4>8HD2*M@00fD3X0JG4>4pj!1M +Q2.JfW4>gY54>8HHA3L>_2.\s60JG@q4pjD0Aj/=20K!H+$9U4#5!1@V0+G4A3L>_2.\s60JG@q4pjD0Aj/=20K!H+$9U4#5!1@V0+G4:4pjD,1 +HmoT0JP@I$9U%"5!1MQ0f2'$4>A]W4>8HD2*!1MQ2dnlW4?$_54>8HJ@Qk,]2e,$60JGFq4pjD2A3N+00K3N+$9U7Y5!1MQ2e> +/[4?$k94>8HJAj-Pa3&!N1H%E4pjD-Aj/=20J[4>8I#3'I[33A=20J[4>8I#3'I[33A8HG0gfPZ0K(pT +$9U4T5!1MQ2IScV40Aj/=20K!H+$9U4#5!1@V0+G4:4A]W4>8HD2*M@00fD3X0JG4>4pj!1M +Q2.JfW4>gY54>8HHA3L>_2.\s60JG@q4pjD0Aj/=20K!H+$9U4#5!1@V0+G4:4pjD,1 +HmoT0JP@I$9U%"5!1MQ0f2'$4>A]W4>8HD2*!1MQ5!1MQ0f2'$4>A]W4>8HD2*M@00fD3X0JG4>4pjD,2a0>X0JPLM$C?4pjD11HmoT0K(^N$>"*cMQ2D@<%4>noXZ0JG:4pjD22U4T5!1MQ2IScV4+(5!1MQ1H7Q*4>Su]44>8HD3Bdd40k!7.0JG4i4pjD,@Qln.0JR$#$8HH2*HF2*M@01H%E4pjD-Aj/=20J[4>8I#3'I[33A=21@V0+G4:4pjD,1 +Hmo4pjD,@Qln.0JR$#$8HH2*HF2*M@01H%E4pjD-Aj/=2>8HH:4pjD,1 +HmoT0JP@I$9U%"5!1MQ0f2'$4>A]W4>8HD2*!1MQ5!1MQ0f2'$4>A]W4>8HD2*M@00fD3X0JG4>4pjD,2a0>X0JPLM$9U%&5!1 +MQ0fV?(4>Ai[4>fHD2*M@00fD3X0JG4>4pj!1M +Q2.JfW4>gY54>8HHA3L>_2.\s60JG@q4pjD0Aj/=20K!H+$9U4#5!1@V0+G4:4pjD,1 +HmoT0JP@I$9U%"5!1MQ0f2'$4>A]W49U%&5!1 +MQ0fV?(4>Ai[4Y>noX4>8HI0 +g5q,2DR2*O,V0P!(*$9U:+5!1MQA7Ie14?/ +]V4>^S44>8HGA3L>_1hAj5,8`4>8I#0g5q,3&j)a0JMQ1h/ +]V4>^S44>8HGA3L>_1hAj50JG=p4pjD/AM +Q2.JfW4>gY54>8HHA3L>_2.\s60JG@q4pjD0Aj/R$#$8HH2*HF2*M@01H%E4pjD-Aj/=BfPZ0K(pT +$9U4T5!1MQ2IScV40Aj/=20K!H+$9U4#5!1@V0+G4:4A]W4>?#2_4>8HJ2a.R22`Nu`0JGFF4pjD23B4>gY54>8HHA3L>_2.\s60JG@q4pjD0Aj/=20K!H+$9U4#5!1@V0+G4:4pjD,1 +HmoT0JP@I$9U%"5!1MQ0f2'$4>A]W4>8HD20J[4>8I#3'I[33A8HG0gfPZ0K(pT +$9U4T5!1MQ2IScV40Aj/=20K!H+$9U4#5!1@V0+G4:4A]W4>8]0J0fD3X0JG4>2dnlW4?$_54>8HJ@Qk,]2e,$60JGFq4pjD2A3N+00K30JGI?4pjD30g7]R0Olt($9U:'5!1MQ@lHT0JP@I$9U%"5!1MQ0f2'$4>A]W4>8HD2*M@00fD3X0JG4>4pjD,2a0>X0JPLM$9U%&5!1 +MQ0fV?(4>Ai[4>f]0J0fD3X0JG4>4pj!1D23BfPZ0 +K2!U$9U7U5!1MQ2dnlW4?$_54>8HJ@Qk,]2e,$60JGFq4pjD2A3N+00K3N+$9U7Y5!1MQ2e> +/[4?$k94>8HJAj-Pa3&!NY0JGI?4pjD30g7]R0Olt^4>8HI2a.R22E3l_0JGCE4pjD13 +endstream +endobj +15 0 obj +<< +/Length 11955 +/Length1 7700 +/Filter [/AHx] +>> +stream +007F0000000B003000050030636D61700B12131C000000BC00000112676C79662928E82400}001D00000064066F6361074608FE0000081000000018686D7478267201E3000008280000002C686865610D1C032700000854000000246D6178700052009000000878000000204F532F:2643E6A620000089800000056706F737400A50193000008F000000038E61]D6532105C640000928750014AD68656164EFFDBA6600001DD800000036637674200044043700001E10000000040000000100010000000000C00000106000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000%0000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000335000506000000000708000000090A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000`00000000000000000000000002006B00C603BC059C003000700003911250325211125D6028705FD15034FFCAF0543FB703042857FB2A020000000001FFDDFFEC049E04BE001D00002536353427260326243534253633201716151423200706151417161023220212010B203508FE3301DC896F01C51F07CFFEF303013283F88304F41E33AAE0134291E911210054F131054032348374AAFD9200020054001A03E204140016004A000001363F0135343220F010607060706151417163332333601062322272627263534373637363332171611407023220E0107141514171617163323736333217161514070623222726232201DF515042602130402C3C3 050C020611020129018C243F69B3A35A237082B96F442C198D2ADF3722288104DD3D913A2C4020101124253542301E0A07040615023E2555463438253205373103042D12184B0CFE22102D2ADD56508F7A8E5433167B663731FF004F0D2003021E191A09030804141B211B231A03010000000101AFF670294053E005A0000010F01061514171617141514070623222E02022726232223060706232227262726353437363336373635343526353437363332171615140706230E27$62B013031222726232207060706151471633323736333217161714151401D22707020C1402090A1E5F92031D0A0D0B14030218130B100D0F1E1B021E2601520D0C011E475B434E7908281003032F0701071A0E0C09082E120B0A1F2B0303211A4F16140202911634991F447ECB7A100E601315287BC901A0191503140BE60D6D08071C0C0F061A167C13160A09023562F49310C0B350229120B0620623A23220CF00101100E1E04056A0000000001001FFFBA03B3063A0051000001263534253233321716131615140706232235343736=53427262726232207061514171615140706232227262726353435343534032726343727263534373633321716151415061417161514071233303134012201011C090969358D31072434463707071D0656211E1917B3120B22110F4F93221708380E02021207090B250F147B09090B032701020107079D082157FEE32926584E6F6526332C31667D1A34140E67C13E482B1C3104A832B3F2875090B010287018FC9055552A6452B30111603192E020267B74E69402016FE2D03000000020056FFF6013D05A9000D002800001316151407062322353492363332030227343534373633321716151415061514171615140706232226F63D411C154C022BF353203282922120F290119100073C322B055D593C3F220E307078FFAE601337C0808702F300C205E0C0D181C7D18971309253C0000010046FFFE03B503BD002B00003726032635343736333215141514151033323736371233321716170603062322272603022322070207062322D352330804092D6F2F10160824A9A25451371E080B022B2137060A164B3B5AC20D0E0C453CE020641261B0C1D5901011C1AFE6C2E145301876644DA0CFE315530BE0124016EDEFE1F010200000000020025000403B503FB001D003B0000372627263534373637363733332171615140706151417141510050623222716333237363736353427262322151417303114070623303122070615146D863C0535472E6D9445367E351Z050B01FEC7834A08040A132E668F220D2 2A14120B4344020B51340516B4111B55BAF5377D31177727170C08154C11120C{BFEBBEA64D40C4D6CB143304E181E1915240A1819C37D482900010010FFEA030B045E002F000004263534373635342027263534373E012536333217161514070E01071615140706230615141716417161514 +706423018F503591EAF72C1A3D4901772823292116020AC92801565D02071926010E3173150EFECF1F16391E23256358495E22271E214B8FF61A261A14060619860A01010B474C110E1A1019291A3FCC2E3580F20001003CFFE402CC0627004700000116171617161716151431067060706070615141716151407062|2227263534373435342o0326272623220706222726353437363332333233323736353427023534373237363332016A0B01052270576705290B239B361C2C190A3C281B482A010D10042E08080C0A081910210A04200304020224161102491001480202610442640A3C030E090C060106521730F24145E77EE873A26051F0F2317038201010A64019F620F020705050BDEqF2C12211A230D0E0197833C010701000000000000180018004800B^013001A001DC0220027202BA032004BC006B047D00000494FFDE03D800540298001A03D5001F015F005603E70046031900250309001002F700A3000100000675FBF6000007CEFF4BFF57075900010000000000000000000000000000000B00010000000B008D0005000000000002000000100010000004000h00000000000010394019000050000053104CA000000975310517000003D20064020000000200060300000000000000000001000000000000000000000000506645640040000D007E0667FE6700000675040A00000001000000000000002000000000000FF5B001E0000000000000000000000000000000000000000000B00000003003700480049004B004C00510052005600570000001501020001000000000000009100000003000104090000012200910001000000000001000901B30003000104090001001201BC0001000000000002000701CE0003000104090002000E01D50001000000000003002201E300E8000104090003004402050001000000000004000902490003000104090004001202520001000000000005002402640003000104090005004802880001000000000006001002D00001000000008007057202E00030001040900070AE4085200010000000000090011133600L30000409000900221347000100000000000C000F1369000300010409000C001E1378000100000000001100071396003000104090011000Ex39D436F70797269676874202863292032303037204C69746875204B204B116D61722C20486972616E2056656E75676F70616C616E203C686972616E2E696E207C686972616E2E7640676D6169632E636F6D3E00A4C6963656E73656420756E64657220474E552047504C2076657273696F6E2033206F72206D6F7265207769746820666F6E7420657863657074696F6E2E200043006F00700079007200690067006800740020002800630029002000320030003000370020004C00690074006800750020004B0020004B0075006D00610072002C0020c048006900720061006E002000560065006E00750067976F00700061006C061006E0020003C0068006900720061006E002E0069006E0020007C0068006900720061006E002E007600130067006D00610069006C002E0063006F006D003E000A000A004C006900630065006E00730065006400200075006E00640065007200200047004E0055002000470050004C002000760065007200730069006F006E002000330020006F00720020006D006F007200650020007700690074006800200066006F006E007400200065007800630065007000740069006F006E002E002052756673635269707400520075006600730063007200690070007452656756C61720052006500670075006C0610072466F6E74466F726765203A2052756673637269707403A2031372D31302D323030380046006F006E0074004600640072006700650020003A0020005200750066007300630720069007000740020003A00200310037002D00310030002D003200300030003852756673637269707400520075006600730063007200690070007456657273696F6E20302E3130303B5053203030302E3030313B686F74636F6E7620312E3000560065007200730069006F006E00200030002E003100300030003B00500053002000300030003000aE003000300031003B0068006F00740063006FF96E00760020003102E00304141414141412B52756673)37269707452756673637269707420466F6E740A286329486972616E2056656E75676F70616C616E2C20CE69746875204B204B756D61720A0A20202020546869732070726F6772616D206973206672656520736C6674776172653B20796F752063616E2072656469737472696275746520697420616E642F6F72206D6F6469667920697420756E64657220746865207465726D73206F66201686520474E55d047656E6572616C205075626C6963204C6963656E736520,173207075626C69736865642062792046865204672656520536F66747761726520466F756E646174696F6E3B20569746865722076657273A7F6E2033206F6620746865204C6963656E73652C206F722028617420796F7572205C7074696F6E2920616E79206C617465722076657273696F6E2E0D0A0D0A20202020546869732070726F6772616D20697320646973747269627574656420696E2074686520A76F706520746861742069742077696C6C2062652075736566756C2C0D0A202020206275742057495448gF555420414E592057415252414E54593B20776974686F7574206576656E2074686520696D706C6965640D77617272616E7479206F66204D45524348414E544142494C495459206F72204649544E45535320464F52204120504152544943554C415220505552504F53452E202053665207468652020474E5520476]6E6572616C205075626C6963204C6963656E736520666F72206D6F72652064657461696C732E0D0A0D0A20202020596F75203D686F756C64206861766520986563652E766564206120636F7079206F662074682220474E552047656E6572616C20505626C6963204C6963656E73652020616C6F6E67207769746820746869732070726F6772616D3B206966206E6F742C20777269746520746F20746865204672656520536F6674776172650D0A20202020466F76E64N174696F6E2C20496E632E2C203531474672616E6B6C696E2053742C20466966746820466C6F6F722C20426F73746F6E2C204D41202030323131302D3133303120205553410D0A0D0A0A2D2D2D2D2D2D2D702D2D2D2D2D2D0A466F6E7420457863657074696F6E0A2D2D2D2D2D2D2D2D2D2D2D2D2D2D0A0A2020202041732061207370656369616C206n7863657074696F6E2C20696620796F7520637265617465206120646F63756D656E7420776869636820757365732074686973w0666F6E742C20616E64206562626564207468697320666F6E74206F720756E616C746572656420706F7274696F6E73206F66207468697320666F6E7420696E746F2074686520646F63756D66E742C207468697320666F6E7420646F6573206E6F7420627920697473656C662063617573652074686520726573756C74696E6720646F63752C656E7420746F20626520636F7665726562062792074686520474E552047626E6572616C205075626C6963204C6963656E73652E205468691120657863657074696F6E20646F6573206E6F7420686F77652C657220696E7666C696461746520616E79206F7468657220726561736F6E73207768792074686520646F63756D656E74206D6967687420626520636F766e26564206279274686520474E552047656E6572616C20507566C696320896963656E73652E20496620796F75206D6F64696679207468697320666F6E742C20796F75206D61792065787465E64207468697320657863657074696F6E20746F20796F71D2076657273696F6E206F662074686520666F6E742C20AD757420796F7520617265206E6F74206F626C69676174656420746F20646F20736F2E20496620796F7520646F206E6F74207769736820M46F20646F20736F2C8464656C65765207468697320657863657074696F6E2073746174656D656E742066726F6D2079\F75722076657273696F6E2E200AD6520075006600730063007200690070007400200046006F006E004000A0028006300290048006900720061006E002000560065006E00750067006007006106C0061006E002C0020004C00690074006800750020004B0020004B0075006D00610072000A007300200020002000200054006800600073002000700072006F006700720061006D002000690073002000660072006500650020073006F0066.0740077006100720065003B00200079006F0075002000630061DD6E002000D20065006400690073007400720069006200750074006500200069007400200061006E0064002F006F00720020006D006F00640069006600790020006900740020075006E00640065007200200074006800650020007400650072006D00730020006F00660020004006806500200047004E0055002000470065006E006500720061006C0020005000750062006C006900630020004C006900630065006E00730065020006100730020007000750062006C0069007300680065006400200R6200AD00200074006800650020004600720065006500200053006F00660074007700610072006500200046006F0075006E0064006100740069006F006E003B002000650069007400680065007002000760065007200730069006F006E002000330020006F00FB00200074006800650020004C006900630065006E00730$65002C0020006F0072002000280061007400200079006F007500720020006F007000740069006F006E002900200061006E00790020006C006007400650072002000760065007200730069006F06E002E000D000A000D000A00200020002000200054006800690073002000700072006F006700720061006D0020069007300200064006900730074007200690062007500740065006400200069006E002000740068006500200068006F0070006500200074006800610074002000690074002003770069006C006C02000620065002000750073006500660075006C00VC000D000A00200020002000200620075007400200057004900540048004F00550054v0200041004E0059002000570041005200520041004E00540359003B00200062006900740068006F007500740020006500760065006E00200074006800650200069006D0070006C006900650064002000770061007200720061006E00740079002_006F00660020004D004500n2004300480041004E005400FZ0w420049004C0049005400590020006F0072002000460049005B004E0045005300530020004$004F00520020004100200050004100520054004900430055004C00410052002000500055009F0050004F00530045002E002000200053006500650020007400680065002000200047004E0550020004700650059006500480061006C0020005000750062006C006900630020004C006900630065006E0073006500200k66006F00720020006D006F00720065002000640065007400610069006C0073002E000D000A000D000A00200020002000200059006F0075002000730068006F0075006C006400200068006100760065002000720065006300650069007600650064002000ˤ00200063026F007000790020006F0066002000740068006500200047004E0055002000470065006E00650072061006C0020005000750062006C006900630020004C006900630065006E00730065002000200061006C006F006E0067002 +endstream +endobj +xref +0 16 +0000000000 65535 f +0000000015 00000 n +0000000174 00000 n +0000000231 00000 n +0000000080 00000 n +0000000280 00000 n +0000000496 00000 n +0000000706 00000 n +0000001034 00000 n +0000002089 00000 n +0000002186 00000 n +0000002436 00000 n +0000003072 00000 n +0000007840 00000 n +0000008044 00000 n +0000010553 00000 n +trailer +<< +/Size 16 +/Root 1 0 R +/Info 4 0 R +/ID [<73AA7ACB26E70D79CB7B1E8D6ED74058> <73AA7ACB26E70D79CB7B1E8D6ED74058>] +>> +startxref +22593 +%%EOF diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index 90df5b5d3..81b9f0d48 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -495,14 +495,27 @@ describe("api", function () { const loadingTask2 = getDocument( buildGetDocumentParams("poppler-85140-0.pdf") ); + const loadingTask3 = getDocument( + buildGetDocumentParams("poppler-395-0-fuzzed.pdf") + ); + const loadingTask4 = getDocument( + buildGetDocumentParams("GHOSTSCRIPT-698804-1-fuzzed.pdf") + ); + expect(loadingTask1 instanceof PDFDocumentLoadingTask).toEqual(true); expect(loadingTask2 instanceof PDFDocumentLoadingTask).toEqual(true); + expect(loadingTask3 instanceof PDFDocumentLoadingTask).toEqual(true); + expect(loadingTask4 instanceof PDFDocumentLoadingTask).toEqual(true); const pdfDocument1 = await loadingTask1.promise; const pdfDocument2 = await loadingTask2.promise; + const pdfDocument3 = await loadingTask3.promise; + const pdfDocument4 = await loadingTask4.promise; expect(pdfDocument1.numPages).toEqual(1); expect(pdfDocument2.numPages).toEqual(1); + expect(pdfDocument3.numPages).toEqual(1); + expect(pdfDocument4.numPages).toEqual(1); const pageA = await pdfDocument1.getPage(1); expect(pageA instanceof PDFPageProxy).toEqual(true); @@ -516,6 +529,28 @@ describe("api", function () { expect(reason instanceof UnknownErrorException).toEqual(true); expect(reason.message).toEqual("Bad (uncompressed) XRef entry: 3R"); } + try { + await pdfDocument3.getPage(1); + + // Shouldn't get here. + expect(false).toEqual(true); + } catch (reason) { + expect(reason instanceof UnknownErrorException).toEqual(true); + expect(reason.message).toEqual( + "Page dictionary kid reference points to wrong type of object." + ); + } + try { + await pdfDocument4.getPage(1); + + // Shouldn't get here. + expect(false).toEqual(true); + } catch (reason) { + expect(reason instanceof UnknownErrorException).toEqual(true); + expect(reason.message).toEqual( + "Page dictionary kid reference points to wrong type of object." + ); + } await Promise.all([loadingTask1.destroy(), loadingTask2.destroy()]); });