Commit f30a5eb05a8fe763184cd8167a4d4531909a34d5

Authored by m-holger
1 parent 253d3aee

Move QPDF::read_xrefStream to QPDF::Xref_table

include/qpdf/QPDF.hh
@@ -759,19 +759,8 @@ class QPDF @@ -759,19 +759,8 @@ class QPDF
759 759
760 void parse(char const* password); 760 void parse(char const* password);
761 void inParse(bool); 761 void inParse(bool);
762 - void setTrailer(QPDFObjectHandle obj);  
763 void read_xref(qpdf_offset_t offset); 762 void read_xref(qpdf_offset_t offset);
764 bool resolveXRefTable(); 763 bool resolveXRefTable();
765 - qpdf_offset_t read_xrefStream(qpdf_offset_t offset);  
766 - qpdf_offset_t processXRefStream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream);  
767 - std::pair<int, std::array<int, 3>>  
768 - processXRefW(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged);  
769 - int processXRefSize(  
770 - QPDFObjectHandle& dict, int entry_size, std::function<QPDFExc(std::string_view)> damaged);  
771 - std::pair<int, std::vector<std::pair<int, int>>> processXRefIndex(  
772 - QPDFObjectHandle& dict,  
773 - int max_num_entries,  
774 - std::function<QPDFExc(std::string_view)> damaged);  
775 void setLastObjectDescription(std::string const& description, QPDFObjGen const& og); 764 void setLastObjectDescription(std::string const& description, QPDFObjGen const& og);
776 QPDFObjectHandle readTrailer(); 765 QPDFObjectHandle readTrailer();
777 QPDFObjectHandle readObject(std::string const& description, QPDFObjGen og); 766 QPDFObjectHandle readObject(std::string const& description, QPDFObjGen og);
libqpdf/QPDF.cc
@@ -526,15 +526,6 @@ QPDF::warn( @@ -526,15 +526,6 @@ QPDF::warn(
526 } 526 }
527 527
528 void 528 void
529 -QPDF::setTrailer(QPDFObjectHandle obj)  
530 -{  
531 - if (m->xref_table.trailer) {  
532 - return;  
533 - }  
534 - m->xref_table.trailer = obj;  
535 -}  
536 -  
537 -void  
538 QPDF::Xref_table::reconstruct(QPDFExc& e) 529 QPDF::Xref_table::reconstruct(QPDFExc& e)
539 { 530 {
540 if (reconstructed) { 531 if (reconstructed) {
@@ -600,7 +591,7 @@ QPDF::Xref_table::reconstruct(QPDFExc&amp; e) @@ -600,7 +591,7 @@ QPDF::Xref_table::reconstruct(QPDFExc&amp; e)
600 if (!t.isDictionary()) { 591 if (!t.isDictionary()) {
601 // Oh well. It was worth a try. 592 // Oh well. It was worth a try.
602 } else { 593 } else {
603 - qpdf.setTrailer(t); 594 + trailer = t;
604 } 595 }
605 m->file->seek(pos, SEEK_SET); 596 m->file->seek(pos, SEEK_SET);
606 } 597 }
@@ -725,7 +716,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset) @@ -725,7 +716,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
725 } 716 }
726 xref_offset = m->xref_table.read_table(xref_offset + skip); 717 xref_offset = m->xref_table.read_table(xref_offset + skip);
727 } else { 718 } else {
728 - xref_offset = read_xrefStream(xref_offset); 719 + xref_offset = m->xref_table.read_stream(xref_offset);
729 } 720 }
730 if (visited.count(xref_offset) != 0) { 721 if (visited.count(xref_offset) != 0) {
731 QTC::TC("qpdf", "QPDF xref loop"); 722 QTC::TC("qpdf", "QPDF xref loop");
@@ -1028,7 +1019,7 @@ QPDF::Xref_table::read_table(qpdf_offset_t xref_offset) @@ -1028,7 +1019,7 @@ QPDF::Xref_table::read_table(qpdf_offset_t xref_offset)
1028 if (cur_trailer.getKey("/XRefStm").isInteger()) { 1019 if (cur_trailer.getKey("/XRefStm").isInteger()) {
1029 // Read the xref stream but disregard any return value -- we'll use our trailer's 1020 // Read the xref stream but disregard any return value -- we'll use our trailer's
1030 // /Prev key instead of the xref stream's. 1021 // /Prev key instead of the xref stream's.
1031 - (void)qpdf.read_xrefStream(cur_trailer.getKey("/XRefStm").getIntValue()); 1022 + (void)read_stream(cur_trailer.getKey("/XRefStm").getIntValue());
1032 } else { 1023 } else {
1033 throw qpdf.damagedPDF("xref stream", xref_offset, "invalid /XRefStm"); 1024 throw qpdf.damagedPDF("xref stream", xref_offset, "invalid /XRefStm");
1034 } 1025 }
@@ -1049,34 +1040,35 @@ QPDF::Xref_table::read_table(qpdf_offset_t xref_offset) @@ -1049,34 +1040,35 @@ QPDF::Xref_table::read_table(qpdf_offset_t xref_offset)
1049 1040
1050 // Read a single cross-reference stream. 1041 // Read a single cross-reference stream.
1051 qpdf_offset_t 1042 qpdf_offset_t
1052 -QPDF::read_xrefStream(qpdf_offset_t xref_offset) 1043 +QPDF::Xref_table::read_stream(qpdf_offset_t xref_offset)
1053 { 1044 {
1054 - if (!m->xref_table.ignore_streams) { 1045 + if (!ignore_streams) {
1055 QPDFObjGen x_og; 1046 QPDFObjGen x_og;
1056 QPDFObjectHandle xref_obj; 1047 QPDFObjectHandle xref_obj;
1057 try { 1048 try {
1058 - xref_obj =  
1059 - readObjectAtOffset(false, xref_offset, "xref stream", QPDFObjGen(0, 0), x_og, true); 1049 + xref_obj = qpdf.readObjectAtOffset(
  1050 + false, xref_offset, "xref stream", QPDFObjGen(0, 0), x_og, true);
1060 } catch (QPDFExc&) { 1051 } catch (QPDFExc&) {
1061 // ignore -- report error below 1052 // ignore -- report error below
1062 } 1053 }
1063 if (xref_obj.isStreamOfType("/XRef")) { 1054 if (xref_obj.isStreamOfType("/XRef")) {
1064 QTC::TC("qpdf", "QPDF found xref stream"); 1055 QTC::TC("qpdf", "QPDF found xref stream");
1065 - return processXRefStream(xref_offset, xref_obj); 1056 + return process_stream(xref_offset, xref_obj);
1066 } 1057 }
1067 } 1058 }
1068 1059
1069 QTC::TC("qpdf", "QPDF can't find xref"); 1060 QTC::TC("qpdf", "QPDF can't find xref");
1070 - throw damagedPDF("", xref_offset, "xref not found"); 1061 + throw qpdf.damagedPDF("", xref_offset, "xref not found");
1071 return 0; // unreachable 1062 return 0; // unreachable
1072 } 1063 }
1073 1064
1074 // Return the entry size of the xref stream and the processed W array. 1065 // Return the entry size of the xref stream and the processed W array.
1075 std::pair<int, std::array<int, 3>> 1066 std::pair<int, std::array<int, 3>>
1076 -QPDF::processXRefW(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged) 1067 +QPDF::Xref_table::process_W(
  1068 + QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged)
1077 { 1069 {
1078 auto W_obj = dict.getKey("/W"); 1070 auto W_obj = dict.getKey("/W");
1079 - if (!(W_obj.isArray() && (W_obj.getArrayNItems() >= 3) && W_obj.getArrayItem(0).isInteger() && 1071 + if (!(W_obj.isArray() && W_obj.getArrayNItems() >= 3 && W_obj.getArrayItem(0).isInteger() &&
1080 W_obj.getArrayItem(1).isInteger() && W_obj.getArrayItem(2).isInteger())) { 1072 W_obj.getArrayItem(1).isInteger() && W_obj.getArrayItem(2).isInteger())) {
1081 throw damaged("Cross-reference stream does not have a proper /W key"); 1073 throw damaged("Cross-reference stream does not have a proper /W key");
1082 } 1074 }
@@ -1103,7 +1095,7 @@ QPDF::processXRefW(QPDFObjectHandle&amp; dict, std::function&lt;QPDFExc(std::string_vie @@ -1103,7 +1095,7 @@ QPDF::processXRefW(QPDFObjectHandle&amp; dict, std::function&lt;QPDFExc(std::string_vie
1103 1095
1104 // Validate Size key and return the maximum number of entries that the xref stream can contain. 1096 // Validate Size key and return the maximum number of entries that the xref stream can contain.
1105 int 1097 int
1106 -QPDF::processXRefSize( 1098 +QPDF::Xref_table::process_Size(
1107 QPDFObjectHandle& dict, int entry_size, std::function<QPDFExc(std::string_view)> damaged) 1099 QPDFObjectHandle& dict, int entry_size, std::function<QPDFExc(std::string_view)> damaged)
1108 { 1100 {
1109 // Number of entries is limited by the highest possible object id and stream size. 1101 // Number of entries is limited by the highest possible object id and stream size.
@@ -1127,7 +1119,7 @@ QPDF::processXRefSize( @@ -1127,7 +1119,7 @@ QPDF::processXRefSize(
1127 1119
1128 // Return the number of entries of the xref stream and the processed Index array. 1120 // Return the number of entries of the xref stream and the processed Index array.
1129 std::pair<int, std::vector<std::pair<int, int>>> 1121 std::pair<int, std::vector<std::pair<int, int>>>
1130 -QPDF::processXRefIndex( 1122 +QPDF::Xref_table::process_Index(
1131 QPDFObjectHandle& dict, int max_num_entries, std::function<QPDFExc(std::string_view)> damaged) 1123 QPDFObjectHandle& dict, int max_num_entries, std::function<QPDFExc(std::string_view)> damaged)
1132 { 1124 {
1133 auto size = dict.getKey("/Size").getIntValueAsInt(); 1125 auto size = dict.getKey("/Size").getIntValueAsInt();
@@ -1194,17 +1186,17 @@ QPDF::processXRefIndex( @@ -1194,17 +1186,17 @@ QPDF::processXRefIndex(
1194 } 1186 }
1195 1187
1196 qpdf_offset_t 1188 qpdf_offset_t
1197 -QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) 1189 +QPDF::Xref_table::process_stream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
1198 { 1190 {
1199 auto damaged = [this, xref_offset](std::string_view msg) -> QPDFExc { 1191 auto damaged = [this, xref_offset](std::string_view msg) -> QPDFExc {
1200 - return damagedPDF("xref stream", xref_offset, msg.data()); 1192 + return qpdf.damagedPDF("xref stream", xref_offset, msg.data());
1201 }; 1193 };
1202 1194
1203 auto dict = xref_obj.getDict(); 1195 auto dict = xref_obj.getDict();
1204 1196
1205 - auto [entry_size, W] = processXRefW(dict, damaged);  
1206 - int max_num_entries = processXRefSize(dict, entry_size, damaged);  
1207 - auto [num_entries, indx] = processXRefIndex(dict, max_num_entries, damaged); 1197 + auto [entry_size, W] = process_W(dict, damaged);
  1198 + int max_num_entries = process_Size(dict, entry_size, damaged);
  1199 + auto [num_entries, indx] = process_Index(dict, max_num_entries, damaged);
1208 1200
1209 std::shared_ptr<Buffer> bp = xref_obj.getStreamData(qpdf_dl_specialized); 1201 std::shared_ptr<Buffer> bp = xref_obj.getStreamData(qpdf_dl_specialized);
1210 size_t actual_size = bp->getSize(); 1202 size_t actual_size = bp->getSize();
@@ -1217,7 +1209,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj) @@ -1217,7 +1209,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
1217 if (expected_size > actual_size) { 1209 if (expected_size > actual_size) {
1218 throw x; 1210 throw x;
1219 } else { 1211 } else {
1220 - warn(x); 1212 + qpdf.warn(x);
1221 } 1213 }
1222 } 1214 }
1223 1215
@@ -1246,33 +1238,33 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj) @@ -1246,33 +1238,33 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
1246 // object record, in which case the generation number appears as the third field. 1238 // object record, in which case the generation number appears as the third field.
1247 if (saw_first_compressed_object) { 1239 if (saw_first_compressed_object) {
1248 if (fields[0] != 2) { 1240 if (fields[0] != 2) {
1249 - m->xref_table.uncompressed_after_compressed = true; 1241 + uncompressed_after_compressed = true;
1250 } 1242 }
1251 } else if (fields[0] == 2) { 1243 } else if (fields[0] == 2) {
1252 saw_first_compressed_object = true; 1244 saw_first_compressed_object = true;
1253 } 1245 }
1254 if (obj == 0) { 1246 if (obj == 0) {
1255 // This is needed by checkLinearization() 1247 // This is needed by checkLinearization()
1256 - m->xref_table.first_item_offset = xref_offset; 1248 + first_item_offset = xref_offset;
1257 } else if (fields[0] == 0) { 1249 } else if (fields[0] == 0) {
1258 // Ignore fields[2], which we don't care about in this case. This works around the 1250 // Ignore fields[2], which we don't care about in this case. This works around the
1259 // issue of some PDF files that put invalid values, like -1, here for deleted 1251 // issue of some PDF files that put invalid values, like -1, here for deleted
1260 // objects. 1252 // objects.
1261 - m->xref_table.insert_free(QPDFObjGen(obj, 0)); 1253 + insert_free(QPDFObjGen(obj, 0));
1262 } else { 1254 } else {
1263 - m->xref_table.insert(obj, toI(fields[0]), fields[1], toI(fields[2])); 1255 + insert(obj, toI(fields[0]), fields[1], toI(fields[2]));
1264 } 1256 }
1265 ++obj; 1257 ++obj;
1266 } 1258 }
1267 } 1259 }
1268 1260
1269 - if (!m->xref_table.trailer) {  
1270 - setTrailer(dict); 1261 + if (!trailer) {
  1262 + trailer = dict;
1271 } 1263 }
1272 1264
1273 if (dict.hasKey("/Prev")) { 1265 if (dict.hasKey("/Prev")) {
1274 if (!dict.getKey("/Prev").isInteger()) { 1266 if (!dict.getKey("/Prev").isInteger()) {
1275 - throw damagedPDF( 1267 + throw qpdf.damagedPDF(
1276 "xref stream", "/Prev key in xref stream dictionary is not an integer"); 1268 "xref stream", "/Prev key in xref stream dictionary is not an integer");
1277 } 1269 }
1278 QTC::TC("qpdf", "QPDF prev key in xref stream dictionary"); 1270 QTC::TC("qpdf", "QPDF prev key in xref stream dictionary");
@@ -1378,8 +1370,7 @@ QPDF::showXRefTable() @@ -1378,8 +1370,7 @@ QPDF::showXRefTable()
1378 break; 1370 break;
1379 1371
1380 default: 1372 default:
1381 - throw std::logic_error("unknown cross-reference table type while"  
1382 - " showing xref_table"); 1373 + throw std::logic_error("unknown cross-reference table type while showing xref_table");
1383 break; 1374 break;
1384 } 1375 }
1385 m->log->info("\n"); 1376 m->log->info("\n");
libqpdf/qpdf/QPDF_private.hh
@@ -13,10 +13,7 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt; @@ -13,10 +13,7 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt;
13 } 13 }
14 14
15 qpdf_offset_t read_table(qpdf_offset_t offset); 15 qpdf_offset_t read_table(qpdf_offset_t offset);
16 -  
17 - void insert_reconstructed(int obj, qpdf_offset_t f1, int f2);  
18 - void insert(int obj, int f0, qpdf_offset_t f1, int f2);  
19 - void insert_free(QPDFObjGen); 16 + qpdf_offset_t read_stream(qpdf_offset_t offset);
20 17
21 void reconstruct(QPDFExc& e); 18 void reconstruct(QPDFExc& e);
22 19
@@ -38,6 +35,19 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt; @@ -38,6 +35,19 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt;
38 bool parse_first(std::string const& line, int& obj, int& num, int& bytes); 35 bool parse_first(std::string const& line, int& obj, int& num, int& bytes);
39 bool read_entry(qpdf_offset_t& f1, int& f2, char& type); 36 bool read_entry(qpdf_offset_t& f1, int& f2, char& type);
40 bool read_bad_entry(qpdf_offset_t& f1, int& f2, char& type); 37 bool read_bad_entry(qpdf_offset_t& f1, int& f2, char& type);
  38 + qpdf_offset_t process_stream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream);
  39 + std::pair<int, std::array<int, 3>>
  40 + process_W(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged);
  41 + int process_Size(
  42 + QPDFObjectHandle& dict, int entry_size, std::function<QPDFExc(std::string_view)> damaged);
  43 + std::pair<int, std::vector<std::pair<int, int>>> process_Index(
  44 + QPDFObjectHandle& dict,
  45 + int max_num_entries,
  46 + std::function<QPDFExc(std::string_view)> damaged);
  47 +
  48 + void insert_reconstructed(int obj, qpdf_offset_t f1, int f2);
  49 + void insert(int obj, int f0, qpdf_offset_t f1, int f2);
  50 + void insert_free(QPDFObjGen);
41 51
42 QPDFExc 52 QPDFExc
43 damaged_pdf(std::string const& msg) 53 damaged_pdf(std::string const& msg)