Commit 4aa6ee8d1510d92e17728438f2f9636739343ffc

Authored by m-holger
1 parent 54753f37

Refactor `QPDF::readLinearizationData`: simplify linearization dictionary key ha…

…ndling, replace `QPDFObjectHandle` with direct type usage, and remove redundant `QTC::TC` calls.
libqpdf/QPDF_linearization.cc
@@ -150,80 +150,57 @@ QPDF::readLinearizationData() @@ -150,80 +150,57 @@ QPDF::readLinearizationData()
150 } 150 }
151 151
152 // /L is read and stored in linp by isLinearized() 152 // /L is read and stored in linp by isLinearized()
153 - QPDFObjectHandle H = m->lindict.getKey("/H");  
154 - QPDFObjectHandle O = m->lindict.getKey("/O");  
155 - QPDFObjectHandle E = m->lindict.getKey("/E");  
156 - QPDFObjectHandle N = m->lindict.getKey("/N");  
157 - QPDFObjectHandle T = m->lindict.getKey("/T");  
158 - QPDFObjectHandle P = m->lindict.getKey("/P");  
159 -  
160 - if (!(H.isArray() && O.isInteger() && E.isInteger() && N.isInteger() && T.isInteger() &&  
161 - (P.isInteger() || P.null()))) { 153 + Array H = m->lindict["/H"]; // hint table offset/length for primary and overflow hint tables
  154 + auto H_size = H.size();
  155 + Integer H_0 = H[0]; // hint table offset
  156 + Integer H_1 = H[1]; // hint table length
  157 + Integer H_2 = H[2]; // hint table offset for overflow hint table
  158 + Integer H_3 = H[3]; // hint table length for overflow hint table
  159 + Integer O = m->lindict["/O"];
  160 + Integer E = m->lindict["/E"];
  161 + Integer N = m->lindict["/N"];
  162 + Integer T = m->lindict["/T"];
  163 + auto P_oh = m->lindict["/P"];
  164 + Integer P = P_oh; // first page number
  165 + QTC::TC("qpdf", "QPDF P absent in lindict", P ? 0 : 1);
  166 +
  167 + if (!(H && O && E && N && T && (P || P_oh.null()))) {
162 throw damagedPDF( 168 throw damagedPDF(
163 "linearization dictionary", 169 "linearization dictionary",
164 "some keys in linearization dictionary are of the wrong type"); 170 "some keys in linearization dictionary are of the wrong type");
165 } 171 }
166 172
167 - // Hint table array: offset length [ offset length ]  
168 - size_t n_H_items = H.size();  
169 - if (!(n_H_items == 2 || n_H_items == 4)) { 173 + if (!(H_size == 2 || H_size == 4)) {
170 throw damagedPDF("linearization dictionary", "H has the wrong number of items"); 174 throw damagedPDF("linearization dictionary", "H has the wrong number of items");
171 } 175 }
172 176
173 - std::vector<int> H_items;  
174 - for (auto const& oh: H.as_array()) {  
175 - if (oh.isInteger()) {  
176 - H_items.push_back(oh.getIntValueAsInt());  
177 - } else {  
178 - throw damagedPDF("linearization dictionary", "some H items are of the wrong type");  
179 - }  
180 - }  
181 -  
182 - // H: hint table offset/length for primary and overflow hint tables  
183 - int H0_offset = H_items.at(0);  
184 - int H0_length = H_items.at(1);  
185 - int H1_offset = 0;  
186 - int H1_length = 0;  
187 - if (H_items.size() == 4) {  
188 - // Acrobat doesn't read or write these (as PDF 1.4), so we don't have a way to generate a  
189 - // test case.  
190 - // QTC::TC("qpdf", "QPDF overflow hint table");  
191 - H1_offset = H_items.at(2);  
192 - H1_length = H_items.at(3);  
193 - }  
194 -  
195 - // P: first page number  
196 - int first_page = 0;  
197 - if (P.isInteger()) {  
198 - QTC::TC("qpdf", "QPDF P present in lindict");  
199 - first_page = P.getIntValueAsInt();  
200 - } else {  
201 - QTC::TC("qpdf", "QPDF P absent in lindict"); 177 + if (!(H_0 && H_1 && (H_size == 2 || (H_2 && H_3)))) {
  178 + throw damagedPDF("linearization dictionary", "some H items are of the wrong type");
202 } 179 }
203 180
204 // Store linearization parameter data 181 // Store linearization parameter data
205 182
206 // Various places in the code use linp.npages, which is initialized from N, to pre-allocate 183 // Various places in the code use linp.npages, which is initialized from N, to pre-allocate
207 // memory, so make sure it's accurate and bail right now if it's not. 184 // memory, so make sure it's accurate and bail right now if it's not.
208 - if (N.getIntValue() != static_cast<long long>(getAllPages().size())) { 185 + if (N != getAllPages().size()) {
209 throw damagedPDF("linearization hint table", "/N does not match number of pages"); 186 throw damagedPDF("linearization hint table", "/N does not match number of pages");
210 } 187 }
211 188
212 // file_size initialized by isLinearized() 189 // file_size initialized by isLinearized()
213 - m->linp.first_page_object = O.getIntValueAsInt();  
214 - m->linp.first_page_end = E.getIntValue();  
215 - m->linp.npages = N.getUIntValueAsUInt();  
216 - m->linp.xref_zero_offset = T.getIntValue();  
217 - m->linp.first_page = first_page;  
218 - m->linp.H_offset = H0_offset;  
219 - m->linp.H_length = H0_length; 190 + m->linp.first_page_object = O;
  191 + m->linp.first_page_end = E;
  192 + m->linp.npages = N;
  193 + m->linp.xref_zero_offset = T;
  194 + m->linp.first_page = P ? P : 0;
  195 + m->linp.H_offset = H_0;
  196 + m->linp.H_length = H_1;
220 197
221 // Read hint streams 198 // Read hint streams
222 199
223 Pl_Buffer pb("hint buffer"); 200 Pl_Buffer pb("hint buffer");
224 - QPDFObjectHandle H0 = readHintStream(pb, H0_offset, toS(H0_length));  
225 - if (H1_offset) {  
226 - (void)readHintStream(pb, H1_offset, toS(H1_length)); 201 + auto H0 = readHintStream(pb, H_0, H_1);
  202 + if (H_2) {
  203 + (void)readHintStream(pb, H_2, H_3);
227 } 204 }
228 205
229 // PDF 1.4 hint tables that we ignore: 206 // PDF 1.4 hint tables that we ignore:
@@ -237,8 +214,8 @@ QPDF::readLinearizationData() @@ -237,8 +214,8 @@ QPDF::readLinearizationData()
237 // /L page label 214 // /L page label
238 215
239 // Individual hint table offsets 216 // Individual hint table offsets
240 - QPDFObjectHandle HS = H0.getKey("/S"); // shared object  
241 - QPDFObjectHandle HO = H0.getKey("/O"); // outline 217 + Integer HS = H0["/S"]; // shared object
  218 + Integer HO = H0["/O"]; // outline
242 219
243 auto hbp = pb.getBufferSharedPointer(); 220 auto hbp = pb.getBufferSharedPointer();
244 Buffer* hb = hbp.get(); 221 Buffer* hb = hbp.get();
@@ -247,18 +224,18 @@ QPDF::readLinearizationData() @@ -247,18 +224,18 @@ QPDF::readLinearizationData()
247 224
248 readHPageOffset(BitStream(h_buf, h_size)); 225 readHPageOffset(BitStream(h_buf, h_size));
249 226
250 - int HSi = HS.getIntValueAsInt();  
251 - if ((HSi < 0) || (toS(HSi) >= h_size)) { 227 + size_t HSi = HS;
  228 + if (HSi < 0 || HSi >= h_size) {
252 throw damagedPDF("linearization hint table", "/S (shared object) offset is out of bounds"); 229 throw damagedPDF("linearization hint table", "/S (shared object) offset is out of bounds");
253 } 230 }
254 - readHSharedObject(BitStream(h_buf + HSi, h_size - toS(HSi))); 231 + readHSharedObject(BitStream(h_buf + HSi, h_size - HSi));
255 232
256 - if (HO.isInteger()) {  
257 - int HOi = HO.getIntValueAsInt();  
258 - if ((HOi < 0) || (toS(HOi) >= h_size)) { 233 + if (HO) {
  234 + if (HO < 0 || HO >= h_size) {
259 throw damagedPDF("linearization hint table", "/O (outline) offset is out of bounds"); 235 throw damagedPDF("linearization hint table", "/O (outline) offset is out of bounds");
260 } 236 }
261 - readHGeneric(BitStream(h_buf + HOi, h_size - toS(HOi)), m->outline_hints); 237 + size_t HOi = HO;
  238 + readHGeneric(BitStream(h_buf + HO, h_size - HOi), m->outline_hints);
262 } 239 }
263 } 240 }
264 241
qpdf/qpdf.testcov
@@ -8,8 +8,7 @@ QPDF object stream offsets not increasing 0 @@ -8,8 +8,7 @@ QPDF object stream offsets not increasing 0
8 QPDF ignore self-referential object stream 0 8 QPDF ignore self-referential object stream 0
9 QPDF object stream contains id < 1 0 9 QPDF object stream contains id < 1 0
10 QPDF hint table length direct 0 10 QPDF hint table length direct 0
11 -QPDF P absent in lindict 0  
12 -QPDF P present in lindict 0 11 +QPDF P absent in lindict 1
13 QPDF expected n n obj 0 12 QPDF expected n n obj 0
14 QPDF err /T mismatch 0 13 QPDF err /T mismatch 0
15 QPDF err /O mismatch 0 14 QPDF err /O mismatch 0