Commit f2228b1f88dfed31b5b16026984db69f605f84dc

Authored by m-holger
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,8 +952,6 @@ QPDF::read_xrefEntry(qpdf_offset_t& f1, int& f2, char& type)
952 qpdf_offset_t 952 qpdf_offset_t
953 QPDF::read_xrefTable(qpdf_offset_t xref_offset) 953 QPDF::read_xrefTable(qpdf_offset_t xref_offset)
954 { 954 {
955 - std::vector<QPDFObjGen> deleted_items;  
956 -  
957 m->file->seek(xref_offset, SEEK_SET); 955 m->file->seek(xref_offset, SEEK_SET);
958 std::string line; 956 std::string line;
959 while (true) { 957 while (true) {
@@ -982,8 +980,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) @@ -982,8 +980,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
982 "xref table", "invalid xref entry (obj=" + std::to_string(i) + ")"); 980 "xref table", "invalid xref entry (obj=" + std::to_string(i) + ")");
983 } 981 }
984 if (type == 'f') { 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 } else { 984 } else {
988 insertXrefEntry(toI(i), 1, f1, f2); 985 insertXrefEntry(toI(i), 1, f1, f2);
989 } 986 }
@@ -1030,23 +1027,16 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) @@ -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 if (cur_trailer.hasKey("/Prev")) { 1030 if (cur_trailer.hasKey("/Prev")) {
1039 if (!cur_trailer.getKey("/Prev").isInteger()) { 1031 if (!cur_trailer.getKey("/Prev").isInteger()) {
1040 QTC::TC("qpdf", "QPDF trailer prev not integer"); 1032 QTC::TC("qpdf", "QPDF trailer prev not integer");
1041 throw damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer"); 1033 throw damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer");
1042 } 1034 }
1043 QTC::TC("qpdf", "QPDF prev key in trailer dictionary"); 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 // Read a single cross-reference stream. 1042 // Read a single cross-reference stream.