Commit 4aa6ee8d1510d92e17728438f2f9636739343ffc
1 parent
54753f37
Refactor `QPDF::readLinearizationData`: simplify linearization dictionary key ha…
…ndling, replace `QPDFObjectHandle` with direct type usage, and remove redundant `QTC::TC` calls.
Showing
2 changed files
with
39 additions
and
63 deletions
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 | ... | ... |