Commit 6d4e3ba8a43d8a084a94f9cea4669cb35812fb67

Authored by Jay Berkenbilt
1 parent 5a2aa594

Test (and fix) handling of dangling references

libqpdf/QPDF_json.cc
@@ -147,6 +147,7 @@ QPDF::JSONReactor::arrayStart() @@ -147,6 +147,7 @@ QPDF::JSONReactor::arrayStart()
147 void 147 void
148 QPDF::JSONReactor::containerEnd(JSON const& value) 148 QPDF::JSONReactor::containerEnd(JSON const& value)
149 { 149 {
  150 + auto from_state = state;
150 state = state_stack.back(); 151 state = state_stack.back();
151 state_stack.pop_back(); 152 state_stack.pop_back();
152 if (state == st_initial) { 153 if (state == st_initial) {
@@ -215,10 +216,13 @@ QPDF::JSONReactor::containerEnd(JSON const& value) @@ -215,10 +216,13 @@ QPDF::JSONReactor::containerEnd(JSON const& value)
215 if (!parse_error) { 216 if (!parse_error) {
216 object_stack.pop_back(); 217 object_stack.pop_back();
217 } 218 }
218 - } else if (state == st_qpdf) { 219 + } else if ((state == st_top) && (from_state == st_qpdf)) {
219 for (auto const& og: this->reserved) { 220 for (auto const& og: this->reserved) {
220 - // QXXXQ  
221 - // QTC::TC("qpdf", "QPDF_json non-trivial null reserved"); 221 + // Handle dangling indirect object references which the
  222 + // PDF spec says to treat as nulls. It's tempting to make
  223 + // this an error, but that would be wrong since valid
  224 + // input files may have these.
  225 + QTC::TC("qpdf", "QPDF_json non-trivial null reserved");
222 this->pdf.replaceObject(og, QPDFObjectHandle::newNull()); 226 this->pdf.replaceObject(og, QPDFObjectHandle::newNull());
223 } 227 }
224 this->reserved.clear(); 228 this->reserved.clear();
qpdf/qpdf.testcov
@@ -675,3 +675,4 @@ QPDF_json ignore second-level key 0 @@ -675,3 +675,4 @@ QPDF_json ignore second-level key 0
675 QPDF_json ignore unknown key in object_top 0 675 QPDF_json ignore unknown key in object_top 0
676 QPDF_json ignore unknown key in trailer 0 676 QPDF_json ignore unknown key in trailer 0
677 QPDF_json ignore unknown key in stream 0 677 QPDF_json ignore unknown key in stream 0
  678 +QPDF_json non-trivial null reserved 0
qpdf/qtest/qpdf/good13.out
1 /QTest is indirect and has type dictionary (9) 1 /QTest is indirect and has type dictionary (9)
2 /QTest is a dictionary 2 /QTest is a dictionary
  3 + /dangling-ref-for-json-test is direct
3 /hex strings is direct 4 /hex strings is direct
4 /indirect is indirect 5 /indirect is indirect
5 /names is direct 6 /names is direct
6 /nesting is direct 7 /nesting is direct
7 /strings is direct 8 /strings is direct
8 unparse: 7 0 R 9 unparse: 7 0 R
9 -unparseResolved: << /hex#20strings [ (Potato) <01020300040560> (AB) ] /indirect 8 0 R /names [ /nesting /hex#20strings /text#2fplain ] /nesting << /a [ 1 2 << /x (y) >> [ (z) ] ] /b << / (legal) /a [ 1 2 ] >> >> /strings [ (one) <24a2> () (\(\)) (\() (\)) (a\f\b\t\r\nb) (") ("") ("\("\)") <410042> (a\nb) (a b) <efbbbfcf80> <efbbbff09fa594> ] >> 10 +unparseResolved: << /dangling-ref-for-json-test [ 9 0 R ] /hex#20strings [ (Potato) <01020300040560> (AB) ] /indirect 8 0 R /names [ /nesting /hex#20strings /text#2fplain ] /nesting << /a [ 1 2 << /x (y) >> [ (z) ] ] /b << / (legal) /a [ 1 2 ] >> >> /strings [ (one) <24a2> () (\(\)) (\() (\)) (a\f\b\t\r\nb) (") ("") ("\("\)") <410042> (a\nb) (a b) <efbbbfcf80> <efbbbff09fa594> ] >>
10 test 1 done 11 test 1 done
qpdf/qtest/qpdf/good13.pdf
@@ -74,6 +74,7 @@ b) (π) (🥔)] @@ -74,6 +74,7 @@ b) (π) (🥔)]
74 /b <</a [1 2] / (legal)>> 74 /b <</a [1 2] / (legal)>>
75 >> 75 >>
76 /names [/n#65sting /hex#20strings /text#2fplain] 76 /names [/n#65sting /hex#20strings /text#2fplain]
  77 + /dangling-ref-for-json-test [9 0 R]
77 >> 78 >>
78 endobj 79 endobj
79 80
@@ -81,6 +82,12 @@ endobj @@ -81,6 +82,12 @@ endobj
81 (hello) 82 (hello)
82 endobj 83 endobj
83 84
  85 +% NOTE:
  86 +%
  87 +% If adding a new object, update /dangling-ref-for-json-test to point
  88 +% to something that's not here.
  89 +%
  90 +
84 xref 91 xref
85 0 9 92 0 9
86 0000000000 65535 f 93 0000000000 65535 f
@@ -91,12 +98,12 @@ xref @@ -91,12 +98,12 @@ xref
91 0000000403 00000 n 98 0000000403 00000 n
92 0000000438 00000 n 99 0000000438 00000 n
93 0000000556 00000 n 100 0000000556 00000 n
94 -0000000908 00000 n 101 +0000000946 00000 n
95 trailer << 102 trailer <<
96 /Size 9 103 /Size 9
97 /Root 1 0 R 104 /Root 1 0 R
98 /QTest 7 0 R 105 /QTest 7 0 R
99 >> 106 >>
100 startxref 107 startxref
101 -932 108 +1085
102 %%EOF 109 %%EOF
qpdf/qtest/qpdf/good13.qdf
@@ -13,12 +13,15 @@ endobj @@ -13,12 +13,15 @@ endobj
13 %% Original object ID: 7 0 13 %% Original object ID: 7 0
14 2 0 obj 14 2 0 obj
15 << 15 <<
  16 + /dangling-ref-for-json-test [
  17 + 4 0 R
  18 + ]
16 /hex#20strings [ 19 /hex#20strings [
17 (Potato) 20 (Potato)
18 <01020300040560> 21 <01020300040560>
19 (AB) 22 (AB)
20 ] 23 ]
21 - /indirect 4 0 R 24 + /indirect 5 0 R
22 /names [ 25 /names [
23 /nesting 26 /nesting
24 /hex#20strings 27 /hex#20strings
@@ -68,22 +71,27 @@ endobj @@ -68,22 +71,27 @@ endobj
68 << 71 <<
69 /Count 1 72 /Count 1
70 /Kids [ 73 /Kids [
71 - 5 0 R 74 + 6 0 R
72 ] 75 ]
73 /Type /Pages 76 /Type /Pages
74 >> 77 >>
75 endobj 78 endobj
76 79
77 -%% Original object ID: 8 0 80 +%% Original object ID: 9 0
78 4 0 obj 81 4 0 obj
  82 +null
  83 +endobj
  84 +
  85 +%% Original object ID: 8 0
  86 +5 0 obj
79 (hello) 87 (hello)
80 endobj 88 endobj
81 89
82 %% Page 1 90 %% Page 1
83 %% Original object ID: 3 0 91 %% Original object ID: 3 0
84 -5 0 obj 92 +6 0 obj
85 << 93 <<
86 - /Contents 6 0 R 94 + /Contents 7 0 R
87 /MediaBox [ 95 /MediaBox [
88 0 96 0
89 0 97 0
@@ -93,9 +101,9 @@ endobj @@ -93,9 +101,9 @@ endobj
93 /Parent 3 0 R 101 /Parent 3 0 R
94 /Resources << 102 /Resources <<
95 /Font << 103 /Font <<
96 - /F1 8 0 R 104 + /F1 9 0 R
97 >> 105 >>
98 - /ProcSet 9 0 R 106 + /ProcSet 10 0 R
99 >> 107 >>
100 /Type /Page 108 /Type /Page
101 >> 109 >>
@@ -103,9 +111,9 @@ endobj @@ -103,9 +111,9 @@ endobj
103 111
104 %% Contents for page 1 112 %% Contents for page 1
105 %% Original object ID: 4 0 113 %% Original object ID: 4 0
106 -6 0 obj 114 +7 0 obj
107 << 115 <<
108 - /Length 7 0 R 116 + /Length 8 0 R
109 >> 117 >>
110 stream 118 stream
111 BT 119 BT
@@ -116,12 +124,12 @@ ET @@ -116,12 +124,12 @@ ET
116 endstream 124 endstream
117 endobj 125 endobj
118 126
119 -7 0 obj 127 +8 0 obj
120 44 128 44
121 endobj 129 endobj
122 130
123 %% Original object ID: 6 0 131 %% Original object ID: 6 0
124 -8 0 obj 132 +9 0 obj
125 << 133 <<
126 /BaseFont /Helvetica 134 /BaseFont /Helvetica
127 /Encoding /WinAnsiEncoding 135 /Encoding /WinAnsiEncoding
@@ -132,7 +140,7 @@ endobj @@ -132,7 +140,7 @@ endobj
132 endobj 140 endobj
133 141
134 %% Original object ID: 5 0 142 %% Original object ID: 5 0
135 -9 0 obj 143 +10 0 obj
136 [ 144 [
137 /PDF 145 /PDF
138 /Text 146 /Text
@@ -140,23 +148,24 @@ endobj @@ -140,23 +148,24 @@ endobj
140 endobj 148 endobj
141 149
142 xref 150 xref
143 -0 10 151 +0 11
144 0000000000 65535 f 152 0000000000 65535 f
145 0000000052 00000 n 153 0000000052 00000 n
146 0000000133 00000 n 154 0000000133 00000 n
147 -0000000710 00000 n  
148 -0000000809 00000 n  
149 -0000000870 00000 n  
150 -0000001112 00000 n  
151 -0000001211 00000 n  
152 -0000001257 00000 n  
153 -0000001402 00000 n 155 +0000000756 00000 n
  156 +0000000855 00000 n
  157 +0000000903 00000 n
  158 +0000000964 00000 n
  159 +0000001207 00000 n
  160 +0000001306 00000 n
  161 +0000001352 00000 n
  162 +0000001497 00000 n
154 trailer << 163 trailer <<
155 /QTest 2 0 R 164 /QTest 2 0 R
156 /Root 1 0 R 165 /Root 1 0 R
157 - /Size 10 166 + /Size 11
158 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] 167 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
159 >> 168 >>
160 startxref 169 startxref
161 -1437 170 +1533
162 %%EOF 171 %%EOF
qpdf/qtest/qpdf/json-changed-good13.pdf
@@ -13,12 +13,15 @@ endobj @@ -13,12 +13,15 @@ endobj
13 %% Original object ID: 7 0 13 %% Original object ID: 7 0
14 2 0 obj 14 2 0 obj
15 << 15 <<
  16 + /dangling-ref-for-json-test [
  17 + 4 0 R
  18 + ]
16 /hex#20strings [ 19 /hex#20strings [
17 (Potato) 20 (Potato)
18 <01020300040560> 21 <01020300040560>
19 (AB) 22 (AB)
20 ] 23 ]
21 - /indirect 4 0 R 24 + /indirect 5 0 R
22 /names [ 25 /names [
23 /nesting 26 /nesting
24 /hex#20strings 27 /hex#20strings
@@ -68,22 +71,27 @@ endobj @@ -68,22 +71,27 @@ endobj
68 << 71 <<
69 /Count 1 72 /Count 1
70 /Kids [ 73 /Kids [
71 - 5 0 R 74 + 6 0 R
72 ] 75 ]
73 /Type /Pages 76 /Type /Pages
74 >> 77 >>
75 endobj 78 endobj
76 79
77 -%% Original object ID: 8 0 80 +%% Original object ID: 9 0
78 4 0 obj 81 4 0 obj
  82 +null
  83 +endobj
  84 +
  85 +%% Original object ID: 8 0
  86 +5 0 obj
79 (hello) 87 (hello)
80 endobj 88 endobj
81 89
82 %% Page 1 90 %% Page 1
83 %% Original object ID: 3 0 91 %% Original object ID: 3 0
84 -5 0 obj 92 +6 0 obj
85 << 93 <<
86 - /Contents 6 0 R 94 + /Contents 7 0 R
87 /MediaBox [ 95 /MediaBox [
88 0 96 0
89 0 97 0
@@ -93,9 +101,9 @@ endobj @@ -93,9 +101,9 @@ endobj
93 /Parent 3 0 R 101 /Parent 3 0 R
94 /Resources << 102 /Resources <<
95 /Font << 103 /Font <<
96 - /F1 8 0 R 104 + /F1 9 0 R
97 >> 105 >>
98 - /ProcSet 9 0 R 106 + /ProcSet 10 0 R
99 >> 107 >>
100 /Type /Page 108 /Type /Page
101 >> 109 >>
@@ -103,9 +111,9 @@ endobj @@ -103,9 +111,9 @@ endobj
103 111
104 %% Contents for page 1 112 %% Contents for page 1
105 %% Original object ID: 4 0 113 %% Original object ID: 4 0
106 -6 0 obj 114 +7 0 obj
107 << 115 <<
108 - /Length 7 0 R 116 + /Length 8 0 R
109 >> 117 >>
110 stream 118 stream
111 BT 119 BT
@@ -116,12 +124,12 @@ ET @@ -116,12 +124,12 @@ ET
116 endstream 124 endstream
117 endobj 125 endobj
118 126
119 -7 0 obj 127 +8 0 obj
120 44 128 44
121 endobj 129 endobj
122 130
123 %% Original object ID: 6 0 131 %% Original object ID: 6 0
124 -8 0 obj 132 +9 0 obj
125 << 133 <<
126 /BaseFont /Helvetica 134 /BaseFont /Helvetica
127 /Encoding /WinAnsiEncoding 135 /Encoding /WinAnsiEncoding
@@ -132,7 +140,7 @@ endobj @@ -132,7 +140,7 @@ endobj
132 endobj 140 endobj
133 141
134 %% Original object ID: 5 0 142 %% Original object ID: 5 0
135 -9 0 obj 143 +10 0 obj
136 [ 144 [
137 /PDF 145 /PDF
138 /Text 146 /Text
@@ -140,23 +148,24 @@ endobj @@ -140,23 +148,24 @@ endobj
140 endobj 148 endobj
141 149
142 xref 150 xref
143 -0 10 151 +0 11
144 0000000000 65535 f 152 0000000000 65535 f
145 0000000052 00000 n 153 0000000052 00000 n
146 0000000133 00000 n 154 0000000133 00000 n
147 -0000000706 00000 n  
148 -0000000805 00000 n  
149 -0000000866 00000 n  
150 -0000001108 00000 n  
151 -0000001207 00000 n  
152 -0000001253 00000 n  
153 -0000001398 00000 n 155 +0000000752 00000 n
  156 +0000000851 00000 n
  157 +0000000899 00000 n
  158 +0000000960 00000 n
  159 +0000001203 00000 n
  160 +0000001302 00000 n
  161 +0000001348 00000 n
  162 +0000001493 00000 n
154 trailer << 163 trailer <<
155 /QTest 2 0 R 164 /QTest 2 0 R
156 /Root 1 0 R 165 /Root 1 0 R
157 - /Size 10 166 + /Size 11
158 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] 167 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
159 >> 168 >>
160 startxref 169 startxref
161 -1433 170 +1529
162 %%EOF 171 %%EOF
qpdf/qtest/qpdf/manual-qpdf-json-out.json
1 { 1 {
2 "qpdf-v2": { 2 "qpdf-v2": {
3 "pdfversion": "2.0", 3 "pdfversion": "2.0",
4 - "maxobjectid": 8, 4 + "maxobjectid": 100,
5 "objects": { 5 "objects": {
6 "obj:1 0 R": { 6 "obj:1 0 R": {
7 "value": { 7 "value": {
@@ -119,7 +119,15 @@ @@ -119,7 +119,15 @@
119 } 119 }
120 }, 120 },
121 "obj:8 0 R": { 121 "obj:8 0 R": {
122 - "value": "u:hello" 122 + "value": {
  123 + "/dangling": [
  124 + "100 0 R"
  125 + ],
  126 + "/k1": "u:hello"
  127 + }
  128 + },
  129 + "obj:100 0 R": {
  130 + "value": null
123 }, 131 },
124 "trailer": { 132 "trailer": {
125 "value": { 133 "value": {
qpdf/qtest/qpdf/manual-qpdf-json-pdf.json
1 { 1 {
2 "qpdf-v2": { 2 "qpdf-v2": {
3 "pdfversion": "2.0", 3 "pdfversion": "2.0",
4 - "maxobjectid": 9, 4 + "maxobjectid": 10,
5 "objects": { 5 "objects": {
6 "obj:1 0 R": { 6 "obj:1 0 R": {
7 "value": { 7 "value": {
@@ -79,11 +79,16 @@ @@ -79,11 +79,16 @@
79 } 79 }
80 }, 80 },
81 "obj:4 0 R": { 81 "obj:4 0 R": {
82 - "value": "u:hello" 82 + "value": {
  83 + "/dangling": [
  84 + "6 0 R"
  85 + ],
  86 + "/k1": "u:hello"
  87 + }
83 }, 88 },
84 "obj:5 0 R": { 89 "obj:5 0 R": {
85 "value": { 90 "value": {
86 - "/Contents": "6 0 R", 91 + "/Contents": "7 0 R",
87 "/MediaBox": [ 92 "/MediaBox": [
88 0, 93 0,
89 0, 94 0,
@@ -93,23 +98,26 @@ @@ -93,23 +98,26 @@
93 "/Parent": "3 0 R", 98 "/Parent": "3 0 R",
94 "/Resources": { 99 "/Resources": {
95 "/Font": { 100 "/Font": {
96 - "/F1": "8 0 R" 101 + "/F1": "9 0 R"
97 }, 102 },
98 - "/ProcSet": "9 0 R" 103 + "/ProcSet": "10 0 R"
99 }, 104 },
100 "/Type": "/Page" 105 "/Type": "/Page"
101 } 106 }
102 }, 107 },
103 "obj:6 0 R": { 108 "obj:6 0 R": {
  109 + "value": null
  110 + },
  111 + "obj:7 0 R": {
104 "stream": { 112 "stream": {
105 "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", 113 "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=",
106 "dict": {} 114 "dict": {}
107 } 115 }
108 }, 116 },
109 - "obj:7 0 R": { 117 + "obj:8 0 R": {
110 "value": 44 118 "value": 44
111 }, 119 },
112 - "obj:8 0 R": { 120 + "obj:9 0 R": {
113 "value": { 121 "value": {
114 "/BaseFont": "/Helvetica", 122 "/BaseFont": "/Helvetica",
115 "/Encoding": "/WinAnsiEncoding", 123 "/Encoding": "/WinAnsiEncoding",
@@ -118,7 +126,7 @@ @@ -118,7 +126,7 @@
118 "/Type": "/Font" 126 "/Type": "/Font"
119 } 127 }
120 }, 128 },
121 - "obj:9 0 R": { 129 + "obj:10 0 R": {
122 "value": [ 130 "value": [
123 "/PDF", 131 "/PDF",
124 "/Text" 132 "/Text"
@@ -132,7 +140,7 @@ @@ -132,7 +140,7 @@
132 ], 140 ],
133 "/QTest": "2 0 R", 141 "/QTest": "2 0 R",
134 "/Root": "1 0 R", 142 "/Root": "1 0 R",
135 - "/Size": 10 143 + "/Size": 11
136 } 144 }
137 } 145 }
138 } 146 }
qpdf/qtest/qpdf/manual-qpdf-json.json
@@ -134,7 +134,10 @@ @@ -134,7 +134,10 @@
134 } 134 }
135 }, 135 },
136 "obj:8 0 R": { 136 "obj:8 0 R": {
137 - "value": "u:hello" 137 + "value": {
  138 + "/k1": "u:hello",
  139 + "/dangling": ["100 0 R"]
  140 + }
138 } 141 }
139 } 142 }
140 } 143 }
qpdf/qtest/qpdf/manual-qpdf-json.pdf
@@ -85,14 +85,19 @@ endobj @@ -85,14 +85,19 @@ endobj
85 85
86 %% Original object ID: 8 0 86 %% Original object ID: 8 0
87 4 0 obj 87 4 0 obj
88 -(hello) 88 +<<
  89 + /dangling [
  90 + 6 0 R
  91 + ]
  92 + /k1 (hello)
  93 +>>
89 endobj 94 endobj
90 95
91 %% Page 1 96 %% Page 1
92 %% Original object ID: 3 0 97 %% Original object ID: 3 0
93 5 0 obj 98 5 0 obj
94 << 99 <<
95 - /Contents 6 0 R 100 + /Contents 7 0 R
96 /MediaBox [ 101 /MediaBox [
97 0 102 0
98 0 103 0
@@ -102,19 +107,24 @@ endobj @@ -102,19 +107,24 @@ endobj
102 /Parent 3 0 R 107 /Parent 3 0 R
103 /Resources << 108 /Resources <<
104 /Font << 109 /Font <<
105 - /F1 8 0 R 110 + /F1 9 0 R
106 >> 111 >>
107 - /ProcSet 9 0 R 112 + /ProcSet 10 0 R
108 >> 113 >>
109 /Type /Page 114 /Type /Page
110 >> 115 >>
111 endobj 116 endobj
112 117
  118 +%% Original object ID: 100 0
  119 +6 0 obj
  120 +null
  121 +endobj
  122 +
113 %% Contents for page 1 123 %% Contents for page 1
114 %% Original object ID: 4 0 124 %% Original object ID: 4 0
115 -6 0 obj 125 +7 0 obj
116 << 126 <<
117 - /Length 7 0 R 127 + /Length 8 0 R
118 >> 128 >>
119 stream 129 stream
120 BT 130 BT
@@ -125,12 +135,12 @@ ET @@ -125,12 +135,12 @@ ET
125 endstream 135 endstream
126 endobj 136 endobj
127 137
128 -7 0 obj 138 +8 0 obj
129 44 139 44
130 endobj 140 endobj
131 141
132 %% Original object ID: 6 0 142 %% Original object ID: 6 0
133 -8 0 obj 143 +9 0 obj
134 << 144 <<
135 /BaseFont /Helvetica 145 /BaseFont /Helvetica
136 /Encoding /WinAnsiEncoding 146 /Encoding /WinAnsiEncoding
@@ -141,7 +151,7 @@ endobj @@ -141,7 +151,7 @@ endobj
141 endobj 151 endobj
142 152
143 %% Original object ID: 5 0 153 %% Original object ID: 5 0
144 -9 0 obj 154 +10 0 obj
145 [ 155 [
146 /PDF 156 /PDF
147 /Text 157 /Text
@@ -149,23 +159,24 @@ endobj @@ -149,23 +159,24 @@ endobj
149 endobj 159 endobj
150 160
151 xref 161 xref
152 -0 10 162 +0 11
153 0000000000 65535 f 163 0000000000 65535 f
154 0000000052 00000 n 164 0000000052 00000 n
155 0000000133 00000 n 165 0000000133 00000 n
156 0000000829 00000 n 166 0000000829 00000 n
157 0000000928 00000 n 167 0000000928 00000 n
158 -0000000989 00000 n  
159 -0000001231 00000 n  
160 -0000001330 00000 n  
161 -0000001376 00000 n  
162 -0000001521 00000 n 168 +0000001029 00000 n
  169 +0000001251 00000 n
  170 +0000001322 00000 n
  171 +0000001421 00000 n
  172 +0000001467 00000 n
  173 +0000001612 00000 n
163 trailer << 174 trailer <<
164 /QTest 2 0 R 175 /QTest 2 0 R
165 /Root 1 0 R 176 /Root 1 0 R
166 - /Size 10 177 + /Size 11
167 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] 178 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
168 >> 179 >>
169 startxref 180 startxref
170 -1556 181 +1648
171 %%EOF 182 %%EOF