Ignore Annotations with too large border widths, to prevent the annotationLayer from rendering it over the surrounding document (bug 1552113)

The border `width` will instead fallback to the default value of `1`, rather than ignoring it altoghether, to also ensure that e.g. `LinkAnnotation`s become clickable as intended.

Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1552113
This commit is contained in:
Jonas Jenwald 2019-05-31 20:44:24 +02:00
parent 209e42043a
commit 876c962235
4 changed files with 127 additions and 5 deletions

View File

@ -16,7 +16,8 @@
import { import {
AnnotationBorderStyleType, AnnotationFieldFlag, AnnotationFlag, AnnotationBorderStyleType, AnnotationFieldFlag, AnnotationFlag,
AnnotationType, isString, OPS, stringToBytes, stringToPDFString, Util, warn AnnotationType, assert, isString, OPS, stringToBytes, stringToPDFString, Util,
warn
} from '../shared/util'; } from '../shared/util';
import { Catalog, FileSpec, ObjectLoader } from './obj'; import { Catalog, FileSpec, ObjectLoader } from './obj';
import { Dict, isDict, isName, isRef, isStream } from './primitives'; import { Dict, isDict, isName, isRef, isStream } from './primitives';
@ -361,6 +362,11 @@ class Annotation {
* @param {Dict} borderStyle - The border style dictionary * @param {Dict} borderStyle - The border style dictionary
*/ */
setBorderStyle(borderStyle) { setBorderStyle(borderStyle) {
if (typeof PDFJSDev === 'undefined' ||
PDFJSDev.test('!PRODUCTION || TESTING')) {
assert(this.rectangle, 'setRectangle must have been called previously.');
}
this.borderStyle = new AnnotationBorderStyle(); this.borderStyle = new AnnotationBorderStyle();
if (!isDict(borderStyle)) { if (!isDict(borderStyle)) {
return; return;
@ -370,7 +376,7 @@ class Annotation {
let dictType = dict.get('Type'); let dictType = dict.get('Type');
if (!dictType || isName(dictType, 'Border')) { if (!dictType || isName(dictType, 'Border')) {
this.borderStyle.setWidth(dict.get('W')); this.borderStyle.setWidth(dict.get('W'), this.rectangle);
this.borderStyle.setStyle(dict.get('S')); this.borderStyle.setStyle(dict.get('S'));
this.borderStyle.setDashArray(dict.getArray('D')); this.borderStyle.setDashArray(dict.getArray('D'));
} }
@ -379,7 +385,7 @@ class Annotation {
if (Array.isArray(array) && array.length >= 3) { if (Array.isArray(array) && array.length >= 3) {
this.borderStyle.setHorizontalCornerRadius(array[0]); this.borderStyle.setHorizontalCornerRadius(array[0]);
this.borderStyle.setVerticalCornerRadius(array[1]); this.borderStyle.setVerticalCornerRadius(array[1]);
this.borderStyle.setWidth(array[2]); this.borderStyle.setWidth(array[2], this.rectangle);
if (array.length === 4) { // Dash array available if (array.length === 4) { // Dash array available
this.borderStyle.setDashArray(array[3]); this.borderStyle.setDashArray(array[3]);
@ -497,9 +503,16 @@ class AnnotationBorderStyle {
* *
* @public * @public
* @memberof AnnotationBorderStyle * @memberof AnnotationBorderStyle
* @param {integer} width - The width * @param {integer} width - The width.
* @param {Array} rect - The annotation `Rect` entry.
*/ */
setWidth(width) { setWidth(width, rect = [0, 0, 0, 0]) {
if (typeof PDFJSDev === 'undefined' ||
PDFJSDev.test('!PRODUCTION || TESTING')) {
assert(Array.isArray(rect) && rect.length === 4,
'A valid `rect` parameter must be provided.');
}
// Some corrupt PDF generators may provide the width as a `Name`, // Some corrupt PDF generators may provide the width as a `Name`,
// rather than as a number (fixes issue 10385). // rather than as a number (fixes issue 10385).
if (isName(width)) { if (isName(width)) {
@ -507,6 +520,19 @@ class AnnotationBorderStyle {
return; return;
} }
if (Number.isInteger(width)) { if (Number.isInteger(width)) {
if (width > 0) {
const maxWidth = (rect[2] - rect[0]) / 2;
const maxHeight = (rect[3] - rect[1]) / 2;
// Ignore large `width`s, since they lead to the Annotation overflowing
// the size set by the `Rect` entry thus causing the `annotationLayer`
// to render it over the surrounding document (fixes bug1552113.pdf).
if ((maxWidth > 0 && maxHeight > 0) &&
(width > maxWidth || width > maxHeight)) {
warn(`AnnotationBorderStyle.setWidth - ignoring width: ${width}`);
width = 1;
}
}
this.width = width; this.width = width;
} }
} }

View File

@ -96,6 +96,7 @@
!bug1245391_reduced.pdf !bug1245391_reduced.pdf
!bug1252420.pdf !bug1252420.pdf
!bug1513120_reduced.pdf !bug1513120_reduced.pdf
!bug1552113.pdf
!issue9949.pdf !issue9949.pdf
!bug1308536.pdf !bug1308536.pdf
!bug1337429.pdf !bug1337429.pdf

86
test/pdfs/bug1552113.pdf Normal file
View File

@ -0,0 +1,86 @@
%PDF-1.7
%âãÏÓ
1 0 obj
<<
/Pages 2 0 R
/Type /Catalog
>>
endobj
2 0 obj
<<
/Kids [3 0 R]
/Type /Pages
/Count 1
>>
endobj
3 0 obj
<<
/Parent 2 0 R
/Annots [4 0 R]
/Resources
<<
/Font
<<
/F1 5 0 R
>>
>>
/MediaBox [0 0 250 50]
/Type /Page
/Contents 6 0 R
>>
endobj
4 0 obj
<<
/Border [0 0 112]
/Subtype /Link
/C [0 0 1]
/A
<<
/URI (http://www.example.org)
/Type /Action
/S /URI
>>
/Type /Annot
/Rect [5 25 155 45]
>>
endobj
5 0 obj
<<
/BaseFont /Times-Roman
/Subtype /Type1
/Type /Font
/Encoding /WinAnsiEncoding
>>
endobj
6 0 obj
<<
/Length 111
>>
stream
BT
10 30 TD
/F1 14 Tf
(http://www.example.org/) Tj
0 -20 Td
(Bug 1552113 - this text should be visible.) Tj
ET
endstream
endobj xref
0 7
0000000000 65535 f
0000000015 00000 n
0000000066 00000 n
0000000125 00000 n
0000000270 00000 n
0000000432 00000 n
0000000533 00000 n
trailer
<<
/Root 1 0 R
/Size 7
>>
startxref
697
%%EOF

View File

@ -680,6 +680,15 @@
"annotations": true, "annotations": true,
"about": "Annotation with (unsupported) file:// URL." "about": "Annotation with (unsupported) file:// URL."
}, },
{ "id": "bug1552113",
"file": "pdfs/bug1552113.pdf",
"md5": "dafb7ba1328e8deaab2e3619c94bf974",
"link": false,
"rounds": 1,
"type": "eq",
"annotations": true,
"about": "Annotation with (ridiculously) large border width."
},
{ "id": "issue4934", { "id": "issue4934",
"file": "pdfs/issue4934.pdf", "file": "pdfs/issue4934.pdf",
"md5": "6099da44f677702ae65a648b51a2226d", "md5": "6099da44f677702ae65a648b51a2226d",