Commit a4db9b3149562a6117b1d9edf89e3853480aeba8

Authored by m-holger
1 parent f30a5eb0

Move QPDF::read_xref to QPDF::Xref_table

include/qpdf/QPDF.hh
@@ -759,7 +759,6 @@ class QPDF @@ -759,7 +759,6 @@ 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 read_xref(qpdf_offset_t offset);  
763 bool resolveXRefTable(); 762 bool resolveXRefTable();
764 void setLastObjectDescription(std::string const& description, QPDFObjGen const& og); 763 void setLastObjectDescription(std::string const& description, QPDFObjGen const& og);
765 QPDFObjectHandle readTrailer(); 764 QPDFObjectHandle readTrailer();
libqpdf/QPDF.cc
@@ -468,7 +468,7 @@ QPDF::parse(char const* password) @@ -468,7 +468,7 @@ QPDF::parse(char const* password)
468 throw damagedPDF("", 0, "can't find startxref"); 468 throw damagedPDF("", 0, "can't find startxref");
469 } 469 }
470 try { 470 try {
471 - read_xref(xref_offset); 471 + m->xref_table.read(xref_offset);
472 } catch (QPDFExc&) { 472 } catch (QPDFExc&) {
473 throw; 473 throw;
474 } catch (std::exception& e) { 474 } catch (std::exception& e) {
@@ -625,7 +625,7 @@ QPDF::Xref_table::reconstruct(QPDFExc& e) @@ -625,7 +625,7 @@ QPDF::Xref_table::reconstruct(QPDFExc& e)
625 } 625 }
626 if (max_offset > 0) { 626 if (max_offset > 0) {
627 try { 627 try {
628 - qpdf.read_xref(max_offset); 628 + read(max_offset);
629 } catch (std::exception&) { 629 } catch (std::exception&) {
630 throw damaged_pdf( 630 throw damaged_pdf(
631 "error decoding candidate xref stream while recovering damaged file"); 631 "error decoding candidate xref stream while recovering damaged file");
@@ -664,8 +664,10 @@ QPDF::Xref_table::reconstruct(QPDFExc& e) @@ -664,8 +664,10 @@ QPDF::Xref_table::reconstruct(QPDFExc& e)
664 } 664 }
665 665
666 void 666 void
667 -QPDF::read_xref(qpdf_offset_t xref_offset) 667 +QPDF::Xref_table::read(qpdf_offset_t xref_offset)
668 { 668 {
  669 + auto* m = qpdf.m.get();
  670 +
669 std::map<int, int> free_table; 671 std::map<int, int> free_table;
670 std::set<qpdf_offset_t> visited; 672 std::set<qpdf_offset_t> visited;
671 while (xref_offset) { 673 while (xref_offset) {
@@ -700,7 +702,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset) @@ -700,7 +702,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
700 if ((strncmp(buf, "xref", 4) == 0) && QUtil::is_space(buf[4])) { 702 if ((strncmp(buf, "xref", 4) == 0) && QUtil::is_space(buf[4])) {
701 if (skipped_space) { 703 if (skipped_space) {
702 QTC::TC("qpdf", "QPDF xref skipped space"); 704 QTC::TC("qpdf", "QPDF xref skipped space");
703 - warn(damagedPDF("", 0, "extraneous whitespace seen before xref")); 705 + warn_damaged("extraneous whitespace seen before xref");
704 } 706 }
705 QTC::TC( 707 QTC::TC(
706 "qpdf", 708 "qpdf",
@@ -714,46 +716,43 @@ QPDF::read_xref(qpdf_offset_t xref_offset) @@ -714,46 +716,43 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
714 while (QUtil::is_space(buf[skip])) { 716 while (QUtil::is_space(buf[skip])) {
715 ++skip; 717 ++skip;
716 } 718 }
717 - xref_offset = m->xref_table.read_table(xref_offset + skip); 719 + xref_offset = read_table(xref_offset + skip);
718 } else { 720 } else {
719 - xref_offset = m->xref_table.read_stream(xref_offset); 721 + xref_offset = read_stream(xref_offset);
720 } 722 }
721 if (visited.count(xref_offset) != 0) { 723 if (visited.count(xref_offset) != 0) {
722 QTC::TC("qpdf", "QPDF xref loop"); 724 QTC::TC("qpdf", "QPDF xref loop");
723 - throw damagedPDF("", 0, "loop detected following xref tables"); 725 + throw damaged_pdf("loop detected following xref tables");
724 } 726 }
725 } 727 }
726 728
727 - if (!m->xref_table.trailer) {  
728 - throw damagedPDF("", 0, "unable to find trailer while reading xref"); 729 + if (!trailer) {
  730 + throw damaged_pdf("unable to find trailer while reading xref");
729 } 731 }
730 - int size = m->xref_table.trailer.getKey("/Size").getIntValueAsInt(); 732 + int size = trailer.getKey("/Size").getIntValueAsInt();
731 int max_obj = 0; 733 int max_obj = 0;
732 - if (!m->xref_table.empty()) {  
733 - max_obj = m->xref_table.rbegin()->first.getObj(); 734 + if (!empty()) {
  735 + max_obj = rbegin()->first.getObj();
734 } 736 }
735 - if (!m->xref_table.deleted_objects.empty()) {  
736 - max_obj = std::max(max_obj, *(m->xref_table.deleted_objects.rbegin())); 737 + if (!deleted_objects.empty()) {
  738 + max_obj = std::max(max_obj, *deleted_objects.rbegin());
737 } 739 }
738 if ((size < 1) || (size - 1 != max_obj)) { 740 if ((size < 1) || (size - 1 != max_obj)) {
739 QTC::TC("qpdf", "QPDF xref size mismatch"); 741 QTC::TC("qpdf", "QPDF xref size mismatch");
740 - warn(damagedPDF(  
741 - "",  
742 - 0,  
743 - ("reported number of objects (" + std::to_string(size) +  
744 - ") is not one plus the highest object number (" + std::to_string(max_obj) + ")"))); 742 + warn_damaged("reported number of objects (" + std::to_string(size) +
  743 + ") is not one plus the highest object number (" + std::to_string(max_obj) + ")");
745 } 744 }
746 745
747 // We no longer need the deleted_objects table, so go ahead and clear it out to make sure we 746 // We no longer need the deleted_objects table, so go ahead and clear it out to make sure we
748 // never depend on its being set. 747 // never depend on its being set.
749 - m->xref_table.deleted_objects.clear(); 748 + deleted_objects.clear();
750 749
751 // Make sure we keep only the highest generation for any object. 750 // Make sure we keep only the highest generation for any object.
752 QPDFObjGen last_og{-1, 0}; 751 QPDFObjGen last_og{-1, 0};
753 - for (auto const& item: m->xref_table) { 752 + for (auto const& item: *this) {
754 auto id = item.first.getObj(); 753 auto id = item.first.getObj();
755 if (id == last_og.getObj() && id > 0) { 754 if (id == last_og.getObj() && id > 0) {
756 - removeObject(last_og); 755 + qpdf.removeObject(last_og);
757 } 756 }
758 last_og = item.first; 757 last_og = item.first;
759 } 758 }
libqpdf/qpdf/QPDF_private.hh
@@ -12,9 +12,7 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt; @@ -12,9 +12,7 @@ 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 - qpdf_offset_t read_stream(qpdf_offset_t offset);  
17 - 15 + void read(qpdf_offset_t offset);
18 void reconstruct(QPDFExc& e); 16 void reconstruct(QPDFExc& e);
19 17
20 QPDFObjectHandle trailer; 18 QPDFObjectHandle trailer;
@@ -32,9 +30,14 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt; @@ -32,9 +30,14 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt;
32 qpdf_offset_t first_item_offset{0}; // actual value from file 30 qpdf_offset_t first_item_offset{0}; // actual value from file
33 31
34 private: 32 private:
  33 + // Methods to parse tables
  34 + qpdf_offset_t read_table(qpdf_offset_t offset);
35 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);
36 bool read_entry(qpdf_offset_t& f1, int& f2, char& type); 36 bool read_entry(qpdf_offset_t& f1, int& f2, char& type);
37 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 +
  39 + // Methods to parse streams
  40 + qpdf_offset_t read_stream(qpdf_offset_t offset);
38 qpdf_offset_t process_stream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream); 41 qpdf_offset_t process_stream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream);
39 std::pair<int, std::array<int, 3>> 42 std::pair<int, std::array<int, 3>>
40 process_W(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged); 43 process_W(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged);
@@ -45,6 +48,7 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt; @@ -45,6 +48,7 @@ class QPDF::Xref_table: public std::map&lt;QPDFObjGen, QPDFXRefEntry&gt;
45 int max_num_entries, 48 int max_num_entries,
46 std::function<QPDFExc(std::string_view)> damaged); 49 std::function<QPDFExc(std::string_view)> damaged);
47 50
  51 + // Methods to insert table entries
48 void insert_reconstructed(int obj, qpdf_offset_t f1, int f2); 52 void insert_reconstructed(int obj, qpdf_offset_t f1, int f2);
49 void insert(int obj, int f0, qpdf_offset_t f1, int f2); 53 void insert(int obj, int f0, qpdf_offset_t f1, int f2);
50 void insert_free(QPDFObjGen); 54 void insert_free(QPDFObjGen);