Commit f2228b1f88dfed31b5b16026984db69f605f84dc
1 parent
dc1ae845
Fix handling of hybrid reference files in QPDF::read_xrefTable
QPDF::read_xrefTable ignores type 0 entries for objects in a section if an associates XRefStm has an entry for the same object. The spec states: When the conforming reader searches for an object, if an entry is not found in any given standard cross-reference section, the search shall proceed to a cross-reference stream specified by the XRefStm entry before looking in the previous cross-reference section, If a deleted entry is found in a section, the XRefStm is not searched according to the standard.
Showing
1 changed file
with
3 additions
and
13 deletions
libqpdf/QPDF.cc
| ... | ... | @@ -952,8 +952,6 @@ QPDF::read_xrefEntry(qpdf_offset_t& f1, int& f2, char& type) |
| 952 | 952 | qpdf_offset_t |
| 953 | 953 | QPDF::read_xrefTable(qpdf_offset_t xref_offset) |
| 954 | 954 | { |
| 955 | - std::vector<QPDFObjGen> deleted_items; | |
| 956 | - | |
| 957 | 955 | m->file->seek(xref_offset, SEEK_SET); |
| 958 | 956 | std::string line; |
| 959 | 957 | while (true) { |
| ... | ... | @@ -982,8 +980,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) |
| 982 | 980 | "xref table", "invalid xref entry (obj=" + std::to_string(i) + ")"); |
| 983 | 981 | } |
| 984 | 982 | if (type == 'f') { |
| 985 | - // Save deleted items until after we've checked the XRefStm, if any. | |
| 986 | - deleted_items.emplace_back(toI(i), f2); | |
| 983 | + insertFreeXrefEntry(QPDFObjGen(toI(i), f2)); | |
| 987 | 984 | } else { |
| 988 | 985 | insertXrefEntry(toI(i), 1, f1, f2); |
| 989 | 986 | } |
| ... | ... | @@ -1030,23 +1027,16 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) |
| 1030 | 1027 | } |
| 1031 | 1028 | } |
| 1032 | 1029 | |
| 1033 | - // Handle any deleted items now that we've read the /XRefStm. | |
| 1034 | - for (auto const& og: deleted_items) { | |
| 1035 | - insertFreeXrefEntry(og); | |
| 1036 | - } | |
| 1037 | - | |
| 1038 | 1030 | if (cur_trailer.hasKey("/Prev")) { |
| 1039 | 1031 | if (!cur_trailer.getKey("/Prev").isInteger()) { |
| 1040 | 1032 | QTC::TC("qpdf", "QPDF trailer prev not integer"); |
| 1041 | 1033 | throw damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer"); |
| 1042 | 1034 | } |
| 1043 | 1035 | QTC::TC("qpdf", "QPDF prev key in trailer dictionary"); |
| 1044 | - xref_offset = cur_trailer.getKey("/Prev").getIntValue(); | |
| 1045 | - } else { | |
| 1046 | - xref_offset = 0; | |
| 1036 | + return cur_trailer.getKey("/Prev").getIntValue(); | |
| 1047 | 1037 | } |
| 1048 | 1038 | |
| 1049 | - return xref_offset; | |
| 1039 | + return 0; | |
| 1050 | 1040 | } |
| 1051 | 1041 | |
| 1052 | 1042 | // Read a single cross-reference stream. | ... | ... |