Skip to content

Commit

Permalink
Handle parse error stream data (fixes #1123)
Browse files Browse the repository at this point in the history
A parse error in stream data in which stream data contained a nested
object would cause a crash because qpdf was not correctly updating its
internal state. Rework the QPDF json reactor to not be sensitive to
parse errors in this way.
  • Loading branch information
jberkenbilt committed Feb 4, 2024
1 parent 7caa9dd commit cb0f390
Show file tree
Hide file tree
Showing 14 changed files with 311 additions and 151 deletions.
287 changes: 148 additions & 139 deletions libqpdf/QPDF_json.cc

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion qpdf/qpdf.testcov
Expand Up @@ -668,7 +668,6 @@ QPDF_json value stream both or neither 0
QPDFJob need json-stream-prefix for stdout 0
QPDFJob write json to stdout 0
QPDFJob write json to file 0
QPDF_json don't check object after parse error 0
QPDF_json ignoring unknown top-level key 0
QPDF_json ignore second-level key 0
QPDF_json ignore unknown key in object_top 0
Expand All @@ -694,3 +693,6 @@ QPDFJob misplaced page range 0
QPDFJob duplicated range 0
QPDFJob json over/under no file 0
QPDF_Array copy 1
QPDF_json stream data not string 0
QPDF_json stream datafile not string 0
QPDF_json stream not a dictionary 0
2 changes: 2 additions & 0 deletions qpdf/qtest/qpdf-json.test
Expand Up @@ -37,6 +37,8 @@ my @badfiles = (
'obj-key-errors',
'bad-data',
'bad-datafile',
'bad-data2',
'bad-datafile2',
);

$n_tests += scalar(@badfiles);
Expand Down
71 changes: 71 additions & 0 deletions qpdf/qtest/qpdf/qjson-bad-data2.json
@@ -0,0 +1,71 @@
{
"qpdf": [
{
"jsonversion": 2,
"pdfversion": "1.3",
"maxobjectid": 6
},
{
"obj:1 0 R": {
"value": {
"/Pages": "2 0 R",
"/Type": "/Catalog"
}
},
"obj:2 0 R": {
"value": {
"/Count": 1,
"/Kids": [
"3 0 R"
],
"/Type": "/Pages"
}
},
"obj:3 0 R": {
"value": {
"/Contents": ["4 0 R", "7 0 R"],
"/MediaBox": [
0,
0,
612,
792
],
"/Parent": "2 0 R",
"/Resources": {
"/Font": {
"/F1": "6 0 R"
},
"/ProcSet": "5 0 R"
},
"/Type": "/Page"
}
},
"obj:4 0 R": {
"stream": {
"data": [[]],
"dict": {}
}
},
"obj:5 0 R": {
"value": [
"/PDF",
"/Text"
]
},
"obj:6 0 R": {
"value": {
"/BaseFont": "/Helvetica",
"/Encoding": "/WinAnsiEncoding",
"/Subtype": "/Type1",
"/Type": "/Font"
}
},
"trailer": {
"value": {
"/Root": "1 0 R",
"/Size": 7
}
}
}
]
}
2 changes: 2 additions & 0 deletions qpdf/qtest/qpdf/qjson-bad-data2.out
@@ -0,0 +1,2 @@
WARNING: qjson-bad-data2.json (obj:4 0 R, offset 846): "stream.data" must be a string
qpdf: qjson-bad-data2.json: errors found in JSON
71 changes: 71 additions & 0 deletions qpdf/qtest/qpdf/qjson-bad-datafile2.json
@@ -0,0 +1,71 @@
{
"qpdf": [
{
"jsonversion": 2,
"pdfversion": "1.3",
"maxobjectid": 6
},
{
"obj:1 0 R": {
"value": {
"/Pages": "2 0 R",
"/Type": "/Catalog"
}
},
"obj:2 0 R": {
"value": {
"/Count": 1,
"/Kids": [
"3 0 R"
],
"/Type": "/Pages"
}
},
"obj:3 0 R": {
"value": {
"/Contents": ["4 0 R", "7 0 R"],
"/MediaBox": [
0,
0,
612,
792
],
"/Parent": "2 0 R",
"/Resources": {
"/Font": {
"/F1": "6 0 R"
},
"/ProcSet": "5 0 R"
},
"/Type": "/Page"
}
},
"obj:4 0 R": {
"stream": {
"datafile": [[]],
"dict": {}
}
},
"obj:5 0 R": {
"value": [
"/PDF",
"/Text"
]
},
"obj:6 0 R": {
"value": {
"/BaseFont": "/Helvetica",
"/Encoding": "/WinAnsiEncoding",
"/Subtype": "/Type1",
"/Type": "/Font"
}
},
"trailer": {
"value": {
"/Root": "1 0 R",
"/Size": 7
}
}
}
]
}
2 changes: 2 additions & 0 deletions qpdf/qtest/qpdf/qjson-bad-datafile2.out
@@ -0,0 +1,2 @@
WARNING: qjson-bad-datafile2.json (obj:4 0 R, offset 850): "stream.datafile" must be a string containing a file name
qpdf: qjson-bad-datafile2.json: errors found in JSON
4 changes: 2 additions & 2 deletions qpdf/qtest/qpdf/qjson-bad-pdf-version1.out
@@ -1,3 +1,3 @@
WARNING: qjson-bad-pdf-version1.json (offset 41): invalid JSON version (must be 2)
WARNING: qjson-bad-pdf-version1.json (offset 70): invalid PDF version (must be x.y)
WARNING: qjson-bad-pdf-version1.json (offset 41): invalid JSON version (must be numeric value 2)
WARNING: qjson-bad-pdf-version1.json (offset 70): invalid PDF version (must be "x.y")
qpdf: qjson-bad-pdf-version1.json: errors found in JSON
4 changes: 2 additions & 2 deletions qpdf/qtest/qpdf/qjson-bad-pdf-version2.out
@@ -1,5 +1,5 @@
WARNING: qjson-bad-pdf-version2.json (offset 41): invalid JSON version (must be 2)
WARNING: qjson-bad-pdf-version2.json (offset 66): invalid PDF version (must be x.y)
WARNING: qjson-bad-pdf-version2.json (offset 41): invalid JSON version (must be numeric value 2)
WARNING: qjson-bad-pdf-version2.json (offset 66): invalid PDF version (must be "x.y")
WARNING: qjson-bad-pdf-version2.json (offset 97): calledgetallpages must be a boolean
WARNING: qjson-bad-pdf-version2.json (offset 138): pushedinheritedpageresources must be a boolean
qpdf: qjson-bad-pdf-version2.json: errors found in JSON
6 changes: 3 additions & 3 deletions qpdf/qtest/qpdf/qjson-obj-key-errors.out
@@ -1,7 +1,7 @@
WARNING: qjson-obj-key-errors.json (obj:2 0 R, offset 244): object must have exactly one of "value" or "stream"
WARNING: qjson-obj-key-errors.json (obj:3 0 R, offset 542): object must have exactly one of "value" or "stream"
WARNING: qjson-obj-key-errors.json (obj:4 0 R, offset 710): "stream" is missing "dict"
WARNING: qjson-obj-key-errors.json (obj:4 0 R, offset 710): new "stream" must have exactly one of "data" or "datafile"
WARNING: qjson-obj-key-errors.json (obj:5 0 R, offset 800): new "stream" must have exactly one of "data" or "datafile"
WARNING: qjson-obj-key-errors.json (obj:4 0 R, offset 690): "stream" is missing "dict"
WARNING: qjson-obj-key-errors.json (obj:4 0 R, offset 690): new "stream" must have exactly one of "data" or "datafile"
WARNING: qjson-obj-key-errors.json (obj:5 0 R, offset 780): new "stream" must have exactly one of "data" or "datafile"
WARNING: qjson-obj-key-errors.json (trailer, offset 1178): "trailer" is missing "value"
qpdf: qjson-obj-key-errors.json: errors found in JSON
3 changes: 1 addition & 2 deletions qpdf/qtest/qpdf/qjson-stream-dict-not-dict.out
@@ -1,5 +1,4 @@
WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 142): "stream.dict" must be a dictionary
WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 142): unrecognized string value
WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 122): new "stream" must have exactly one of "data" or "datafile"
WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 102): new "stream" must have exactly one of "data" or "datafile"
WARNING: qjson-stream-dict-not-dict.json: "qpdf[1].trailer" was not seen
qpdf: qjson-stream-dict-not-dict.json: errors found in JSON
1 change: 1 addition & 0 deletions qpdf/qtest/qpdf/qjson-stream-not-dict.out
@@ -1,3 +1,4 @@
WARNING: qjson-stream-not-dict.json (obj:1 0 R, offset 122): "stream" must be a dictionary
WARNING: qjson-stream-not-dict.json (obj:1 0 R, offset 102): "stream" is missing "dict"
WARNING: qjson-stream-not-dict.json: "qpdf[1].trailer" was not seen
qpdf: qjson-stream-not-dict.json: errors found in JSON
1 change: 1 addition & 0 deletions qpdf/qtest/qpdf/qjson-trailer-stream.out
@@ -1,2 +1,3 @@
WARNING: qjson-trailer-stream.json (trailer, offset 1269): the trailer may not be a stream
WARNING: qjson-trailer-stream.json (trailer, offset 1249): "trailer" is missing "value"
qpdf: qjson-trailer-stream.json: errors found in JSON
4 changes: 2 additions & 2 deletions qpdf/qtest/qpdf/update-from-json-errors.out
@@ -1,4 +1,4 @@
WARNING: good13.pdf (obj:4 0 R from qpdf-json-update-errors.json, offset 95): existing "stream" may at most one of "data" or "datafile"
WARNING: good13.pdf (obj:4 0 R from qpdf-json-update-errors.json, offset 75): existing "stream" may at most one of "data" or "datafile"
WARNING: good13.pdf (obj:20 0 R from qpdf-json-update-errors.json, offset 335): unrecognized string value
WARNING: good13.pdf (obj:20 0 R from qpdf-json-update-errors.json, offset 293): new "stream" must have exactly one of "data" or "datafile"
WARNING: good13.pdf (obj:20 0 R from qpdf-json-update-errors.json, offset 273): new "stream" must have exactly one of "data" or "datafile"
qpdf: qpdf-json-update-errors.json: errors found in JSON

0 comments on commit cb0f390

Please sign in to comment.