Commit 1e072e223a61d26b612864978b21aac6a0d0dc19
1 parent
0ac37bc9
Move QPDF::insertXrefEntry etc to QPDF::Xref_table
Showing
3 changed files
with
37 additions
and
25 deletions
include/qpdf/QPDF.hh
| ... | ... | @@ -777,9 +777,6 @@ class QPDF |
| 777 | 777 | QPDFObjectHandle& dict, |
| 778 | 778 | int max_num_entries, |
| 779 | 779 | std::function<QPDFExc(std::string_view)> damaged); |
| 780 | - void insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2); | |
| 781 | - void insertFreeXrefEntry(QPDFObjGen); | |
| 782 | - void insertReconstructedXrefEntry(int obj, qpdf_offset_t f1, int f2); | |
| 783 | 780 | void setLastObjectDescription(std::string const& description, QPDFObjGen const& og); |
| 784 | 781 | QPDFObjectHandle readTrailer(); |
| 785 | 782 | QPDFObjectHandle readObject(std::string const& description, QPDFObjGen og); | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -196,15 +196,16 @@ QPDF::EncryptionParameters::EncryptionParameters() : |
| 196 | 196 | { |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | -QPDF::Members::Members() : | |
| 199 | +QPDF::Members::Members(QPDF& qpdf) : | |
| 200 | 200 | log(QPDFLogger::defaultLogger()), |
| 201 | 201 | file(new InvalidInputSource()), |
| 202 | - encp(new EncryptionParameters) | |
| 202 | + encp(new EncryptionParameters), | |
| 203 | + xref_table(qpdf) | |
| 203 | 204 | { |
| 204 | 205 | } |
| 205 | 206 | |
| 206 | 207 | QPDF::QPDF() : |
| 207 | - m(new Members()) | |
| 208 | + m(new Members(*this)) | |
| 208 | 209 | { |
| 209 | 210 | m->tokenizer.allowEOF(); |
| 210 | 211 | // Generate a unique ID. It just has to be unique among all QPDF objects allocated throughout |
| ... | ... | @@ -585,7 +586,7 @@ QPDF::reconstruct_xref(QPDFExc& e) |
| 585 | 586 | int obj = QUtil::string_to_int(t1.getValue().c_str()); |
| 586 | 587 | int gen = QUtil::string_to_int(t2.getValue().c_str()); |
| 587 | 588 | if (obj <= m->xref_table.max_id) { |
| 588 | - insertReconstructedXrefEntry(obj, token_start, gen); | |
| 589 | + m->xref_table.insert_reconstructed(obj, token_start, gen); | |
| 589 | 590 | } else { |
| 590 | 591 | warn(damagedPDF( |
| 591 | 592 | "", 0, "ignoring object with impossibly large id " + std::to_string(obj))); |
| ... | ... | @@ -981,9 +982,9 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) |
| 981 | 982 | "xref table", "invalid xref entry (obj=" + std::to_string(i) + ")"); |
| 982 | 983 | } |
| 983 | 984 | if (type == 'f') { |
| 984 | - insertFreeXrefEntry(QPDFObjGen(toI(i), f2)); | |
| 985 | + m->xref_table.insert_free(QPDFObjGen(toI(i), f2)); | |
| 985 | 986 | } else { |
| 986 | - insertXrefEntry(toI(i), 1, f1, f2); | |
| 987 | + m->xref_table.insert(toI(i), 1, f1, f2); | |
| 987 | 988 | } |
| 988 | 989 | } |
| 989 | 990 | qpdf_offset_t pos = m->file->tell(); |
| ... | ... | @@ -1251,9 +1252,9 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) |
| 1251 | 1252 | // Ignore fields[2], which we don't care about in this case. This works around the |
| 1252 | 1253 | // issue of some PDF files that put invalid values, like -1, here for deleted |
| 1253 | 1254 | // objects. |
| 1254 | - insertFreeXrefEntry(QPDFObjGen(obj, 0)); | |
| 1255 | + m->xref_table.insert_free(QPDFObjGen(obj, 0)); | |
| 1255 | 1256 | } else { |
| 1256 | - insertXrefEntry(obj, toI(fields[0]), fields[1], toI(fields[2])); | |
| 1257 | + m->xref_table.insert(obj, toI(fields[0]), fields[1], toI(fields[2])); | |
| 1257 | 1258 | } |
| 1258 | 1259 | ++obj; |
| 1259 | 1260 | } |
| ... | ... | @@ -1276,7 +1277,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) |
| 1276 | 1277 | } |
| 1277 | 1278 | |
| 1278 | 1279 | void |
| 1279 | -QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2) | |
| 1280 | +QPDF::Xref_table::insert(int obj, int f0, qpdf_offset_t f1, int f2) | |
| 1280 | 1281 | { |
| 1281 | 1282 | // Populate the xref table in such a way that the first reference to an object that we see, |
| 1282 | 1283 | // which is the one in the latest xref table in which it appears, is the one that gets stored. |
| ... | ... | @@ -1285,22 +1286,23 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2) |
| 1285 | 1286 | // If there is already an entry for this object and generation in the table, it means that a |
| 1286 | 1287 | // later xref table has registered this object. Disregard this one. |
| 1287 | 1288 | |
| 1288 | - if (obj > m->xref_table.max_id) { | |
| 1289 | + if (obj > max_id) { | |
| 1289 | 1290 | // ignore impossibly large object ids or object ids > Size. |
| 1290 | 1291 | return; |
| 1291 | 1292 | } |
| 1292 | 1293 | |
| 1293 | - if (m->xref_table.deleted_objects.count(obj)) { | |
| 1294 | + if (deleted_objects.count(obj)) { | |
| 1294 | 1295 | QTC::TC("qpdf", "QPDF xref deleted object"); |
| 1295 | 1296 | return; |
| 1296 | 1297 | } |
| 1297 | 1298 | |
| 1298 | 1299 | if (f0 == 2 && static_cast<int>(f1) == obj) { |
| 1299 | - warn(damagedPDF("xref stream", "self-referential object stream " + std::to_string(obj))); | |
| 1300 | + qpdf.warn(qpdf.damagedPDF( | |
| 1301 | + "xref stream", "self-referential object stream " + std::to_string(obj))); | |
| 1300 | 1302 | return; |
| 1301 | 1303 | } |
| 1302 | 1304 | |
| 1303 | - auto [iter, created] = m->xref_table.try_emplace(QPDFObjGen(obj, (f0 == 2 ? 0 : f2))); | |
| 1305 | + auto [iter, created] = try_emplace(QPDFObjGen(obj, (f0 == 2 ? 0 : f2))); | |
| 1304 | 1306 | if (!created) { |
| 1305 | 1307 | QTC::TC("qpdf", "QPDF xref reused object"); |
| 1306 | 1308 | return; |
| ... | ... | @@ -1318,35 +1320,36 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2) |
| 1318 | 1320 | break; |
| 1319 | 1321 | |
| 1320 | 1322 | default: |
| 1321 | - throw damagedPDF("xref stream", "unknown xref stream entry type " + std::to_string(f0)); | |
| 1323 | + throw qpdf.damagedPDF( | |
| 1324 | + "xref stream", "unknown xref stream entry type " + std::to_string(f0)); | |
| 1322 | 1325 | break; |
| 1323 | 1326 | } |
| 1324 | 1327 | } |
| 1325 | 1328 | |
| 1326 | 1329 | void |
| 1327 | -QPDF::insertFreeXrefEntry(QPDFObjGen og) | |
| 1330 | +QPDF::Xref_table::insert_free(QPDFObjGen og) | |
| 1328 | 1331 | { |
| 1329 | - if (!m->xref_table.count(og)) { | |
| 1330 | - m->xref_table.deleted_objects.insert(og.getObj()); | |
| 1332 | + if (!count(og)) { | |
| 1333 | + deleted_objects.insert(og.getObj()); | |
| 1331 | 1334 | } |
| 1332 | 1335 | } |
| 1333 | 1336 | |
| 1334 | 1337 | // Replace uncompressed object. This is used in xref recovery mode, which reads the file from |
| 1335 | 1338 | // beginning to end. |
| 1336 | 1339 | void |
| 1337 | -QPDF::insertReconstructedXrefEntry(int obj, qpdf_offset_t f1, int f2) | |
| 1340 | +QPDF::Xref_table::insert_reconstructed(int obj, qpdf_offset_t f1, int f2) | |
| 1338 | 1341 | { |
| 1339 | - if (!(obj > 0 && obj <= m->xref_table.max_id && 0 <= f2 && f2 < 65535)) { | |
| 1342 | + if (!(obj > 0 && obj <= max_id && 0 <= f2 && f2 < 65535)) { | |
| 1340 | 1343 | QTC::TC("qpdf", "QPDF xref overwrite invalid objgen"); |
| 1341 | 1344 | return; |
| 1342 | 1345 | } |
| 1343 | 1346 | |
| 1344 | 1347 | QPDFObjGen og(obj, f2); |
| 1345 | - if (!m->xref_table.deleted_objects.count(obj)) { | |
| 1348 | + if (!deleted_objects.count(obj)) { | |
| 1346 | 1349 | // deleted_objects stores the uncompressed objects removed from the xref table at the start |
| 1347 | 1350 | // of recovery. |
| 1348 | 1351 | QTC::TC("qpdf", "QPDF xref overwrite object"); |
| 1349 | - m->xref_table[QPDFObjGen(obj, f2)] = QPDFXRefEntry(f1); | |
| 1352 | + insert_or_assign(QPDFObjGen(obj, f2), QPDFXRefEntry(f1)); | |
| 1350 | 1353 | } |
| 1351 | 1354 | } |
| 1352 | 1355 | ... | ... |
libqpdf/qpdf/QPDF_private.hh
| ... | ... | @@ -7,6 +7,15 @@ |
| 7 | 7 | class QPDF::Xref_table: public std::map<QPDFObjGen, QPDFXRefEntry> |
| 8 | 8 | { |
| 9 | 9 | public: |
| 10 | + Xref_table(QPDF& qpdf) : | |
| 11 | + qpdf(qpdf) | |
| 12 | + { | |
| 13 | + } | |
| 14 | + | |
| 15 | + void insert_reconstructed(int obj, qpdf_offset_t f1, int f2); | |
| 16 | + void insert(int obj, int f0, qpdf_offset_t f1, int f2); | |
| 17 | + void insert_free(QPDFObjGen); | |
| 18 | + | |
| 10 | 19 | QPDFObjectHandle trailer; |
| 11 | 20 | bool reconstructed{false}; |
| 12 | 21 | // Various tables are indexed by object id, with potential size id + 1 |
| ... | ... | @@ -20,6 +29,9 @@ class QPDF::Xref_table: public std::map<QPDFObjGen, QPDFXRefEntry> |
| 20 | 29 | // Linearization data |
| 21 | 30 | bool uncompressed_after_compressed{false}; |
| 22 | 31 | qpdf_offset_t first_item_offset{0}; // actual value from file |
| 32 | + | |
| 33 | + private: | |
| 34 | + QPDF& qpdf; | |
| 23 | 35 | }; |
| 24 | 36 | |
| 25 | 37 | // Writer class is restricted to QPDFWriter so that only it can call certain methods. |
| ... | ... | @@ -469,7 +481,7 @@ class QPDF::Members |
| 469 | 481 | ~Members() = default; |
| 470 | 482 | |
| 471 | 483 | private: |
| 472 | - Members(); | |
| 484 | + Members(QPDF& qpdf); | |
| 473 | 485 | Members(Members const&) = delete; |
| 474 | 486 | |
| 475 | 487 | std::shared_ptr<QPDFLogger> log; | ... | ... |