Commit 253d3aee8fb231a777cae127af52c262dcdeb9a6

Authored by m-holger
1 parent 3fbff845

Move QPDF::read_xrefEntry to QPDF::Xref_table

include/qpdf/QPDF.hh
@@ -762,10 +762,6 @@ class QPDF @@ -762,10 +762,6 @@ class QPDF
762 void setTrailer(QPDFObjectHandle obj); 762 void setTrailer(QPDFObjectHandle obj);
763 void read_xref(qpdf_offset_t offset); 763 void read_xref(qpdf_offset_t offset);
764 bool resolveXRefTable(); 764 bool resolveXRefTable();
765 - bool parse_xrefFirst(std::string const& line, int& obj, int& num, int& bytes);  
766 - bool read_xrefEntry(qpdf_offset_t& f1, int& f2, char& type);  
767 - bool read_bad_xrefEntry(qpdf_offset_t& f1, int& f2, char& type);  
768 - qpdf_offset_t read_xrefTable(qpdf_offset_t offset);  
769 qpdf_offset_t read_xrefStream(qpdf_offset_t offset); 765 qpdf_offset_t read_xrefStream(qpdf_offset_t offset);
770 qpdf_offset_t processXRefStream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream); 766 qpdf_offset_t processXRefStream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream);
771 std::pair<int, std::array<int, 3>> 767 std::pair<int, std::array<int, 3>>
libqpdf/QPDF.cc
@@ -723,7 +723,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset) @@ -723,7 +723,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
723 while (QUtil::is_space(buf[skip])) { 723 while (QUtil::is_space(buf[skip])) {
724 ++skip; 724 ++skip;
725 } 725 }
726 - xref_offset = read_xrefTable(xref_offset + skip); 726 + xref_offset = m->xref_table.read_table(xref_offset + skip);
727 } else { 727 } else {
728 xref_offset = read_xrefStream(xref_offset); 728 xref_offset = read_xrefStream(xref_offset);
729 } 729 }
@@ -769,7 +769,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset) @@ -769,7 +769,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
769 } 769 }
770 770
771 bool 771 bool
772 -QPDF::parse_xrefFirst(std::string const& line, int& obj, int& num, int& bytes) 772 +QPDF::Xref_table::parse_first(std::string const& line, int& obj, int& num, int& bytes)
773 { 773 {
774 // is_space and is_digit both return false on '\0', so this will not overrun the null-terminated 774 // is_space and is_digit both return false on '\0', so this will not overrun the null-terminated
775 // buffer. 775 // buffer.
@@ -817,8 +817,10 @@ QPDF::parse_xrefFirst(std::string const&amp; line, int&amp; obj, int&amp; num, int&amp; bytes) @@ -817,8 +817,10 @@ QPDF::parse_xrefFirst(std::string const&amp; line, int&amp; obj, int&amp; num, int&amp; bytes)
817 } 817 }
818 818
819 bool 819 bool
820 -QPDF::read_bad_xrefEntry(qpdf_offset_t& f1, int& f2, char& type) 820 +QPDF::Xref_table::read_bad_entry(qpdf_offset_t& f1, int& f2, char& type)
821 { 821 {
  822 + auto* m = qpdf.m.get();
  823 +
822 // Reposition after initial read attempt and reread. 824 // Reposition after initial read attempt and reread.
823 m->file->seek(m->file->getLastOffset(), SEEK_SET); 825 m->file->seek(m->file->getLastOffset(), SEEK_SET);
824 auto line = m->file->readLine(30); 826 auto line = m->file->readLine(30);
@@ -887,7 +889,7 @@ QPDF::read_bad_xrefEntry(qpdf_offset_t&amp; f1, int&amp; f2, char&amp; type) @@ -887,7 +889,7 @@ QPDF::read_bad_xrefEntry(qpdf_offset_t&amp; f1, int&amp; f2, char&amp; type)
887 } 889 }
888 890
889 if (invalid) { 891 if (invalid) {
890 - warn(damagedPDF("xref table", "accepting invalid xref table entry")); 892 + qpdf.warn(damaged_table("accepting invalid xref table entry"));
891 } 893 }
892 894
893 f1 = QUtil::string_to_ll(f1_str.c_str()); 895 f1 = QUtil::string_to_ll(f1_str.c_str());
@@ -899,8 +901,10 @@ QPDF::read_bad_xrefEntry(qpdf_offset_t&amp; f1, int&amp; f2, char&amp; type) @@ -899,8 +901,10 @@ QPDF::read_bad_xrefEntry(qpdf_offset_t&amp; f1, int&amp; f2, char&amp; type)
899 // Optimistically read and parse xref entry. If entry is bad, call read_bad_xrefEntry and return 901 // Optimistically read and parse xref entry. If entry is bad, call read_bad_xrefEntry and return
900 // result. 902 // result.
901 bool 903 bool
902 -QPDF::read_xrefEntry(qpdf_offset_t& f1, int& f2, char& type) 904 +QPDF::Xref_table::read_entry(qpdf_offset_t& f1, int& f2, char& type)
903 { 905 {
  906 + auto* m = qpdf.m.get();
  907 +
904 std::array<char, 21> line; 908 std::array<char, 21> line;
905 if (m->file->read(line.data(), 20) != 20) { 909 if (m->file->read(line.data(), 20) != 20) {
906 // C++20: [[unlikely]] 910 // C++20: [[unlikely]]
@@ -948,13 +952,15 @@ QPDF::read_xrefEntry(qpdf_offset_t&amp; f1, int&amp; f2, char&amp; type) @@ -948,13 +952,15 @@ QPDF::read_xrefEntry(qpdf_offset_t&amp; f1, int&amp; f2, char&amp; type)
948 return true; 952 return true;
949 } 953 }
950 } 954 }
951 - return read_bad_xrefEntry(f1, f2, type); 955 + return read_bad_entry(f1, f2, type);
952 } 956 }
953 957
954 // Read a single cross-reference table section and associated trailer. 958 // Read a single cross-reference table section and associated trailer.
955 qpdf_offset_t 959 qpdf_offset_t
956 -QPDF::read_xrefTable(qpdf_offset_t xref_offset) 960 +QPDF::Xref_table::read_table(qpdf_offset_t xref_offset)
957 { 961 {
  962 + auto* m = qpdf.m.get();
  963 +
958 m->file->seek(xref_offset, SEEK_SET); 964 m->file->seek(xref_offset, SEEK_SET);
959 std::string line; 965 std::string line;
960 while (true) { 966 while (true) {
@@ -963,33 +969,32 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) @@ -963,33 +969,32 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
963 int obj = 0; 969 int obj = 0;
964 int num = 0; 970 int num = 0;
965 int bytes = 0; 971 int bytes = 0;
966 - if (!parse_xrefFirst(line, obj, num, bytes)) { 972 + if (!parse_first(line, obj, num, bytes)) {
967 QTC::TC("qpdf", "QPDF invalid xref"); 973 QTC::TC("qpdf", "QPDF invalid xref");
968 - throw damagedPDF("xref table", "xref syntax invalid"); 974 + throw damaged_table("xref syntax invalid");
969 } 975 }
970 m->file->seek(m->file->getLastOffset() + bytes, SEEK_SET); 976 m->file->seek(m->file->getLastOffset() + bytes, SEEK_SET);
971 for (qpdf_offset_t i = obj; i - num < obj; ++i) { 977 for (qpdf_offset_t i = obj; i - num < obj; ++i) {
972 if (i == 0) { 978 if (i == 0) {
973 // This is needed by checkLinearization() 979 // This is needed by checkLinearization()
974 - m->xref_table.first_item_offset = m->file->tell(); 980 + first_item_offset = m->file->tell();
975 } 981 }
976 // For xref_table, these will always be small enough to be ints 982 // For xref_table, these will always be small enough to be ints
977 qpdf_offset_t f1 = 0; 983 qpdf_offset_t f1 = 0;
978 int f2 = 0; 984 int f2 = 0;
979 char type = '\0'; 985 char type = '\0';
980 - if (!read_xrefEntry(f1, f2, type)) { 986 + if (!read_entry(f1, f2, type)) {
981 QTC::TC("qpdf", "QPDF invalid xref entry"); 987 QTC::TC("qpdf", "QPDF invalid xref entry");
982 - throw damagedPDF(  
983 - "xref table", "invalid xref entry (obj=" + std::to_string(i) + ")"); 988 + throw damaged_table("invalid xref entry (obj=" + std::to_string(i) + ")");
984 } 989 }
985 if (type == 'f') { 990 if (type == 'f') {
986 - m->xref_table.insert_free(QPDFObjGen(toI(i), f2)); 991 + insert_free(QPDFObjGen(toI(i), f2));
987 } else { 992 } else {
988 - m->xref_table.insert(toI(i), 1, f1, f2); 993 + insert(toI(i), 1, f1, f2);
989 } 994 }
990 } 995 }
991 qpdf_offset_t pos = m->file->tell(); 996 qpdf_offset_t pos = m->file->tell();
992 - if (readToken(*m->file).isWord("trailer")) { 997 + if (qpdf.readToken(*m->file).isWord("trailer")) {
993 break; 998 break;
994 } else { 999 } else {
995 m->file->seek(pos, SEEK_SET); 1000 m->file->seek(pos, SEEK_SET);
@@ -997,35 +1002,35 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) @@ -997,35 +1002,35 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
997 } 1002 }
998 1003
999 // Set offset to previous xref table if any 1004 // Set offset to previous xref table if any
1000 - QPDFObjectHandle cur_trailer = readTrailer(); 1005 + auto cur_trailer = qpdf.readTrailer();
1001 if (!cur_trailer.isDictionary()) { 1006 if (!cur_trailer.isDictionary()) {
1002 QTC::TC("qpdf", "QPDF missing trailer"); 1007 QTC::TC("qpdf", "QPDF missing trailer");
1003 - throw damagedPDF("", "expected trailer dictionary"); 1008 + throw qpdf.damagedPDF("", "expected trailer dictionary");
1004 } 1009 }
1005 1010
1006 - if (!m->xref_table.trailer) {  
1007 - setTrailer(cur_trailer); 1011 + if (!trailer) {
  1012 + trailer = cur_trailer;
1008 1013
1009 - if (!m->xref_table.trailer.hasKey("/Size")) { 1014 + if (!trailer.hasKey("/Size")) {
1010 QTC::TC("qpdf", "QPDF trailer lacks size"); 1015 QTC::TC("qpdf", "QPDF trailer lacks size");
1011 - throw damagedPDF("trailer", "trailer dictionary lacks /Size key"); 1016 + throw qpdf.damagedPDF("trailer", "trailer dictionary lacks /Size key");
1012 } 1017 }
1013 - if (!m->xref_table.trailer.getKey("/Size").isInteger()) { 1018 + if (!trailer.getKey("/Size").isInteger()) {
1014 QTC::TC("qpdf", "QPDF trailer size not integer"); 1019 QTC::TC("qpdf", "QPDF trailer size not integer");
1015 - throw damagedPDF("trailer", "/Size key in trailer dictionary is not an integer"); 1020 + throw qpdf.damagedPDF("trailer", "/Size key in trailer dictionary is not an integer");
1016 } 1021 }
1017 } 1022 }
1018 1023
1019 if (cur_trailer.hasKey("/XRefStm")) { 1024 if (cur_trailer.hasKey("/XRefStm")) {
1020 - if (m->xref_table.ignore_streams) { 1025 + if (ignore_streams) {
1021 QTC::TC("qpdf", "QPDF ignoring XRefStm in trailer"); 1026 QTC::TC("qpdf", "QPDF ignoring XRefStm in trailer");
1022 } else { 1027 } else {
1023 if (cur_trailer.getKey("/XRefStm").isInteger()) { 1028 if (cur_trailer.getKey("/XRefStm").isInteger()) {
1024 // Read the xref stream but disregard any return value -- we'll use our trailer's 1029 // Read the xref stream but disregard any return value -- we'll use our trailer's
1025 // /Prev key instead of the xref stream's. 1030 // /Prev key instead of the xref stream's.
1026 - (void)read_xrefStream(cur_trailer.getKey("/XRefStm").getIntValue()); 1031 + (void)qpdf.read_xrefStream(cur_trailer.getKey("/XRefStm").getIntValue());
1027 } else { 1032 } else {
1028 - throw damagedPDF("xref stream", xref_offset, "invalid /XRefStm"); 1033 + throw qpdf.damagedPDF("xref stream", xref_offset, "invalid /XRefStm");
1029 } 1034 }
1030 } 1035 }
1031 } 1036 }
@@ -1033,7 +1038,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) @@ -1033,7 +1038,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
1033 if (cur_trailer.hasKey("/Prev")) { 1038 if (cur_trailer.hasKey("/Prev")) {
1034 if (!cur_trailer.getKey("/Prev").isInteger()) { 1039 if (!cur_trailer.getKey("/Prev").isInteger()) {
1035 QTC::TC("qpdf", "QPDF trailer prev not integer"); 1040 QTC::TC("qpdf", "QPDF trailer prev not integer");
1036 - throw damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer"); 1041 + throw qpdf.damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer");
1037 } 1042 }
1038 QTC::TC("qpdf", "QPDF prev key in trailer dictionary"); 1043 QTC::TC("qpdf", "QPDF prev key in trailer dictionary");
1039 return cur_trailer.getKey("/Prev").getIntValue(); 1044 return cur_trailer.getKey("/Prev").getIntValue();
libqpdf/qpdf/QPDF_private.hh
@@ -12,6 +12,8 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt; @@ -12,6 +12,8 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt;
12 { 12 {
13 } 13 }
14 14
  15 + qpdf_offset_t read_table(qpdf_offset_t offset);
  16 +
15 void insert_reconstructed(int obj, qpdf_offset_t f1, int f2); 17 void insert_reconstructed(int obj, qpdf_offset_t f1, int f2);
16 void insert(int obj, int f0, qpdf_offset_t f1, int f2); 18 void insert(int obj, int f0, qpdf_offset_t f1, int f2);
17 void insert_free(QPDFObjGen); 19 void insert_free(QPDFObjGen);
@@ -33,12 +35,22 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt; @@ -33,12 +35,22 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt;
33 qpdf_offset_t first_item_offset{0}; // actual value from file 35 qpdf_offset_t first_item_offset{0}; // actual value from file
34 36
35 private: 37 private:
  38 + 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);
  40 + bool read_bad_entry(qpdf_offset_t& f1, int& f2, char& type);
  41 +
36 QPDFExc 42 QPDFExc
37 damaged_pdf(std::string const& msg) 43 damaged_pdf(std::string const& msg)
38 { 44 {
39 return qpdf.damagedPDF("", 0, msg); 45 return qpdf.damagedPDF("", 0, msg);
40 } 46 }
41 47
  48 + QPDFExc
  49 + damaged_table(std::string const& msg)
  50 + {
  51 + return qpdf.damagedPDF("xref table", msg);
  52 + }
  53 +
42 void 54 void
43 warn_damaged(std::string const& msg) 55 warn_damaged(std::string const& msg)
44 { 56 {