Always prefer abbreviated keys, over full ones, when doing any dictionary lookups (issue 14256)

Note that issue 14256 was specifically about *inline* images, please refer to:
 - https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf#G7.1852045
 - https://www.pdfa.org/safedocs-unearths-pdf-inline-image-issue/
 - https://pdf-issues.pdfa.org/32000-2-2020/clause08.html#H8.9.7

However, during review of the initial PR in https://github.com/mozilla/pdf.js/pull/14257#issuecomment-964469710, it was suggested that we instead do this *unconditionally for all* dictionary lookups.
In addition to re-ordering the existing call-sites in the `src/core`-code, and adding non-PRODUCTION/TESTING asserts to catch future errors, for consistency a number of existing `if`/`switch`-blocks were re-factored to also check the abbreviated keys first.
This commit is contained in:
Jonas Jenwald 2021-11-09 22:39:21 +01:00
parent 4ee906adf4
commit ea1c348c67
12 changed files with 730 additions and 104 deletions

View File

@ -379,14 +379,14 @@ class ColorSpace {
cs = xref.fetchIfRef(cs);
if (isName(cs)) {
switch (cs.name) {
case "DeviceGray":
case "G":
case "DeviceGray":
return this.singletons.gray;
case "DeviceRGB":
case "RGB":
case "DeviceRGB":
return this.singletons.rgb;
case "DeviceCMYK":
case "CMYK":
case "DeviceCMYK":
return this.singletons.cmyk;
case "Pattern":
return new PatternCS(/* baseCS = */ null);
@ -417,14 +417,14 @@ class ColorSpace {
let params, numComps, baseCS, whitePoint, blackPoint, gamma;
switch (mode) {
case "DeviceGray":
case "G":
case "DeviceGray":
return this.singletons.gray;
case "DeviceRGB":
case "RGB":
case "DeviceRGB":
return this.singletons.rgb;
case "DeviceCMYK":
case "CMYK":
case "DeviceCMYK":
return this.singletons.cmyk;
case "CalGray":
params = xref.fetchIfRef(cs[1]);
@ -467,8 +467,8 @@ class ColorSpace {
baseCS = this._parse(baseCS, xref, resources, pdfFunctionFactory);
}
return new PatternCS(baseCS);
case "Indexed":
case "I":
case "Indexed":
baseCS = this._parse(cs[1], xref, resources, pdfFunctionFactory);
const hiVal = xref.fetchIfRef(cs[2]) + 1;
const lookup = xref.fetchIfRef(cs[3]);

View File

@ -580,8 +580,8 @@ class PartialEvaluator {
}) {
const dict = image.dict;
const imageRef = dict.objId;
const w = dict.get("Width", "W");
const h = dict.get("Height", "H");
const w = dict.get("W", "Width");
const h = dict.get("H", "Height");
if (!(w && isNum(w)) || !(h && isNum(h))) {
warn("Image dimensions are missing, or not numbers.");
@ -604,8 +604,8 @@ class PartialEvaluator {
operatorList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
}
const imageMask = dict.get("ImageMask", "IM") || false;
const interpolate = dict.get("Interpolate", "I");
const imageMask = dict.get("IM", "ImageMask") || false;
const interpolate = dict.get("I", "Interpolate");
let imgData, args;
if (imageMask) {
// This depends on a tmpCanvas being filled with the
@ -613,20 +613,17 @@ class PartialEvaluator {
// data can't be done here. Instead of creating a
// complete PDFImage, only read the information needed
// for later.
const width = dict.get("Width", "W");
const height = dict.get("Height", "H");
const bitStrideLength = (width + 7) >> 3;
const bitStrideLength = (w + 7) >> 3;
const imgArray = image.getBytes(
bitStrideLength * height,
bitStrideLength * h,
/* forceClamped = */ true
);
const decode = dict.getArray("Decode", "D");
const decode = dict.getArray("D", "Decode");
imgData = PDFImage.createMask({
imgArray,
width,
height,
width: w,
height: h,
imageIsFromDecodeStream: image instanceof DecodeStream,
inverseDecode: !!decode && decode[0] > 0,
interpolate,
@ -648,7 +645,7 @@ class PartialEvaluator {
return;
}
const softMask = dict.get("SMask", "SM") || false;
const softMask = dict.get("SM", "SMask") || false;
const mask = dict.get("Mask") || false;
const SMALL_IMAGE_DIMENSIONS = 200;

View File

@ -93,7 +93,7 @@ class PDFImage {
this.image = image;
const dict = image.dict;
const filter = dict.get("Filter");
const filter = dict.get("F", "Filter");
if (isName(filter)) {
switch (filter.name) {
case "JPXDecode":
@ -114,8 +114,8 @@ class PDFImage {
}
// TODO cache rendered images?
let width = dict.get("Width", "W");
let height = dict.get("Height", "H");
let width = dict.get("W", "Width");
let height = dict.get("H", "Height");
if (
Number.isInteger(image.width) &&
@ -139,13 +139,13 @@ class PDFImage {
this.width = width;
this.height = height;
this.interpolate = dict.get("Interpolate", "I");
this.imageMask = dict.get("ImageMask", "IM") || false;
this.interpolate = dict.get("I", "Interpolate");
this.imageMask = dict.get("IM", "ImageMask") || false;
this.matte = dict.get("Matte") || false;
let bitsPerComponent = image.bitsPerComponent;
if (!bitsPerComponent) {
bitsPerComponent = dict.get("BitsPerComponent", "BPC");
bitsPerComponent = dict.get("BPC", "BitsPerComponent");
if (!bitsPerComponent) {
if (this.imageMask) {
bitsPerComponent = 1;
@ -159,7 +159,7 @@ class PDFImage {
this.bpc = bitsPerComponent;
if (!this.imageMask) {
let colorSpace = dict.getRaw("ColorSpace") || dict.getRaw("CS");
let colorSpace = dict.getRaw("CS") || dict.getRaw("ColorSpace");
if (!colorSpace) {
info("JPX images (which do not require color spaces)");
switch (image.numComps) {
@ -174,8 +174,7 @@ class PDFImage {
break;
default:
throw new Error(
`JPX images with ${image.numComps} ` +
"color components not supported."
`JPX images with ${image.numComps} color components not supported.`
);
}
}
@ -189,7 +188,7 @@ class PDFImage {
this.numComps = this.colorSpace.numComps;
}
this.decode = dict.getArray("Decode", "D");
this.decode = dict.getArray("D", "Decode");
this.needsDecode = false;
if (
this.decode &&
@ -226,7 +225,7 @@ class PDFImage {
} else if (mask) {
if (isStream(mask)) {
const maskDict = mask.dict,
imageMask = maskDict.get("ImageMask", "IM");
imageMask = maskDict.get("IM", "ImageMask");
if (!imageMask) {
warn("Ignoring /Mask in image without /ImageMask.");
} else {

View File

@ -62,9 +62,9 @@ class JpegStream extends DecodeStream {
};
// Checking if values need to be transformed before conversion.
const decodeArr = this.dict.getArray("Decode", "D");
const decodeArr = this.dict.getArray("D", "Decode");
if (this.forceRGB && Array.isArray(decodeArr)) {
const bitsPerComponent = this.dict.get("BitsPerComponent") || 8;
const bitsPerComponent = this.dict.get("BPC", "BitsPerComponent") || 8;
const decodeArrLength = decodeArr.length;
const transform = new Int32Array(decodeArrLength);
let transformNeeded = false;

View File

@ -513,7 +513,7 @@ class Parser {
}
// Extract the name of the first (i.e. the current) image filter.
const filter = dict.get("Filter", "F");
const filter = dict.get("F", "Filter");
let filterName;
if (isName(filter)) {
filterName = filter.name;
@ -527,14 +527,21 @@ class Parser {
// Parse image stream.
const startPos = stream.pos;
let length;
if (filterName === "DCTDecode" || filterName === "DCT") {
length = this.findDCTDecodeInlineStreamEnd(stream);
} else if (filterName === "ASCII85Decode" || filterName === "A85") {
length = this.findASCII85DecodeInlineStreamEnd(stream);
} else if (filterName === "ASCIIHexDecode" || filterName === "AHx") {
length = this.findASCIIHexDecodeInlineStreamEnd(stream);
} else {
length = this.findDefaultInlineStreamEnd(stream);
switch (filterName) {
case "DCT":
case "DCTDecode":
length = this.findDCTDecodeInlineStreamEnd(stream);
break;
case "A85":
case "ASCII85Decode":
length = this.findASCII85DecodeInlineStreamEnd(stream);
break;
case "AHx":
case "ASCIIHexDecode":
length = this.findASCIIHexDecodeInlineStreamEnd(stream);
break;
default:
length = this.findDefaultInlineStreamEnd(stream);
}
let imageStream = stream.makeSubStream(startPos, length, dict);
@ -694,15 +701,12 @@ class Parser {
}
filter(stream, dict, length) {
let filter = dict.get("Filter", "F");
let params = dict.get("DecodeParms", "DP");
let filter = dict.get("F", "Filter");
let params = dict.get("DP", "DecodeParms");
if (isName(filter)) {
if (Array.isArray(params)) {
warn(
"/DecodeParms should not contain an Array, " +
"when /Filter contains a Name."
);
warn("/DecodeParms should not be an Array, when /Filter is a Name.");
}
return this.makeFilter(stream, filter.name, length, params);
}
@ -740,59 +744,60 @@ class Parser {
try {
const xrefStreamStats = this.xref.stats.streamTypes;
if (name === "FlateDecode" || name === "Fl") {
xrefStreamStats[StreamType.FLATE] = true;
if (params) {
return new PredictorStream(
new FlateStream(stream, maybeLength),
maybeLength,
params
);
}
return new FlateStream(stream, maybeLength);
}
if (name === "LZWDecode" || name === "LZW") {
xrefStreamStats[StreamType.LZW] = true;
let earlyChange = 1;
if (params) {
if (params.has("EarlyChange")) {
earlyChange = params.get("EarlyChange");
switch (name) {
case "Fl":
case "FlateDecode":
xrefStreamStats[StreamType.FLATE] = true;
if (params) {
return new PredictorStream(
new FlateStream(stream, maybeLength),
maybeLength,
params
);
}
return new PredictorStream(
new LZWStream(stream, maybeLength, earlyChange),
maybeLength,
params
);
}
return new LZWStream(stream, maybeLength, earlyChange);
}
if (name === "DCTDecode" || name === "DCT") {
xrefStreamStats[StreamType.DCT] = true;
return new JpegStream(stream, maybeLength, params);
}
if (name === "JPXDecode" || name === "JPX") {
xrefStreamStats[StreamType.JPX] = true;
return new JpxStream(stream, maybeLength, params);
}
if (name === "ASCII85Decode" || name === "A85") {
xrefStreamStats[StreamType.A85] = true;
return new Ascii85Stream(stream, maybeLength);
}
if (name === "ASCIIHexDecode" || name === "AHx") {
xrefStreamStats[StreamType.AHX] = true;
return new AsciiHexStream(stream, maybeLength);
}
if (name === "CCITTFaxDecode" || name === "CCF") {
xrefStreamStats[StreamType.CCF] = true;
return new CCITTFaxStream(stream, maybeLength, params);
}
if (name === "RunLengthDecode" || name === "RL") {
xrefStreamStats[StreamType.RLX] = true;
return new RunLengthStream(stream, maybeLength);
}
if (name === "JBIG2Decode") {
xrefStreamStats[StreamType.JBIG] = true;
return new Jbig2Stream(stream, maybeLength, params);
return new FlateStream(stream, maybeLength);
case "LZW":
case "LZWDecode":
xrefStreamStats[StreamType.LZW] = true;
let earlyChange = 1;
if (params) {
if (params.has("EarlyChange")) {
earlyChange = params.get("EarlyChange");
}
return new PredictorStream(
new LZWStream(stream, maybeLength, earlyChange),
maybeLength,
params
);
}
return new LZWStream(stream, maybeLength, earlyChange);
case "DCT":
case "DCTDecode":
xrefStreamStats[StreamType.DCT] = true;
return new JpegStream(stream, maybeLength, params);
case "JPX":
case "JPXDecode":
xrefStreamStats[StreamType.JPX] = true;
return new JpxStream(stream, maybeLength, params);
case "A85":
case "ASCII85Decode":
xrefStreamStats[StreamType.A85] = true;
return new Ascii85Stream(stream, maybeLength);
case "AHx":
case "ASCIIHexDecode":
xrefStreamStats[StreamType.AHX] = true;
return new AsciiHexStream(stream, maybeLength);
case "CCF":
case "CCITTFaxDecode":
xrefStreamStats[StreamType.CCF] = true;
return new CCITTFaxStream(stream, maybeLength, params);
case "RL":
case "RunLengthDecode":
xrefStreamStats[StreamType.RLX] = true;
return new RunLengthStream(stream, maybeLength);
case "JBIG2Decode":
xrefStreamStats[StreamType.JBIG] = true;
return new Jbig2Stream(stream, maybeLength, params);
}
warn(`Filter "${name}" is not supported.`);
return stream;

View File

@ -117,7 +117,7 @@ class RadialAxialShading extends BaseShading {
this.coordsArr = dict.getArray("Coords");
this.shadingType = dict.get("ShadingType");
const cs = ColorSpace.parse({
cs: dict.getRaw("ColorSpace") || dict.getRaw("CS"),
cs: dict.getRaw("CS") || dict.getRaw("ColorSpace"),
xref,
resources,
pdfFunctionFactory,
@ -415,7 +415,7 @@ class MeshShading extends BaseShading {
this.bbox = null;
}
const cs = ColorSpace.parse({
cs: dict.getRaw("ColorSpace") || dict.getRaw("CS"),
cs: dict.getRaw("CS") || dict.getRaw("ColorSpace"),
xref,
resources,
pdfFunctionFactory,

View File

@ -43,7 +43,7 @@ class PredictorStream extends DecodeStream {
this.dict = str.dict;
const colors = (this.colors = params.get("Colors") || 1);
const bits = (this.bits = params.get("BitsPerComponent") || 8);
const bits = (this.bits = params.get("BPC", "BitsPerComponent") || 8);
const columns = (this.columns = params.get("Columns") || 1);
this.pixBytes = (colors * bits + 7) >> 3;

View File

@ -90,8 +90,22 @@ class Dict {
get(key1, key2, key3) {
let value = this._map[key1];
if (value === undefined && key2 !== undefined) {
if (
(typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")) &&
key2.length < key1.length
) {
unreachable("Dict.get: Expected keys to be ordered by length.");
}
value = this._map[key2];
if (value === undefined && key3 !== undefined) {
if (
(typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")) &&
key3.length < key2.length
) {
unreachable("Dict.get: Expected keys to be ordered by length.");
}
value = this._map[key3];
}
}
@ -105,8 +119,22 @@ class Dict {
async getAsync(key1, key2, key3) {
let value = this._map[key1];
if (value === undefined && key2 !== undefined) {
if (
(typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")) &&
key2.length < key1.length
) {
unreachable("Dict.getAsync: Expected keys to be ordered by length.");
}
value = this._map[key2];
if (value === undefined && key3 !== undefined) {
if (
(typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")) &&
key3.length < key2.length
) {
unreachable("Dict.getAsync: Expected keys to be ordered by length.");
}
value = this._map[key3];
}
}
@ -120,8 +148,22 @@ class Dict {
getArray(key1, key2, key3) {
let value = this._map[key1];
if (value === undefined && key2 !== undefined) {
if (
(typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")) &&
key2.length < key1.length
) {
unreachable("Dict.getArray: Expected keys to be ordered by length.");
}
value = this._map[key2];
if (value === undefined && key3 !== undefined) {
if (
(typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")) &&
key3.length < key2.length
) {
unreachable("Dict.getArray: Expected keys to be ordered by length.");
}
value = this._map[key3];
}
}

View File

@ -437,6 +437,7 @@
!annotation-strikeout.pdf
!annotation-strikeout-without-appearance.pdf
!annotation-squiggly.pdf
!issue14256.pdf
!annotation-squiggly-without-appearance.pdf
!annotation-highlight.pdf
!annotation-highlight-without-appearance.pdf

576
test/pdfs/issue14256.pdf Normal file
View File

@ -0,0 +1,576 @@
%PDF-1.7
% Copyright 2021, PDF Association.
1 0 obj
<< /Type /Catalog
/Outlines 2 0 R
/Pages 3 0 R
>>
endobj
2 0 obj
<< /Type /Outlines
/Count 0
>>
endobj
3 0 obj
<< /Type /Pages
/Kids [4 0 R]
/Count 1
>>
endobj
4 0 obj
<< /Type /Page
/Parent 3 0 R
/MediaBox [0 0 900 900]
/Contents 5 0 R
/Resources
<< /ColorSpace
<< /3chanRGB [ /CalRGB
<< /WhitePoint [0.9505 1.0 1.0890]
/Gamma [0.5 1.2 1.9]
/Matrix [0.4497 0.2446 0.0252
0.3163 0.4920 0.1412
0.3845 0.0833 0.9227]
>> ]
>>
/Font << /F1 6 0 R >>
>>
>>
endobj
5 0 obj
<< /Length 13569 >>
stream
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% #1: Only full key names --> all PDF parsers should support!
q
BT
0 0 0 rg % Black text
/F1 8 Tf
10 0 0 10 45 520 Tm
(1) Tj
ET
Q
q
0 1 0 rg % Green fill
10 400 200 100 re f % Paint green rectangle below image
200 0 0 100 10 400 cm
BI
/Width 20
/Height 10
/BitsPerComponent 8
/ColorSpace /DeviceRGB
/Filter [/ASCIIHexDecode]
/Length 1240
ID
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ffff00ffff00ff
ff00ffff00ff0000ff0000ffff000000
ff0000ff0000ffffff000000ffffff00
ffff00ffff000000ffffff00ffff00ff
ff000000ff0000ffffff00ffff00ffff
00ff0000ff0000ffff00ffff000000ff
ffff00ffff000000ff0000ffffff0000
00ff0000ffffff00ffff000000ffffff
00ffff000000ffffff00ffff00ff0000
ff0000ffff00ffff000000ffffff00ff
ff000000ffffff000000ffffff000000
ffffff000000ffffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
ff00ffff000000ffffff00ffff000000
ffffff000000ffffff000000ffffff00
0000ffffff00ffff000000ff0000ffff
ff00ffff00ff0000ff0000ffff00ffff
000000ffffff00ffff000000ffffff00
ffff00ffff000000ffffff00ffff0000
00ffffff00ffff000000ffffff00ffff
00ff0000ff0000ffff000000ff0000ff
0000ffffff000000ffffff00ffff00ff
ff000000ffffff00ffff00ffff000000
ff0000ff0000ffffff00ffff00ff0000
ff0000ffff00ffff00ffff00ffff00ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000 >
EI
Q
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% #2: Only abbreviated key names --> all PDF parsers should support!
q
BT
0 0 0 rg % Black text
/F1 8 Tf
10 0 0 10 255 520 Tm
(2) Tj
ET
Q
q
0 1 0 rg % Green fill
220 400 200 100 re f % Paint green rectangle below image
200 0 0 100 220 400 cm
BI
/W 20
/H 10
/BPC 8
/CS /RGB
/F [/AHx]
/L 1240
ID
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ffff00ffff00ff
ff00ffff00ff0000ff0000ffff000000
ff0000ff0000ffffff000000ffffff00
ffff00ffff000000ffffff00ffff00ff
ff000000ff0000ffffff00ffff00ffff
00ff0000ff0000ffff00ffff000000ff
ffff00ffff000000ff0000ffffff0000
00ff0000ffffff00ffff000000ffffff
00ffff000000ffffff00ffff00ff0000
ff0000ffff00ffff000000ffffff00ff
ff000000ffffff000000ffffff000000
ffffff000000ffffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
ff00ffff000000ffffff00ffff000000
ffffff000000ffffff000000ffffff00
0000ffffff00ffff000000ff0000ffff
ff00ffff00ff0000ff0000ffff00ffff
000000ffffff00ffff000000ffffff00
ffff00ffff000000ffffff00ffff0000
00ffffff00ffff000000ffffff00ffff
00ff0000ff0000ffff000000ff0000ff
0000ffffff000000ffffff00ffff00ff
ff000000ffffff00ffff00ffff000000
ff0000ff0000ffffff00ffff00ff0000
ff0000ffff00ffff00ffff00ffff00ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000 >
EI
Q
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% #3: CORRECT abbreviated key names, INCORRECT full keys
% (width x height = constant).
q
BT
0 0 0 rg % Black text
/F1 8 Tf
10 0 0 10 465 520 Tm
(3) Tj
ET
Q
q
0 1 0 rg % Green fill
430 400 200 100 re f % Paint green rectangle below image
200 0 0 100 430 400 cm
BI
/W 20 %% COMMENT OUT THIS LINE (and below) TO SEE EFFECT!
/Width 10
/H 10 %% COMMENT OUT THIS LINE (and above) TO SEE EFFECT!
/Height 40
/BPC 8
/BitsPerComponent 4
/CS /RGB
/F [/AHx]
/L 1240
ID
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ffff00ffff00ff
ff00ffff00ff0000ff0000ffff000000
ff0000ff0000ffffff000000ffffff00
ffff00ffff000000ffffff00ffff00ff
ff000000ff0000ffffff00ffff00ffff
00ff0000ff0000ffff00ffff000000ff
ffff00ffff000000ff0000ffffff0000
00ff0000ffffff00ffff000000ffffff
00ffff000000ffffff00ffff00ff0000
ff0000ffff00ffff000000ffffff00ff
ff000000ffffff000000ffffff000000
ffffff000000ffffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
ff00ffff000000ffffff00ffff000000
ffffff000000ffffff000000ffffff00
0000ffffff00ffff000000ff0000ffff
ff00ffff00ff0000ff0000ffff00ffff
000000ffffff00ffff000000ffffff00
ffff00ffff000000ffffff00ffff0000
00ffffff00ffff000000ffffff00ffff
00ff0000ff0000ffff000000ff0000ff
0000ffffff000000ffffff00ffff00ff
ff000000ffffff00ffff00ffff000000
ff0000ff0000ffffff00ffff00ff0000
ff0000ffff00ffff00ffff00ffff00ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000 >
EI
Q
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% #4: CORRECT abbreviated key names, INCORRECT full keys
% for Filter
q
BT
0 0 0 rg % Black text
/F1 8 Tf
10 0 0 10 675 520 Tm
(4) Tj
ET
Q
q
0 1 0 rg % Green fill
640 400 200 100 re f % Paint green rectangle below image
200 0 0 100 640 400 cm
BI
/W 20
/H 10
/BPC 8
/CS /RGB
/F [/AHx]
/Filter [/A85]
/Length 1240
ID
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ffff00ffff00ff
ff00ffff00ff0000ff0000ffff000000
ff0000ff0000ffffff000000ffffff00
ffff00ffff000000ffffff00ffff00ff
ff000000ff0000ffffff00ffff00ffff
00ff0000ff0000ffff00ffff000000ff
ffff00ffff000000ff0000ffffff0000
00ff0000ffffff00ffff000000ffffff
00ffff000000ffffff00ffff00ff0000
ff0000ffff00ffff000000ffffff00ff
ff000000ffffff000000ffffff000000
ffffff000000ffffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
ff00ffff000000ffffff00ffff000000
ffffff000000ffffff000000ffffff00
0000ffffff00ffff000000ff0000ffff
ff00ffff00ff0000ff0000ffff00ffff
000000ffffff00ffff000000ffffff00
ffff00ffff000000ffffff00ffff0000
00ffffff00ffff000000ffffff00ffff
00ff0000ff0000ffff000000ff0000ff
0000ffffff000000ffffff00ffff00ff
ff000000ffffff00ffff00ffff000000
ff0000ff0000ffffff00ffff00ff0000
ff0000ffff00ffff00ffff00ffff00ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000 >
EI
Q
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% #5: CORRECT abbreviated key names, INCORRECT full keys
% for ColorSpace. Visual colour shift if INCORRECT (compared
% to other images)
q
BT
0 0 0 rg % Black text
/F1 8 Tf
10 0 0 10 45 220 Tm
(5) Tj
ET
Q
q
0 1 0 rg % Green fill
10 100 200 100 re f % Paint green rectangle below image
200 0 0 100 10 100 cm
BI
/W 20
/H 10
/BPC 8
/CS /RGB %% COMMENT OUT THIS LINE TO SEE EFFECT!
/ColorSpace /3chanRGB
/F [/AHx]
/Length 1240
ID
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ffff00ffff00ff
ff00ffff00ff0000ff0000ffff000000
ff0000ff0000ffffff000000ffffff00
ffff00ffff000000ffffff00ffff00ff
ff000000ff0000ffffff00ffff00ffff
00ff0000ff0000ffff00ffff000000ff
ffff00ffff000000ff0000ffffff0000
00ff0000ffffff00ffff000000ffffff
00ffff000000ffffff00ffff00ff0000
ff0000ffff00ffff000000ffffff00ff
ff000000ffffff000000ffffff000000
ffffff000000ffffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
ff00ffff000000ffffff00ffff000000
ffffff000000ffffff000000ffffff00
0000ffffff00ffff000000ff0000ffff
ff00ffff00ff0000ff0000ffff00ffff
000000ffffff00ffff000000ffffff00
ffff00ffff000000ffffff00ffff0000
00ffffff00ffff000000ffffff00ffff
00ff0000ff0000ffff000000ff0000ff
0000ffffff000000ffffff00ffff00ff
ff000000ffffff00ffff00ffff000000
ff0000ff0000ffffff00ffff00ff0000
ff0000ffff00ffff00ffff00ffff00ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000 >
EI
Q
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% #6: CORRECT abbreviated key names, INCORRECT full keys
% for Decode. Colours will be inverted if PDF parser is wrong!
q
BT
0 0 0 rg % Black text
/F1 8 Tf
10 0 0 10 255 220 Tm
(6) Tj
ET
Q
q
0 1 0 rg % Green fill
220 100 200 100 re f % Paint green rectangle below image
200 0 0 100 220 100 cm
BI
/W 20
/H 10
/BPC 8
/CS /RGB
/D [ 0 1 0 1 0 1 ] %% COMMENT OUT THIS LINE TO SEE EFFECT!
/Decode [ 1 0 1 0 1 0 ]
/F [/AHx]
/Length 1240
ID
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ffff00ffff00ff
ff00ffff00ff0000ff0000ffff000000
ff0000ff0000ffffff000000ffffff00
ffff00ffff000000ffffff00ffff00ff
ff000000ff0000ffffff00ffff00ffff
00ff0000ff0000ffff00ffff000000ff
ffff00ffff000000ff0000ffffff0000
00ff0000ffffff00ffff000000ffffff
00ffff000000ffffff00ffff00ff0000
ff0000ffff00ffff000000ffffff00ff
ff000000ffffff000000ffffff000000
ffffff000000ffffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
ff00ffff000000ffffff00ffff000000
ffffff000000ffffff000000ffffff00
0000ffffff00ffff000000ff0000ffff
ff00ffff00ff0000ff0000ffff00ffff
000000ffffff00ffff000000ffffff00
ffff00ffff000000ffffff00ffff0000
00ffffff00ffff000000ffffff00ffff
00ff0000ff0000ffff000000ff0000ff
0000ffffff000000ffffff00ffff00ff
ff000000ffffff00ffff00ffff000000
ff0000ff0000ffffff00ffff00ff0000
ff0000ffff00ffff00ffff00ffff00ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000 >
EI
Q
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% #7: CORRECT abbreviated key names, INCORRECT full keys
% for Interpolate. If appearance is different to the other
% images then the PDF parser is incorrect!
q
BT
0 0 0 rg % Black text
/F1 8 Tf
10 0 0 10 465 220 Tm
(7) Tj
ET
Q
q
0 1 0 rg % Green fill
430 100 200 100 re f % Paint green rectangle below image
200 0 0 100 430 100 cm
BI
/W 20
/H 10
/BPC 8
/CS /RGB
/I false %% COMMENT OUT THIS LINE TO SEE EFFECT!
/Interpolate true
/F [/AHx]
/Length 1240
ID
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ffff00ffff00ff
ff00ffff00ff0000ff0000ffff000000
ff0000ff0000ffffff000000ffffff00
ffff00ffff000000ffffff00ffff00ff
ff000000ff0000ffffff00ffff00ffff
00ff0000ff0000ffff00ffff000000ff
ffff00ffff000000ff0000ffffff0000
00ff0000ffffff00ffff000000ffffff
00ffff000000ffffff00ffff00ff0000
ff0000ffff00ffff000000ffffff00ff
ff000000ffffff000000ffffff000000
ffffff000000ffffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
ff00ffff000000ffffff00ffff000000
ffffff000000ffffff000000ffffff00
0000ffffff00ffff000000ff0000ffff
ff00ffff00ff0000ff0000ffff00ffff
000000ffffff00ffff000000ffffff00
ffff00ffff000000ffffff00ffff0000
00ffffff00ffff000000ffffff00ffff
00ff0000ff0000ffff000000ff0000ff
0000ffffff000000ffffff00ffff00ff
ff000000ffffff00ffff00ffff000000
ff0000ff0000ffffff00ffff00ff0000
ff0000ffff00ffff00ffff00ffff00ff
ff00ffff00ffff00ffff00ffff00ffff
00ffff00ffff00ffff00ffff00ffff00
ffff00ffff00ffff00ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff00
00ff0000ff0000ff0000ff0000ff0000
ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000 >
EI
Q
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% #8: CORRECT abbreviated key names, INCORRECT full keys
% for DecodeParams. If appearance is different to the other
% images then the PDF parser is incorrect!
q
BT
0 0 0 rg % Black text
/F1 8 Tf
10 0 0 10 675 220 Tm
(8) Tj
ET
Q
q
0 1 0 rg % Green fill
640 100 200 100 re f % Paint green rectangle below image
200 0 0 100 640 100 cm
BI
/W 20
/H 10
/BPC 8
/CS /RGB
/F [ /AHx /Fl ]
/DP [ null << /Predictor 15 /Colors 3 /BitsPerComponent 8 /Columns 20 >> ] %% THIS IS REQUIRED TO VIEW IMAGE CORRECTLY
/DecodeParms [ null null ]
/Length 197
ID
28919d90510e80200c435be2fdaf5c3f
a6653297280b2165e175050afb7500c0
9e01312e41c50a3d2f3c753e02372cd1
bb998594283137c76ba2b894bdac2d5a
b8ab25790be7094e9b9b13ae8fac5ef5
c3c2f05776a3e8677da81323233119>
EI
endstream
endobj
6 0 obj
<< /Type /Font
/Subtype /Type1
/BaseFont /Helvetica
>>
endobj
7 0 obj
<< /CreationDate (D:20210529)
/Producer (Manual)
/Creator (Peter Wyatt for SafeDocs)
/Author (Peter Wyatt)
/Subject (Inline Image Test for abbreviated and full key names)
/Title (Inline Image Test for abbreviated and full key names)
/Keywords (image, inline, abbreviation, ambiguous)
>>
endobj
xref
0 8
0000000000 65536 f
0000000048 00000 n
0000000137 00000 n
0000000194 00000 n
0000000267 00000 n
0000000791 00000 n
0000014420 00000 n
0000014509 00000 n
trailer
<< /Size 8
/Root 1 0 R
/Info 7 0 R
>>
startxref
14872
%%EOF

View File

@ -85,6 +85,12 @@
"lastPage": 2,
"type": "eq"
},
{ "id": "issue14256",
"file": "pdfs/issue14256.pdf",
"md5": "15938b7562146dbea7ed8aa15b172fe6",
"rounds": 1,
"type": "eq"
},
{ "id": "issue11549",
"file": "pdfs/issue11549_reduced.pdf",
"md5": "a1ea636f413e02e10dbdf379ab4a99ae",

View File

@ -87,7 +87,7 @@ describe("primitives", function () {
const checkInvalidKeyValues = function (dict) {
expect(dict.get()).toBeUndefined();
expect(dict.get("Prev")).toBeUndefined();
expect(dict.get("Decode", "D")).toBeUndefined();
expect(dict.get("D", "Decode")).toBeUndefined();
expect(dict.get("FontFile", "FontFile2", "FontFile3")).toBeUndefined();
};