From c17801b77e27f9889b05339636e5f02835f0e49f Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Fri, 20 Mar 2026 10:37:11 +0100 Subject: [PATCH] Avoid getting null value in RefSet when cloning --- src/core/editor/pdf_editor.js | 12 +++++++----- test/pdfs/.gitignore | 1 + test/pdfs/extractPages_null_in_array.pdf | 21 +++++++++++++++++++++ test/unit/api_spec.js | 16 ++++++++++++++++ 4 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 test/pdfs/extractPages_null_in_array.pdf diff --git a/src/core/editor/pdf_editor.js b/src/core/editor/pdf_editor.js index 1b64907ef..b4b84b4ae 100644 --- a/src/core/editor/pdf_editor.js +++ b/src/core/editor/pdf_editor.js @@ -249,7 +249,8 @@ class PDFEditor { obj = obj.slice(); } for (let i = 0, ii = obj.length; i < ii; i++) { - const postponedActions = postponedRefCopies.get(obj[i]); + const postponedActions = + obj[i] instanceof Ref && postponedRefCopies.get(obj[i]); if (postponedActions) { // The object is a reference that needs to be copied later. postponedActions.push(ref => (obj[i] = ref)); @@ -277,7 +278,8 @@ class PDFEditor { } if (dict) { for (const [key, rawObj] of dict.getRawEntries()) { - const postponedActions = postponedRefCopies.get(rawObj); + const postponedActions = + rawObj instanceof Ref && postponedRefCopies.get(rawObj); if (postponedActions) { // The object is a reference that needs to be copied later. postponedActions.push(ref => dict.set(key, ref)); @@ -1083,7 +1085,7 @@ class PDFEditor { // Fix the ID tree. for (const [id, nodeRef] of idTree || []) { - const newNodeRef = oldRefMapping.get(nodeRef); + const newNodeRef = nodeRef instanceof Ref && oldRefMapping.get(nodeRef); const newId = dedupIDs.get(id) || id; if (newNodeRef) { newIdTree.set(newId, newNodeRef); @@ -1137,7 +1139,7 @@ class PDFEditor { const newDestinations = (documentData.destinations = new Map()); for (const [key, dest] of Object.entries(destinations)) { const pageRef = dest[0]; - const pageData = pagesMap.get(pageRef); + const pageData = pageRef instanceof Ref && pagesMap.get(pageRef); if (!pageData) { continue; } @@ -1537,7 +1539,7 @@ class PDFEditor { } const { oldRefMapping } = documentData; for (const coRef of co) { - const newCoRef = oldRefMapping.get(coRef); + const newCoRef = coRef instanceof Ref && oldRefMapping.get(coRef); if (newCoRef) { calculationOrder.push(newCoRef); } diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 13e26879f..54eecbe68 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -888,3 +888,4 @@ !outlines_for_editor.pdf !mesh_shading_empty.pdf !acroform_calculation_order.pdf +!extractPages_null_in_array.pdf diff --git a/test/pdfs/extractPages_null_in_array.pdf b/test/pdfs/extractPages_null_in_array.pdf new file mode 100644 index 000000000..cc62b270e --- /dev/null +++ b/test/pdfs/extractPages_null_in_array.pdf @@ -0,0 +1,21 @@ +%PDF-1.0 +1 0 obj +<< /Type /Catalog /Pages 2 0 R >> +endobj +2 0 obj +<< /Type /Pages /Kids [3 0 R] /Count 1 >> +endobj +3 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Dummy [null] >> >> +endobj +xref +0 4 +0000000000 65535 f +0000000009 00000 n +0000000058 00000 n +0000000115 00000 n +trailer +<< /Size 4 /Root 1 0 R >> +startxref +217 +%%EOF diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index 7ce81129f..0547afef4 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -6763,5 +6763,21 @@ small scripts as well as for`); await newLoadingTask.destroy(); }); }); + + describe("extract pages with null values in arrays", function () { + it("should not crash when a page resource contains an array with null entries", async function () { + const loadingTask = getDocument( + buildGetDocumentParams("extractPages_null_in_array.pdf") + ); + const pdfDoc = await loadingTask.promise; + const data = await pdfDoc.extractPages([{ document: null }]); + await loadingTask.destroy(); + + const newLoadingTask = getDocument(data); + const newPdfDoc = await newLoadingTask.promise; + expect(newPdfDoc.numPages).toEqual(1); + await newLoadingTask.destroy(); + }); + }); }); });