Skip to content

Commit ebdb1cb

Browse files
committed
Don't iterate over all empty slots in the xref entries (bug 1980958)
1 parent c6bd044 commit ebdb1cb

File tree

5 files changed

+23
-3
lines changed

5 files changed

+23
-3
lines changed

src/core/primitives.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ class Dict {
315315

316316
class Ref {
317317
constructor(num, gen) {
318-
this.num = num;
318+
this.num = parseInt(num);
319319
this.gen = gen;
320320
}
321321

src/core/xref.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -681,10 +681,14 @@ class XRef {
681681
// When no trailer dictionary candidate exists, try picking the first
682682
// dictionary that contains a /Root entry (fixes issue18986.pdf).
683683
if (!trailerDicts.length) {
684-
for (const [num, entry] of this.entries.entries()) {
685-
if (!entry) {
684+
// In case, this.entries is a sparse array we don't want to
685+
// iterate over empty entries so we use the `in` operator instead of
686+
// using for..of on entries() or a for with the array length.
687+
for (const num in this.entries) {
688+
if (!Object.hasOwn(this.entries, num)) {
686689
continue;
687690
}
691+
const entry = this.entries[num];
688692
const ref = Ref.get(num, entry.gen);
689693
let obj;
690694

@@ -693,6 +697,7 @@ class XRef {
693697
} catch {
694698
continue;
695699
}
700+
696701
if (obj instanceof BaseStream) {
697702
obj = obj.dict;
698703
}

test/pdfs/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,3 +740,4 @@
740740
!dates_save.pdf
741741
!print_protection.pdf
742742
!tracemonkey_with_annotations.pdf
743+
!bug1980958.pdf

test/pdfs/bug1980958.pdf

219 Bytes
Binary file not shown.

test/unit/api_spec.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,20 @@ describe("api", function () {
878878

879879
await loadingTask.destroy();
880880
});
881+
882+
it("Doesn't iterate over all empty slots in the xref entries (bug 1980958)", async function () {
883+
if (isNodeJS) {
884+
pending("Worker is not supported in Node.js.");
885+
}
886+
const loadingTask = getDocument(buildGetDocumentParams("bug1980958.pdf"));
887+
const { promise, resolve } = Promise.withResolvers();
888+
setTimeout(() => resolve(null), 1000);
889+
890+
const pdfDocument = await Promise.race([loadingTask.promise, promise]);
891+
expect(pdfDocument?.numPages).toEqual(1);
892+
893+
loadingTask._worker.destroy();
894+
});
881895
});
882896

883897
describe("PDFWorker", function () {

0 commit comments

Comments
 (0)