diff --git a/src/core/xref.js b/src/core/xref.js index da7491075..8ffbefcc1 100644 --- a/src/core/xref.js +++ b/src/core/xref.js @@ -681,11 +681,15 @@ class XRef { // When no trailer dictionary candidate exists, try picking the first // dictionary that contains a /Root entry (fixes issue18986.pdf). if (!trailerDicts.length) { - for (const [num, entry] of this.entries.entries()) { - if (!entry) { + // In case, this.entries is a sparse array we don't want to + // iterate over empty entries so we use the `in` operator instead of + // using for..of on entries() or a for with the array length. + for (const num in this.entries) { + if (!Object.hasOwn(this.entries, num)) { continue; } - const ref = Ref.get(num, entry.gen); + const entry = this.entries[num]; + const ref = Ref.get(parseInt(num), entry.gen); let obj; try { @@ -693,6 +697,7 @@ class XRef { } catch { continue; } + if (obj instanceof BaseStream) { obj = obj.dict; } diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index f896c4299..59455a89d 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -741,3 +741,4 @@ !print_protection.pdf !tracemonkey_with_annotations.pdf !tracemonkey_with_editable_annotations.pdf +!bug1980958.pdf diff --git a/test/pdfs/bug1980958.pdf b/test/pdfs/bug1980958.pdf new file mode 100644 index 000000000..9470dcd44 --- /dev/null +++ b/test/pdfs/bug1980958.pdf @@ -0,0 +1,10 @@ +%PDF-1.7 +1 0 obj <> +endobj +2 0 obj <> +endobj +3 0 obj <> +endobj + +2147483647 0 obj <> +endobj diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index c777bd18d..648fe309e 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -878,6 +878,20 @@ describe("api", function () { await loadingTask.destroy(); }); + + it("Doesn't iterate over all empty slots in the xref entries (bug 1980958)", async function () { + if (isNodeJS) { + pending("Worker is not supported in Node.js."); + } + const loadingTask = getDocument(buildGetDocumentParams("bug1980958.pdf")); + const { promise, resolve } = Promise.withResolvers(); + setTimeout(() => resolve(null), 1000); + + const pdfDocument = await Promise.race([loadingTask.promise, promise]); + expect(pdfDocument?.numPages).toEqual(1); + + loadingTask._worker.destroy(); + }); }); describe("PDFWorker", function () {