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