Skip to content

Commit

Permalink
Merge pull request #18026 from Snuffleupagus/validate-more-getArray
Browse files Browse the repository at this point in the history
Validate even more dictionary properties
  • Loading branch information
Snuffleupagus committed May 6, 2024
2 parents 14e8746 + 9b41bfc commit b676540
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 83 deletions.
55 changes: 32 additions & 23 deletions src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ import {
getInheritableProperty,
getRotationMatrix,
isAscii,
isNumberArray,
lookupMatrix,
lookupNormalRect,
lookupRect,
numberToString,
stringToUTF16String,
} from "./core_utils.js";
Expand Down Expand Up @@ -550,7 +554,7 @@ function getQuadPoints(dict, rect) {
// Each quadrilateral must consist of eight coordinates.
const quadPoints = dict.getArray("QuadPoints");
if (
!Array.isArray(quadPoints) ||
!isNumberArray(quadPoints, null) ||
quadPoints.length === 0 ||
quadPoints.length % 8 > 0
) {
Expand Down Expand Up @@ -914,10 +918,7 @@ class Annotation {
* @param {Array} rectangle - The rectangle array with exactly four entries
*/
setRectangle(rectangle) {
this.rectangle =
Array.isArray(rectangle) && rectangle.length === 4
? Util.normalizeRect(rectangle)
: [0, 0, 0, 0];
this.rectangle = lookupNormalRect(rectangle, [0, 0, 0, 0]);
}

/**
Expand Down Expand Up @@ -1150,8 +1151,11 @@ class Annotation {
["ExtGState", "ColorSpace", "Pattern", "Shading", "XObject", "Font"],
appearance
);
const bbox = appearanceDict.getArray("BBox") || [0, 0, 1, 1];
const matrix = appearanceDict.getArray("Matrix") || [1, 0, 0, 1, 0, 0];
const bbox = lookupRect(appearanceDict.getArray("BBox"), [0, 0, 1, 1]);
const matrix = lookupMatrix(
appearanceDict.getArray("Matrix"),
IDENTITY_MATRIX
);
const transform = getTransformMatrix(rect, bbox, matrix);

const opList = new OperatorList();
Expand Down Expand Up @@ -1248,10 +1252,13 @@ class Annotation {

if (text.length > 1 || text[0]) {
const appearanceDict = this.appearance.dict;
const bbox = lookupRect(appearanceDict.getArray("BBox"), null);
const matrix = lookupMatrix(appearanceDict.getArray("Matrix"), null);

this.data.textPosition = this._transformPoint(
firstPosition,
appearanceDict.getArray("BBox"),
appearanceDict.getArray("Matrix")
bbox,
matrix
);
this.data.textContent = text;
}
Expand Down Expand Up @@ -1401,7 +1408,7 @@ class AnnotationBorderStyle {
setWidth(width, rect = [0, 0, 0, 0]) {
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
assert(
Array.isArray(rect) && rect.length === 4,
isNumberArray(rect, 4),
"A valid `rect` parameter must be provided."
);
}
Expand Down Expand Up @@ -2972,7 +2979,10 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
: this.uncheckedAppearance;
if (appearance) {
const savedAppearance = this.appearance;
const savedMatrix = appearance.dict.getArray("Matrix") || IDENTITY_MATRIX;
const savedMatrix = lookupMatrix(
appearance.dict.getArray("Matrix"),
IDENTITY_MATRIX
);

if (rotation) {
appearance.dict.set(
Expand Down Expand Up @@ -3737,12 +3747,7 @@ class PopupAnnotation extends Annotation {
warn("Popup annotation has a missing or invalid parent annotation.");
return;
}

const parentRect = parentItem.getArray("Rect");
this.data.parentRect =
Array.isArray(parentRect) && parentRect.length === 4
? Util.normalizeRect(parentRect)
: null;
this.data.parentRect = lookupNormalRect(parentItem.getArray("Rect"), null);

const rt = parentItem.get("RT");
if (isName(rt, AnnotationReplyType.GROUP)) {
Expand Down Expand Up @@ -4030,7 +4035,7 @@ class LineAnnotation extends MarkupAnnotation {
this.data.hasOwnCanvas = this.data.noRotate;
this.data.noHTML = false;

const lineCoordinates = dict.getArray("L");
const lineCoordinates = lookupRect(dict.getArray("L"), [0, 0, 0, 0]);
this.data.lineCoordinates = Util.normalizeRect(lineCoordinates);

if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) {
Expand Down Expand Up @@ -4225,7 +4230,7 @@ class PolylineAnnotation extends MarkupAnnotation {
// horizontal and vertical coordinates, respectively, of each vertex.
// Convert this to an array of objects with x and y coordinates.
const rawVertices = dict.getArray("Vertices");
if (!Array.isArray(rawVertices)) {
if (!isNumberArray(rawVertices, null)) {
return;
}
for (let i = 0, ii = rawVertices.length; i < ii; i += 2) {
Expand Down Expand Up @@ -4314,11 +4319,15 @@ class InkAnnotation extends MarkupAnnotation {
// of each vertex. Convert this to an array of objects with x and y
// coordinates.
this.data.inkLists.push([]);
if (!Array.isArray(rawInkLists[i])) {
continue;
}
for (let j = 0, jj = rawInkLists[i].length; j < jj; j += 2) {
this.data.inkLists[i].push({
x: xref.fetchIfRef(rawInkLists[i][j]),
y: xref.fetchIfRef(rawInkLists[i][j + 1]),
});
const x = xref.fetchIfRef(rawInkLists[i][j]),
y = xref.fetchIfRef(rawInkLists[i][j + 1]);
if (typeof x === "number" && typeof y === "number") {
this.data.inkLists[i].push({ x, y });
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/catalog.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import {
collectActions,
isNumberArray,
MissingDataException,
PDF_VERSION_REGEXP,
recoverJsURL,
Expand Down Expand Up @@ -388,8 +389,7 @@ class Catalog {

// We only need to parse the color when it's valid, and non-default.
if (
Array.isArray(color) &&
color.length === 3 &&
isNumberArray(color, 3) &&
(color[0] !== 0 || color[1] !== 0 || color[2] !== 0)
) {
rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0);
Expand Down
35 changes: 35 additions & 0 deletions src/core/core_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
BaseException,
objectSize,
stringToPDFString,
Util,
warn,
} from "../shared/util.js";
import { Dict, isName, Ref, RefSet } from "./primitives.js";
Expand Down Expand Up @@ -218,6 +219,21 @@ function isWhiteSpace(ch) {
return ch === 0x20 || ch === 0x09 || ch === 0x0d || ch === 0x0a;
}

/**
* Checks if something is an Array containing only boolean values,
* and (optionally) checks its length.
* @param {any} arr
* @param {number | null} len
* @returns {boolean}
*/
function isBooleanArray(arr, len) {
return (
Array.isArray(arr) &&
(len === null || arr.length === len) &&
arr.every(x => typeof x === "boolean")
);
}

/**
* Checks if something is an Array containing only numbers,
* and (optionally) checks its length.
Expand All @@ -233,6 +249,21 @@ function isNumberArray(arr, len) {
);
}

// Returns the matrix, or the fallback value if it's invalid.
function lookupMatrix(arr, fallback) {
return isNumberArray(arr, 6) ? arr : fallback;
}

// Returns the rectangle, or the fallback value if it's invalid.
function lookupRect(arr, fallback) {
return isNumberArray(arr, 4) ? arr : fallback;
}

// Returns the normalized rectangle, or the fallback value if it's invalid.
function lookupNormalRect(arr, fallback) {
return isNumberArray(arr, 4) ? Util.normalizeRect(arr) : fallback;
}

/**
* AcroForm field names use an array like notation to refer to
* repeated XFA elements e.g. foo.bar[nnn].
Expand Down Expand Up @@ -652,9 +683,13 @@ export {
getRotationMatrix,
getSizeInBytes,
isAscii,
isBooleanArray,
isNumberArray,
isWhiteSpace,
log2,
lookupMatrix,
lookupNormalRect,
lookupRect,
MissingDataException,
numberToString,
ParserEOFException,
Expand Down
9 changes: 6 additions & 3 deletions src/core/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
getInheritableProperty,
getNewAnnotationsMap,
isWhiteSpace,
lookupNormalRect,
MissingDataException,
PDF_VERSION_REGEXP,
validateCSSFont,
Expand Down Expand Up @@ -160,10 +161,12 @@ class Page {
if (this.xfaData) {
return this.xfaData.bbox;
}
let box = this._getInheritableProperty(name, /* getArray = */ true);
const box = lookupNormalRect(
this._getInheritableProperty(name, /* getArray = */ true),
null
);

if (Array.isArray(box) && box.length === 4) {
box = Util.normalizeRect(box);
if (box) {
if (box[2] - box[0] > 0 && box[3] - box[1] > 0) {
return box;
}
Expand Down
37 changes: 15 additions & 22 deletions src/core/evaluator.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {
import { getTilingPatternIR, Pattern } from "./pattern.js";
import { getXfaFontDict, getXfaFontName } from "./xfa_fonts.js";
import { IdentityToUnicodeMap, ToUnicodeMap } from "./to_unicode_map.js";
import { isNumberArray, lookupMatrix, lookupNormalRect } from "./core_utils.js";
import { isPDFFunction, PDFFunctionFactory } from "./function.js";
import { Lexer, Parser } from "./parser.js";
import {
Expand All @@ -73,7 +74,6 @@ import { getGlyphsUnicode } from "./glyphlist.js";
import { getMetrics } from "./metrics.js";
import { getUnicodeForGlyph } from "./unicode.js";
import { ImageResizer } from "./image_resizer.js";
import { isNumberArray } from "./core_utils.js";
import { MurmurHash3_64 } from "../shared/murmurhash3.js";
import { OperatorList } from "./operator_list.js";
import { PDFImage } from "./image.js";
Expand Down Expand Up @@ -460,12 +460,8 @@ class PartialEvaluator {
localColorSpaceCache
) {
const dict = xobj.dict;
const matrix = dict.getArray("Matrix");
let bbox = dict.getArray("BBox");
bbox =
Array.isArray(bbox) && bbox.length === 4
? Util.normalizeRect(bbox)
: null;
const matrix = lookupMatrix(dict.getArray("Matrix"), null);
const bbox = lookupNormalRect(dict.getArray("BBox"), null);

let optionalContent, groupOptions;
if (dict.has("OC")) {
Expand Down Expand Up @@ -1578,7 +1574,7 @@ class PartialEvaluator {
localShadingPatternCache,
});
if (objId) {
const matrix = dict.getArray("Matrix");
const matrix = lookupMatrix(dict.getArray("Matrix"), null);
operatorList.addOp(fn, ["Shading", objId, matrix]);
}
return undefined;
Expand Down Expand Up @@ -3265,8 +3261,8 @@ class PartialEvaluator {
const currentState = stateManager.state.clone();
const xObjStateManager = new StateManager(currentState);

const matrix = xobj.dict.getArray("Matrix");
if (Array.isArray(matrix) && matrix.length === 6) {
const matrix = lookupMatrix(xobj.dict.getArray("Matrix"), null);
if (matrix) {
xObjStateManager.transform(matrix);
}

Expand Down Expand Up @@ -4244,10 +4240,7 @@ class PartialEvaluator {

if (!descriptor) {
if (isType3Font) {
let bbox = dict.getArray("FontBBox");
if (!isNumberArray(bbox, 4)) {
bbox = [0, 0, 0, 0];
}
const bbox = lookupNormalRect(dict.getArray("FontBBox"), [0, 0, 0, 0]);
// FontDescriptor is only required for Type3 fonts when the document
// is a tagged pdf. Create a barbebones one to get by.
descriptor = new Dict(null);
Expand Down Expand Up @@ -4437,14 +4430,14 @@ class PartialEvaluator {
}
}

let fontMatrix = dict.getArray("FontMatrix");
if (!isNumberArray(fontMatrix, 6)) {
fontMatrix = FONT_IDENTITY_MATRIX;
}
let bbox = descriptor.getArray("FontBBox") || dict.getArray("FontBBox");
if (!isNumberArray(bbox, 4)) {
bbox = undefined;
}
const fontMatrix = lookupMatrix(
dict.getArray("FontMatrix"),
FONT_IDENTITY_MATRIX
);
const bbox = lookupNormalRect(
descriptor.getArray("FontBBox") || dict.getArray("FontBBox"),
undefined
);
let ascent = descriptor.get("Ascent");
if (typeof ascent !== "number") {
ascent = undefined;
Expand Down

0 comments on commit b676540

Please sign in to comment.