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 150 }
151 151  
152 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 168 throw damagedPDF(
163 169 "linearization dictionary",
164 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 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 181 // Store linearization parameter data
205 182  
206 183 // Various places in the code use linp.npages, which is initialized from N, to pre-allocate
207 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 186 throw damagedPDF("linearization hint table", "/N does not match number of pages");
210 187 }
211 188  
212 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 198 // Read hint streams
222 199  
223 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 206 // PDF 1.4 hint tables that we ignore:
... ... @@ -237,8 +214,8 @@ QPDF::readLinearizationData()
237 214 // /L page label
238 215  
239 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 220 auto hbp = pb.getBufferSharedPointer();
244 221 Buffer* hb = hbp.get();
... ... @@ -247,18 +224,18 @@ QPDF::readLinearizationData()
247 224  
248 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 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 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 QPDF ignore self-referential object stream 0
9 9 QPDF object stream contains id < 1 0
10 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 12 QPDF expected n n obj 0
14 13 QPDF err /T mismatch 0
15 14 QPDF err /O mismatch 0
... ...