Commit 8e6974710cc75b3acfb592db9fb6fd8611c39732
1 parent
250a7364
Add private method QPDF::insertFreeXrefEntry
Showing
2 changed files
with
21 additions
and
14 deletions
include/qpdf/QPDF.hh
| @@ -1003,6 +1003,7 @@ class QPDF | @@ -1003,6 +1003,7 @@ class QPDF | ||
| 1003 | qpdf_offset_t read_xrefStream(qpdf_offset_t offset); | 1003 | qpdf_offset_t read_xrefStream(qpdf_offset_t offset); |
| 1004 | qpdf_offset_t processXRefStream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream); | 1004 | qpdf_offset_t processXRefStream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream); |
| 1005 | void insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2); | 1005 | void insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2); |
| 1006 | + void insertFreeXrefEntry(QPDFObjGen); | ||
| 1006 | void insertReconstructedXrefEntry(int obj, qpdf_offset_t f1, int f2); | 1007 | void insertReconstructedXrefEntry(int obj, qpdf_offset_t f1, int f2); |
| 1007 | void setLastObjectDescription(std::string const& description, QPDFObjGen const& og); | 1008 | void setLastObjectDescription(std::string const& description, QPDFObjGen const& og); |
| 1008 | QPDFObjectHandle readObject( | 1009 | QPDFObjectHandle readObject( |
libqpdf/QPDF.cc
| @@ -890,7 +890,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) | @@ -890,7 +890,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) | ||
| 890 | 890 | ||
| 891 | // Handle any deleted items now that we've read the /XRefStm. | 891 | // Handle any deleted items now that we've read the /XRefStm. |
| 892 | for (auto const& og: deleted_items) { | 892 | for (auto const& og: deleted_items) { |
| 893 | - insertXrefEntry(og.getObj(), 0, 0, og.getGen()); | 893 | + insertFreeXrefEntry(og); |
| 894 | } | 894 | } |
| 895 | 895 | ||
| 896 | if (cur_trailer.hasKey("/Prev")) { | 896 | if (cur_trailer.hasKey("/Prev")) { |
| @@ -1088,9 +1088,10 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) | @@ -1088,9 +1088,10 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) | ||
| 1088 | if (fields[0] == 0) { | 1088 | if (fields[0] == 0) { |
| 1089 | // Ignore fields[2], which we don't care about in this case. This works around the issue | 1089 | // Ignore fields[2], which we don't care about in this case. This works around the issue |
| 1090 | // of some PDF files that put invalid values, like -1, here for deleted objects. | 1090 | // of some PDF files that put invalid values, like -1, here for deleted objects. |
| 1091 | - fields[2] = 0; | 1091 | + insertFreeXrefEntry(QPDFObjGen(obj, 0)); |
| 1092 | + } else { | ||
| 1093 | + insertXrefEntry(obj, toI(fields[0]), fields[1], toI(fields[2])); | ||
| 1092 | } | 1094 | } |
| 1093 | - insertXrefEntry(obj, toI(fields[0]), fields[1], toI(fields[2])); | ||
| 1094 | } | 1095 | } |
| 1095 | 1096 | ||
| 1096 | if (!m->trailer.isInitialized()) { | 1097 | if (!m->trailer.isInitialized()) { |
| @@ -1121,29 +1122,26 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2) | @@ -1121,29 +1122,26 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2) | ||
| 1121 | // If there is already an entry for this object and generation in the table, it means that a | 1122 | // If there is already an entry for this object and generation in the table, it means that a |
| 1122 | // later xref table has registered this object. Disregard this one. | 1123 | // later xref table has registered this object. Disregard this one. |
| 1123 | 1124 | ||
| 1124 | - QPDFObjGen og(obj, (f0 == 2 ? 0 : f2)); | ||
| 1125 | - if (m->xref_table.count(og)) { | ||
| 1126 | - QTC::TC("qpdf", "QPDF xref reused object"); | ||
| 1127 | - return; | ||
| 1128 | - } | ||
| 1129 | if (m->deleted_objects.count(obj)) { | 1125 | if (m->deleted_objects.count(obj)) { |
| 1130 | QTC::TC("qpdf", "QPDF xref deleted object"); | 1126 | QTC::TC("qpdf", "QPDF xref deleted object"); |
| 1131 | return; | 1127 | return; |
| 1132 | } | 1128 | } |
| 1133 | 1129 | ||
| 1134 | - switch (f0) { | ||
| 1135 | - case 0: | ||
| 1136 | - m->deleted_objects.insert(obj); | ||
| 1137 | - break; | 1130 | + auto [iter, created] = m->xref_table.try_emplace(QPDFObjGen(obj, (f0 == 2 ? 0 : f2))); |
| 1131 | + if (!created) { | ||
| 1132 | + QTC::TC("qpdf", "QPDF xref reused object"); | ||
| 1133 | + return; | ||
| 1134 | + } | ||
| 1138 | 1135 | ||
| 1136 | + switch (f0) { | ||
| 1139 | case 1: | 1137 | case 1: |
| 1140 | // f2 is generation | 1138 | // f2 is generation |
| 1141 | QTC::TC("qpdf", "QPDF xref gen > 0", ((f2 > 0) ? 1 : 0)); | 1139 | QTC::TC("qpdf", "QPDF xref gen > 0", ((f2 > 0) ? 1 : 0)); |
| 1142 | - m->xref_table[og] = QPDFXRefEntry(f1); | 1140 | + iter->second = QPDFXRefEntry(f1); |
| 1143 | break; | 1141 | break; |
| 1144 | 1142 | ||
| 1145 | case 2: | 1143 | case 2: |
| 1146 | - m->xref_table[og] = QPDFXRefEntry(toI(f1), f2); | 1144 | + iter->second = QPDFXRefEntry(toI(f1), f2); |
| 1147 | break; | 1145 | break; |
| 1148 | 1146 | ||
| 1149 | default: | 1147 | default: |
| @@ -1152,6 +1150,14 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2) | @@ -1152,6 +1150,14 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2) | ||
| 1152 | } | 1150 | } |
| 1153 | } | 1151 | } |
| 1154 | 1152 | ||
| 1153 | +void | ||
| 1154 | +QPDF::insertFreeXrefEntry(QPDFObjGen og) | ||
| 1155 | +{ | ||
| 1156 | + if (!m->xref_table.count(og)) { | ||
| 1157 | + m->deleted_objects.insert(og.getObj()); | ||
| 1158 | + } | ||
| 1159 | +} | ||
| 1160 | + | ||
| 1155 | // Replace uncompressed object. This is used in xref recovery mode, which reads the file from | 1161 | // Replace uncompressed object. This is used in xref recovery mode, which reads the file from |
| 1156 | // beginning to end. | 1162 | // beginning to end. |
| 1157 | void | 1163 | void |