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 762 void setTrailer(QPDFObjectHandle obj);
763 763 void read_xref(qpdf_offset_t offset);
764 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 765 qpdf_offset_t read_xrefStream(qpdf_offset_t offset);
770 766 qpdf_offset_t processXRefStream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream);
771 767 std::pair<int, std::array<int, 3>>
... ...
libqpdf/QPDF.cc
... ... @@ -723,7 +723,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
723 723 while (QUtil::is_space(buf[skip])) {
724 724 ++skip;
725 725 }
726   - xref_offset = read_xrefTable(xref_offset + skip);
  726 + xref_offset = m->xref_table.read_table(xref_offset + skip);
727 727 } else {
728 728 xref_offset = read_xrefStream(xref_offset);
729 729 }
... ... @@ -769,7 +769,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
769 769 }
770 770  
771 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 774 // is_space and is_digit both return false on '\0', so this will not overrun the null-terminated
775 775 // buffer.
... ... @@ -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 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 824 // Reposition after initial read attempt and reread.
823 825 m->file->seek(m->file->getLastOffset(), SEEK_SET);
824 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 889 }
888 890  
889 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 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 901 // Optimistically read and parse xref entry. If entry is bad, call read_bad_xrefEntry and return
900 902 // result.
901 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 908 std::array<char, 21> line;
905 909 if (m->file->read(line.data(), 20) != 20) {
906 910 // C++20: [[unlikely]]
... ... @@ -948,13 +952,15 @@ QPDF::read_xrefEntry(qpdf_offset_t&amp; f1, int&amp; f2, char&amp; type)
948 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 958 // Read a single cross-reference table section and associated trailer.
955 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 964 m->file->seek(xref_offset, SEEK_SET);
959 965 std::string line;
960 966 while (true) {
... ... @@ -963,33 +969,32 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
963 969 int obj = 0;
964 970 int num = 0;
965 971 int bytes = 0;
966   - if (!parse_xrefFirst(line, obj, num, bytes)) {
  972 + if (!parse_first(line, obj, num, bytes)) {
967 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 976 m->file->seek(m->file->getLastOffset() + bytes, SEEK_SET);
971 977 for (qpdf_offset_t i = obj; i - num < obj; ++i) {
972 978 if (i == 0) {
973 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 982 // For xref_table, these will always be small enough to be ints
977 983 qpdf_offset_t f1 = 0;
978 984 int f2 = 0;
979 985 char type = '\0';
980   - if (!read_xrefEntry(f1, f2, type)) {
  986 + if (!read_entry(f1, f2, type)) {
981 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 990 if (type == 'f') {
986   - m->xref_table.insert_free(QPDFObjGen(toI(i), f2));
  991 + insert_free(QPDFObjGen(toI(i), f2));
987 992 } else {
988   - m->xref_table.insert(toI(i), 1, f1, f2);
  993 + insert(toI(i), 1, f1, f2);
989 994 }
990 995 }
991 996 qpdf_offset_t pos = m->file->tell();
992   - if (readToken(*m->file).isWord("trailer")) {
  997 + if (qpdf.readToken(*m->file).isWord("trailer")) {
993 998 break;
994 999 } else {
995 1000 m->file->seek(pos, SEEK_SET);
... ... @@ -997,35 +1002,35 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
997 1002 }
998 1003  
999 1004 // Set offset to previous xref table if any
1000   - QPDFObjectHandle cur_trailer = readTrailer();
  1005 + auto cur_trailer = qpdf.readTrailer();
1001 1006 if (!cur_trailer.isDictionary()) {
1002 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 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 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 1024 if (cur_trailer.hasKey("/XRefStm")) {
1020   - if (m->xref_table.ignore_streams) {
  1025 + if (ignore_streams) {
1021 1026 QTC::TC("qpdf", "QPDF ignoring XRefStm in trailer");
1022 1027 } else {
1023 1028 if (cur_trailer.getKey("/XRefStm").isInteger()) {
1024 1029 // Read the xref stream but disregard any return value -- we'll use our trailer's
1025 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 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 1038 if (cur_trailer.hasKey("/Prev")) {
1034 1039 if (!cur_trailer.getKey("/Prev").isInteger()) {
1035 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 1043 QTC::TC("qpdf", "QPDF prev key in trailer dictionary");
1039 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 12 {
13 13 }
14 14  
  15 + qpdf_offset_t read_table(qpdf_offset_t offset);
  16 +
15 17 void insert_reconstructed(int obj, qpdf_offset_t f1, int f2);
16 18 void insert(int obj, int f0, qpdf_offset_t f1, int f2);
17 19 void insert_free(QPDFObjGen);
... ... @@ -33,12 +35,22 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt;
33 35 qpdf_offset_t first_item_offset{0}; // actual value from file
34 36  
35 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 42 QPDFExc
37 43 damaged_pdf(std::string const& msg)
38 44 {
39 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 54 void
43 55 warn_damaged(std::string const& msg)
44 56 {
... ...