1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-20 15:18:08 +02:00

Validate explicit destinations on the worker-thread to prevent DataCloneError (issue 17981)

*Note:* This borrows a helper function from the viewer, however the code cannot be directly shared since the worker-thread has access to various primitives.
This commit is contained in:
Jonas Jenwald 2024-04-22 13:47:54 +02:00
parent 522af265a7
commit 7206d0a237
5 changed files with 81 additions and 34 deletions

View file

@ -454,10 +454,7 @@ class PDFLinkService {
}
} catch {}
if (
typeof dest === "string" ||
PDFLinkService.#isValidExplicitDestination(dest)
) {
if (typeof dest === "string" || PDFLinkService.#isValidExplicitDest(dest)) {
this.goToDestination(dest);
return;
}
@ -549,49 +546,44 @@ class PDFLinkService {
return this.#pagesRefCache.get(refStr) || null;
}
static #isValidExplicitDestination(dest) {
if (!Array.isArray(dest)) {
static #isValidExplicitDest(dest) {
if (!Array.isArray(dest) || dest.length < 2) {
return false;
}
const destLength = dest.length;
if (destLength < 2) {
return false;
}
const page = dest[0];
const [page, zoom, ...args] = dest;
if (
!(
typeof page === "object" &&
Number.isInteger(page.num) &&
Number.isInteger(page.gen)
Number.isInteger(page?.num) &&
Number.isInteger(page?.gen)
) &&
!(Number.isInteger(page) && page >= 0)
!Number.isInteger(page)
) {
return false;
}
const zoom = dest[1];
if (!(typeof zoom === "object" && typeof zoom.name === "string")) {
if (!(typeof zoom === "object" && typeof zoom?.name === "string")) {
return false;
}
let allowNull = true;
switch (zoom.name) {
case "XYZ":
if (destLength !== 5) {
if (args.length !== 3) {
return false;
}
break;
case "Fit":
case "FitB":
return destLength === 2;
return args.length === 0;
case "FitH":
case "FitBH":
case "FitV":
case "FitBV":
if (destLength !== 3) {
if (args.length !== 1) {
return false;
}
break;
case "FitR":
if (destLength !== 6) {
if (args.length !== 4) {
return false;
}
allowNull = false;
@ -599,9 +591,8 @@ class PDFLinkService {
default:
return false;
}
for (let i = 2; i < destLength; i++) {
const param = dest[i];
if (!(typeof param === "number" || (allowNull && param === null))) {
for (const arg of args) {
if (!(typeof arg === "number" || (allowNull && arg === null))) {
return false;
}
}