Commit cc9facdb645e163ed67d1311a670c68958e8ac4c
1 parent
61879f9a
Refactor `QPDF`: move warnings and damaged PDF handling logic to `Common` class,…
… streamline error handling, and improve encapsulation.
Showing
7 changed files
with
183 additions
and
160 deletions
include/qpdf/QPDF.hh
| @@ -747,20 +747,7 @@ class QPDF | @@ -747,20 +747,7 @@ class QPDF | ||
| 747 | class ResolveRecorder; | 747 | class ResolveRecorder; |
| 748 | class JSONReactor; | 748 | class JSONReactor; |
| 749 | 749 | ||
| 750 | - void stopOnError(std::string const& message); | ||
| 751 | - inline void | ||
| 752 | - no_ci_stop_if(bool condition, std::string const& message, std::string const& context = {}); | ||
| 753 | void removeObject(QPDFObjGen og); | 750 | void removeObject(QPDFObjGen og); |
| 754 | - static QPDFExc damagedPDF( | ||
| 755 | - InputSource& input, | ||
| 756 | - std::string const& object, | ||
| 757 | - qpdf_offset_t offset, | ||
| 758 | - std::string const& message); | ||
| 759 | - QPDFExc damagedPDF(InputSource& input, qpdf_offset_t offset, std::string const& message); | ||
| 760 | - QPDFExc damagedPDF(std::string const& object, qpdf_offset_t offset, std::string const& message); | ||
| 761 | - QPDFExc damagedPDF(std::string const& object, std::string const& message); | ||
| 762 | - QPDFExc damagedPDF(qpdf_offset_t offset, std::string const& message); | ||
| 763 | - QPDFExc damagedPDF(std::string const& message); | ||
| 764 | 751 | ||
| 765 | // Calls finish() on the pipeline when done but does not delete it | 752 | // Calls finish() on the pipeline when done but does not delete it |
| 766 | bool pipeStreamData( | 753 | bool pipeStreamData( |
libqpdf/QPDF.cc
| @@ -27,7 +27,9 @@ | @@ -27,7 +27,9 @@ | ||
| 27 | using namespace qpdf; | 27 | using namespace qpdf; |
| 28 | using namespace std::literals; | 28 | using namespace std::literals; |
| 29 | 29 | ||
| 30 | -using Objects = QPDF::Doc::Objects; | 30 | +using Doc = QPDF::Doc; |
| 31 | +using Common = Doc::Common; | ||
| 32 | +using Objects = Doc::Objects; | ||
| 31 | using Foreign = Objects::Foreign; | 33 | using Foreign = Objects::Foreign; |
| 32 | using Streams = Objects::Streams; | 34 | using Streams = Objects::Streams; |
| 33 | 35 | ||
| @@ -364,6 +366,12 @@ QPDF::findHeader() | @@ -364,6 +366,12 @@ QPDF::findHeader() | ||
| 364 | void | 366 | void |
| 365 | QPDF::warn(QPDFExc const& e) | 367 | QPDF::warn(QPDFExc const& e) |
| 366 | { | 368 | { |
| 369 | + m->c.warn(e); | ||
| 370 | +} | ||
| 371 | + | ||
| 372 | +void | ||
| 373 | +Common::warn(QPDFExc const& e) | ||
| 374 | +{ | ||
| 367 | if (m->max_warnings > 0 && m->warnings.size() >= m->max_warnings) { | 375 | if (m->max_warnings > 0 && m->warnings.size() >= m->max_warnings) { |
| 368 | stopOnError("Too many warnings - file is too badly damaged"); | 376 | stopOnError("Too many warnings - file is too badly damaged"); |
| 369 | } | 377 | } |
| @@ -380,7 +388,17 @@ QPDF::warn( | @@ -380,7 +388,17 @@ QPDF::warn( | ||
| 380 | qpdf_offset_t offset, | 388 | qpdf_offset_t offset, |
| 381 | std::string const& message) | 389 | std::string const& message) |
| 382 | { | 390 | { |
| 383 | - warn(QPDFExc(error_code, getFilename(), object, offset, message)); | 391 | + m->c.warn(QPDFExc(error_code, getFilename(), object, offset, message)); |
| 392 | +} | ||
| 393 | + | ||
| 394 | +void | ||
| 395 | +Common::warn( | ||
| 396 | + qpdf_error_code_e error_code, | ||
| 397 | + std::string const& object, | ||
| 398 | + qpdf_offset_t offset, | ||
| 399 | + std::string const& message) | ||
| 400 | +{ | ||
| 401 | + warn(QPDFExc(error_code, qpdf.getFilename(), object, offset, message)); | ||
| 384 | } | 402 | } |
| 385 | 403 | ||
| 386 | QPDFObjectHandle | 404 | QPDFObjectHandle |
| @@ -515,7 +533,7 @@ Objects::Foreign::Copier::copied(QPDFObjectHandle const& foreign) | @@ -515,7 +533,7 @@ Objects::Foreign::Copier::copied(QPDFObjectHandle const& foreign) | ||
| 515 | 533 | ||
| 516 | auto og = foreign.getObjGen(); | 534 | auto og = foreign.getObjGen(); |
| 517 | if (!object_map.contains(og)) { | 535 | if (!object_map.contains(og)) { |
| 518 | - qpdf.warn(qpdf.damagedPDF( | 536 | + warn(damagedPDF( |
| 519 | foreign.qpdf()->getFilename() + " object " + og.unparse(' '), | 537 | foreign.qpdf()->getFilename() + " object " + og.unparse(' '), |
| 520 | foreign.offset(), | 538 | foreign.offset(), |
| 521 | "unexpected reference to /Pages object while copying foreign object; replacing with " | 539 | "unexpected reference to /Pages object while copying foreign object; replacing with " |
| @@ -693,12 +711,12 @@ QPDF::getRoot() | @@ -693,12 +711,12 @@ QPDF::getRoot() | ||
| 693 | { | 711 | { |
| 694 | QPDFObjectHandle root = m->trailer.getKey("/Root"); | 712 | QPDFObjectHandle root = m->trailer.getKey("/Root"); |
| 695 | if (!root.isDictionary()) { | 713 | if (!root.isDictionary()) { |
| 696 | - throw damagedPDF("", -1, "unable to find /Root dictionary"); | 714 | + throw m->c.damagedPDF("", -1, "unable to find /Root dictionary"); |
| 697 | } else if ( | 715 | } else if ( |
| 698 | // Check_mode is an interim solution to request #810 pending a more comprehensive review of | 716 | // Check_mode is an interim solution to request #810 pending a more comprehensive review of |
| 699 | // the approach to more extensive checks and warning levels. | 717 | // the approach to more extensive checks and warning levels. |
| 700 | m->check_mode && !root.getKey("/Type").isNameAndEquals("/Catalog")) { | 718 | m->check_mode && !root.getKey("/Type").isNameAndEquals("/Catalog")) { |
| 701 | - warn(damagedPDF("", -1, "catalog /Type entry missing or invalid")); | 719 | + warn(m->c.damagedPDF("", -1, "catalog /Type entry missing or invalid")); |
| 702 | root.replaceKey("/Type", "/Catalog"_qpdf); | 720 | root.replaceKey("/Type", "/Catalog"_qpdf); |
| 703 | } | 721 | } |
| 704 | return root; | 722 | return root; |
| @@ -744,7 +762,7 @@ QPDF::pipeStreamData( | @@ -744,7 +762,7 @@ QPDF::pipeStreamData( | ||
| 744 | try { | 762 | try { |
| 745 | auto buf = file->read(length, offset); | 763 | auto buf = file->read(length, offset); |
| 746 | if (buf.size() != length) { | 764 | if (buf.size() != length) { |
| 747 | - throw damagedPDF( | 765 | + throw qpdf_for_warning.m->c.damagedPDF( |
| 748 | *file, "", offset + toO(buf.size()), "unexpected EOF reading stream data"); | 766 | *file, "", offset + toO(buf.size()), "unexpected EOF reading stream data"); |
| 749 | } | 767 | } |
| 750 | pipeline->write(buf.data(), length); | 768 | pipeline->write(buf.data(), length); |
| @@ -760,7 +778,7 @@ QPDF::pipeStreamData( | @@ -760,7 +778,7 @@ QPDF::pipeStreamData( | ||
| 760 | QTC::TC("qpdf", "QPDF decoding error warning"); | 778 | QTC::TC("qpdf", "QPDF decoding error warning"); |
| 761 | qpdf_for_warning.warn( | 779 | qpdf_for_warning.warn( |
| 762 | // line-break | 780 | // line-break |
| 763 | - damagedPDF( | 781 | + qpdf_for_warning.m->c.damagedPDF( |
| 764 | *file, | 782 | *file, |
| 765 | "", | 783 | "", |
| 766 | file->getLastOffset(), | 784 | file->getLastOffset(), |
| @@ -769,7 +787,7 @@ QPDF::pipeStreamData( | @@ -769,7 +787,7 @@ QPDF::pipeStreamData( | ||
| 769 | if (will_retry) { | 787 | if (will_retry) { |
| 770 | qpdf_for_warning.warn( | 788 | qpdf_for_warning.warn( |
| 771 | // line-break | 789 | // line-break |
| 772 | - damagedPDF( | 790 | + qpdf_for_warning.m->c.damagedPDF( |
| 773 | *file, | 791 | *file, |
| 774 | "", | 792 | "", |
| 775 | file->getLastOffset(), | 793 | file->getLastOffset(), |
| @@ -815,14 +833,14 @@ QPDF::pipeStreamData( | @@ -815,14 +833,14 @@ QPDF::pipeStreamData( | ||
| 815 | // Throw a generic exception when we lack context for something more specific. New code should not | 833 | // Throw a generic exception when we lack context for something more specific. New code should not |
| 816 | // use this. | 834 | // use this. |
| 817 | void | 835 | void |
| 818 | -QPDF::stopOnError(std::string const& message) | 836 | +Common::stopOnError(std::string const& message) |
| 819 | { | 837 | { |
| 820 | throw damagedPDF("", message); | 838 | throw damagedPDF("", message); |
| 821 | } | 839 | } |
| 822 | 840 | ||
| 823 | // Return an exception of type qpdf_e_damaged_pdf. | 841 | // Return an exception of type qpdf_e_damaged_pdf. |
| 824 | QPDFExc | 842 | QPDFExc |
| 825 | -QPDF::damagedPDF( | 843 | +Common::damagedPDF( |
| 826 | InputSource& input, std::string const& object, qpdf_offset_t offset, std::string const& message) | 844 | InputSource& input, std::string const& object, qpdf_offset_t offset, std::string const& message) |
| 827 | { | 845 | { |
| 828 | return {qpdf_e_damaged_pdf, input.getName(), object, offset, message, true}; | 846 | return {qpdf_e_damaged_pdf, input.getName(), object, offset, message, true}; |
| @@ -831,14 +849,15 @@ QPDF::damagedPDF( | @@ -831,14 +849,15 @@ QPDF::damagedPDF( | ||
| 831 | // Return an exception of type qpdf_e_damaged_pdf. The object is taken from | 849 | // Return an exception of type qpdf_e_damaged_pdf. The object is taken from |
| 832 | // m->last_object_description. | 850 | // m->last_object_description. |
| 833 | QPDFExc | 851 | QPDFExc |
| 834 | -QPDF::damagedPDF(InputSource& input, qpdf_offset_t offset, std::string const& message) | 852 | +Common::damagedPDF(InputSource& input, qpdf_offset_t offset, std::string const& message) const |
| 835 | { | 853 | { |
| 836 | return damagedPDF(input, m->last_object_description, offset, message); | 854 | return damagedPDF(input, m->last_object_description, offset, message); |
| 837 | } | 855 | } |
| 838 | 856 | ||
| 839 | // Return an exception of type qpdf_e_damaged_pdf. The filename is taken from m->file. | 857 | // Return an exception of type qpdf_e_damaged_pdf. The filename is taken from m->file. |
| 840 | QPDFExc | 858 | QPDFExc |
| 841 | -QPDF::damagedPDF(std::string const& object, qpdf_offset_t offset, std::string const& message) | 859 | +Common::damagedPDF( |
| 860 | + std::string const& object, qpdf_offset_t offset, std::string const& message) const | ||
| 842 | { | 861 | { |
| 843 | return {qpdf_e_damaged_pdf, m->file->getName(), object, offset, message, true}; | 862 | return {qpdf_e_damaged_pdf, m->file->getName(), object, offset, message, true}; |
| 844 | } | 863 | } |
| @@ -846,7 +865,7 @@ QPDF::damagedPDF(std::string const& object, qpdf_offset_t offset, std::string co | @@ -846,7 +865,7 @@ QPDF::damagedPDF(std::string const& object, qpdf_offset_t offset, std::string co | ||
| 846 | // Return an exception of type qpdf_e_damaged_pdf. The filename is taken from m->file and the | 865 | // Return an exception of type qpdf_e_damaged_pdf. The filename is taken from m->file and the |
| 847 | // offset from .m->file->getLastOffset(). | 866 | // offset from .m->file->getLastOffset(). |
| 848 | QPDFExc | 867 | QPDFExc |
| 849 | -QPDF::damagedPDF(std::string const& object, std::string const& message) | 868 | +Common::damagedPDF(std::string const& object, std::string const& message) const |
| 850 | { | 869 | { |
| 851 | return damagedPDF(object, m->file->getLastOffset(), message); | 870 | return damagedPDF(object, m->file->getLastOffset(), message); |
| 852 | } | 871 | } |
| @@ -854,7 +873,7 @@ QPDF::damagedPDF(std::string const& object, std::string const& message) | @@ -854,7 +873,7 @@ QPDF::damagedPDF(std::string const& object, std::string const& message) | ||
| 854 | // Return an exception of type qpdf_e_damaged_pdf. The filename is taken from m->file and the object | 873 | // Return an exception of type qpdf_e_damaged_pdf. The filename is taken from m->file and the object |
| 855 | // from .m->last_object_description. | 874 | // from .m->last_object_description. |
| 856 | QPDFExc | 875 | QPDFExc |
| 857 | -QPDF::damagedPDF(qpdf_offset_t offset, std::string const& message) | 876 | +Common::damagedPDF(qpdf_offset_t offset, std::string const& message) const |
| 858 | { | 877 | { |
| 859 | return damagedPDF(m->last_object_description, offset, message); | 878 | return damagedPDF(m->last_object_description, offset, message); |
| 860 | } | 879 | } |
| @@ -862,7 +881,7 @@ QPDF::damagedPDF(qpdf_offset_t offset, std::string const& message) | @@ -862,7 +881,7 @@ QPDF::damagedPDF(qpdf_offset_t offset, std::string const& message) | ||
| 862 | // Return an exception of type qpdf_e_damaged_pdf. The filename is taken from m->file, the object | 881 | // Return an exception of type qpdf_e_damaged_pdf. The filename is taken from m->file, the object |
| 863 | // from m->last_object_description and the offset from m->file->getLastOffset(). | 882 | // from m->last_object_description and the offset from m->file->getLastOffset(). |
| 864 | QPDFExc | 883 | QPDFExc |
| 865 | -QPDF::damagedPDF(std::string const& message) | 884 | +Common::damagedPDF(std::string const& message) const |
| 866 | { | 885 | { |
| 867 | return damagedPDF(m->last_object_description, m->file->getLastOffset(), message); | 886 | return damagedPDF(m->last_object_description, m->file->getLastOffset(), message); |
| 868 | } | 887 | } |
libqpdf/QPDF_encryption.cc
| @@ -734,15 +734,16 @@ QPDF::EncryptionParameters::initialize(QPDF& qpdf) | @@ -734,15 +734,16 @@ QPDF::EncryptionParameters::initialize(QPDF& qpdf) | ||
| 734 | } | 734 | } |
| 735 | encryption_initialized = true; | 735 | encryption_initialized = true; |
| 736 | 736 | ||
| 737 | + auto& c = qpdf.m->c; | ||
| 737 | auto& qm = *qpdf.m; | 738 | auto& qm = *qpdf.m; |
| 738 | auto& trailer = qm.trailer; | 739 | auto& trailer = qm.trailer; |
| 739 | auto& file = qm.file; | 740 | auto& file = qm.file; |
| 740 | 741 | ||
| 741 | - auto warn_damaged_pdf = [&qpdf](std::string const& msg) { | ||
| 742 | - qpdf.warn(qpdf.damagedPDF("encryption dictionary", msg)); | 742 | + auto warn_damaged_pdf = [&qpdf, c](std::string const& msg) { |
| 743 | + qpdf.warn(c.damagedPDF("encryption dictionary", msg)); | ||
| 743 | }; | 744 | }; |
| 744 | auto throw_damaged_pdf = [&qpdf](std::string const& msg) { | 745 | auto throw_damaged_pdf = [&qpdf](std::string const& msg) { |
| 745 | - throw qpdf.damagedPDF("encryption dictionary", msg); | 746 | + throw qpdf.m->c.damagedPDF("encryption dictionary", msg); |
| 746 | }; | 747 | }; |
| 747 | auto unsupported = [&file](std::string const& msg) -> QPDFExc { | 748 | auto unsupported = [&file](std::string const& msg) -> QPDFExc { |
| 748 | return { | 749 | return { |
| @@ -770,14 +771,14 @@ QPDF::EncryptionParameters::initialize(QPDF& qpdf) | @@ -770,14 +771,14 @@ QPDF::EncryptionParameters::initialize(QPDF& qpdf) | ||
| 770 | if (id_obj.size() != 2 || !id_obj.getArrayItem(0).isString()) { | 771 | if (id_obj.size() != 2 || !id_obj.getArrayItem(0).isString()) { |
| 771 | // Treating a missing ID as the empty string enables qpdf to decrypt some invalid encrypted | 772 | // Treating a missing ID as the empty string enables qpdf to decrypt some invalid encrypted |
| 772 | // files with no /ID that poppler can read but Adobe Reader can't. | 773 | // files with no /ID that poppler can read but Adobe Reader can't. |
| 773 | - qpdf.warn(qpdf.damagedPDF("trailer", "invalid /ID in trailer dictionary")); | 774 | + qpdf.warn(qpdf.m->c.damagedPDF("trailer", "invalid /ID in trailer dictionary")); |
| 774 | } else { | 775 | } else { |
| 775 | id1 = id_obj.getArrayItem(0).getStringValue(); | 776 | id1 = id_obj.getArrayItem(0).getStringValue(); |
| 776 | } | 777 | } |
| 777 | 778 | ||
| 778 | auto encryption_dict = trailer.getKey("/Encrypt"); | 779 | auto encryption_dict = trailer.getKey("/Encrypt"); |
| 779 | if (!encryption_dict.isDictionary()) { | 780 | if (!encryption_dict.isDictionary()) { |
| 780 | - throw qpdf.damagedPDF("/Encrypt in trailer dictionary is not a dictionary"); | 781 | + throw qpdf.m->c.damagedPDF("/Encrypt in trailer dictionary is not a dictionary"); |
| 781 | } | 782 | } |
| 782 | 783 | ||
| 783 | if (Name(encryption_dict["/Filter"]) != "/Standard") { | 784 | if (Name(encryption_dict["/Filter"]) != "/Standard") { |
| @@ -984,7 +985,7 @@ QPDF::decryptString(std::string& str, QPDFObjGen og) | @@ -984,7 +985,7 @@ QPDF::decryptString(std::string& str, QPDFObjGen og) | ||
| 984 | break; | 985 | break; |
| 985 | 986 | ||
| 986 | default: | 987 | default: |
| 987 | - warn(damagedPDF( | 988 | + warn(m->c.damagedPDF( |
| 988 | "unknown encryption filter for strings (check /StrF in " | 989 | "unknown encryption filter for strings (check /StrF in " |
| 989 | "/Encrypt dictionary); strings may be decrypted improperly")); | 990 | "/Encrypt dictionary); strings may be decrypted improperly")); |
| 990 | // To avoid repeated warnings, reset cf_string. Assume we'd want to use AES if V == 4. | 991 | // To avoid repeated warnings, reset cf_string. Assume we'd want to use AES if V == 4. |
| @@ -1017,7 +1018,8 @@ QPDF::decryptString(std::string& str, QPDFObjGen og) | @@ -1017,7 +1018,8 @@ QPDF::decryptString(std::string& str, QPDFObjGen og) | ||
| 1017 | } catch (QPDFExc&) { | 1018 | } catch (QPDFExc&) { |
| 1018 | throw; | 1019 | throw; |
| 1019 | } catch (std::runtime_error& e) { | 1020 | } catch (std::runtime_error& e) { |
| 1020 | - throw damagedPDF("error decrypting string for object " + og.unparse() + ": " + e.what()); | 1021 | + throw m->c.damagedPDF( |
| 1022 | + "error decrypting string for object " + og.unparse() + ": " + e.what()); | ||
| 1021 | } | 1023 | } |
| 1022 | } | 1024 | } |
| 1023 | 1025 |
libqpdf/QPDF_linearization.cc
| @@ -73,7 +73,7 @@ void | @@ -73,7 +73,7 @@ void | ||
| 73 | Lin::linearizationWarning(std::string_view msg) | 73 | Lin::linearizationWarning(std::string_view msg) |
| 74 | { | 74 | { |
| 75 | m->linearization_warnings = true; | 75 | m->linearization_warnings = true; |
| 76 | - qpdf.warn(qpdf_e_linearization, "", 0, std::string(msg)); | 76 | + warn(qpdf_e_linearization, "", 0, std::string(msg)); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | bool | 79 | bool |
| @@ -166,19 +166,19 @@ Lin::readLinearizationData() | @@ -166,19 +166,19 @@ Lin::readLinearizationData() | ||
| 166 | Integer P = P_oh; // first page number | 166 | Integer P = P_oh; // first page number |
| 167 | QTC::TC("qpdf", "QPDF P absent in lindict", P ? 0 : 1); | 167 | QTC::TC("qpdf", "QPDF P absent in lindict", P ? 0 : 1); |
| 168 | 168 | ||
| 169 | - qpdf.no_ci_stop_if( | 169 | + no_ci_stop_if( |
| 170 | !(H && O && E && N && T && (P || P_oh.null())), | 170 | !(H && O && E && N && T && (P || P_oh.null())), |
| 171 | "some keys in linearization dictionary are of the wrong type", | 171 | "some keys in linearization dictionary are of the wrong type", |
| 172 | "linearization dictionary" // | 172 | "linearization dictionary" // |
| 173 | ); | 173 | ); |
| 174 | 174 | ||
| 175 | - qpdf.no_ci_stop_if( | 175 | + no_ci_stop_if( |
| 176 | !(H_size == 2 || H_size == 4), | 176 | !(H_size == 2 || H_size == 4), |
| 177 | "H has the wrong number of items", | 177 | "H has the wrong number of items", |
| 178 | "linearization dictionary" // | 178 | "linearization dictionary" // |
| 179 | ); | 179 | ); |
| 180 | 180 | ||
| 181 | - qpdf.no_ci_stop_if( | 181 | + no_ci_stop_if( |
| 182 | !(H_0 && H_1 && (H_size == 2 || (H_2 && H_3))), | 182 | !(H_0 && H_1 && (H_size == 2 || (H_2 && H_3))), |
| 183 | "some H items are of the wrong type", | 183 | "some H items are of the wrong type", |
| 184 | "linearization dictionary" // | 184 | "linearization dictionary" // |
| @@ -188,7 +188,7 @@ Lin::readLinearizationData() | @@ -188,7 +188,7 @@ Lin::readLinearizationData() | ||
| 188 | 188 | ||
| 189 | // Various places in the code use linp.npages, which is initialized from N, to pre-allocate | 189 | // Various places in the code use linp.npages, which is initialized from N, to pre-allocate |
| 190 | // memory, so make sure it's accurate and bail right now if it's not. | 190 | // memory, so make sure it's accurate and bail right now if it's not. |
| 191 | - qpdf.no_ci_stop_if( | 191 | + no_ci_stop_if( |
| 192 | N != qpdf.getAllPages().size(), | 192 | N != qpdf.getAllPages().size(), |
| 193 | "/N does not match number of pages", | 193 | "/N does not match number of pages", |
| 194 | "linearization dictionary" // | 194 | "linearization dictionary" // |
| @@ -234,13 +234,12 @@ Lin::readLinearizationData() | @@ -234,13 +234,12 @@ Lin::readLinearizationData() | ||
| 234 | 234 | ||
| 235 | size_t HSi = HS; | 235 | size_t HSi = HS; |
| 236 | if (HSi < 0 || HSi >= h_size) { | 236 | if (HSi < 0 || HSi >= h_size) { |
| 237 | - throw qpdf.damagedPDF( | ||
| 238 | - "linearization hint table", "/S (shared object) offset is out of bounds"); | 237 | + throw damagedPDF("linearization hint table", "/S (shared object) offset is out of bounds"); |
| 239 | } | 238 | } |
| 240 | readHSharedObject(BitStream(h_buf + HSi, h_size - HSi)); | 239 | readHSharedObject(BitStream(h_buf + HSi, h_size - HSi)); |
| 241 | 240 | ||
| 242 | if (HO) { | 241 | if (HO) { |
| 243 | - qpdf.no_ci_stop_if( | 242 | + no_ci_stop_if( |
| 244 | HO < 0 || HO >= h_size, | 243 | HO < 0 || HO >= h_size, |
| 245 | "/O (outline) offset is out of bounds", | 244 | "/O (outline) offset is out of bounds", |
| 246 | "linearization dictionary" // | 245 | "linearization dictionary" // |
| @@ -257,7 +256,7 @@ Lin::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length) | @@ -257,7 +256,7 @@ Lin::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length) | ||
| 257 | ObjCache& oc = m->obj_cache[H]; | 256 | ObjCache& oc = m->obj_cache[H]; |
| 258 | qpdf_offset_t min_end_offset = oc.end_before_space; | 257 | qpdf_offset_t min_end_offset = oc.end_before_space; |
| 259 | qpdf_offset_t max_end_offset = oc.end_after_space; | 258 | qpdf_offset_t max_end_offset = oc.end_after_space; |
| 260 | - qpdf.no_ci_stop_if( | 259 | + no_ci_stop_if( |
| 261 | !H.isStream(), "hint table is not a stream", "linearization dictionary" // | 260 | !H.isStream(), "hint table is not a stream", "linearization dictionary" // |
| 262 | ); | 261 | ); |
| 263 | 262 | ||
| @@ -275,7 +274,7 @@ Lin::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length) | @@ -275,7 +274,7 @@ Lin::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length) | ||
| 275 | QTC::TC("qpdf", "QPDF hint table length direct"); | 274 | QTC::TC("qpdf", "QPDF hint table length direct"); |
| 276 | } | 275 | } |
| 277 | qpdf_offset_t computed_end = offset + toO(length); | 276 | qpdf_offset_t computed_end = offset + toO(length); |
| 278 | - qpdf.no_ci_stop_if( | 277 | + no_ci_stop_if( |
| 279 | computed_end < min_end_offset || computed_end > max_end_offset, | 278 | computed_end < min_end_offset || computed_end > max_end_offset, |
| 280 | "hint table length mismatch (expected = " + std::to_string(computed_end) + "; actual = " + | 279 | "hint table length mismatch (expected = " + std::to_string(computed_end) + "; actual = " + |
| 281 | std::to_string(min_end_offset) + ".." + std::to_string(max_end_offset) + ")", | 280 | std::to_string(min_end_offset) + ".." + std::to_string(max_end_offset) + ")", |
| @@ -464,7 +463,7 @@ Lin::checkLinearizationInternal() | @@ -464,7 +463,7 @@ Lin::checkLinearizationInternal() | ||
| 464 | // are present. In that case, it would probably agree with pdlin. As of this writing, the test | 463 | // are present. In that case, it would probably agree with pdlin. As of this writing, the test |
| 465 | // suite doesn't contain any files with threads. | 464 | // suite doesn't contain any files with threads. |
| 466 | 465 | ||
| 467 | - qpdf.no_ci_stop_if( | 466 | + no_ci_stop_if( |
| 468 | m->part6.empty(), "linearization part 6 unexpectedly empty" // | 467 | m->part6.empty(), "linearization part 6 unexpectedly empty" // |
| 469 | ); | 468 | ); |
| 470 | qpdf_offset_t min_E = -1; | 469 | qpdf_offset_t min_E = -1; |
| @@ -494,14 +493,14 @@ Lin::checkLinearizationInternal() | @@ -494,14 +493,14 @@ Lin::checkLinearizationInternal() | ||
| 494 | qpdf_offset_t | 493 | qpdf_offset_t |
| 495 | Lin::maxEnd(ObjUser const& ou) | 494 | Lin::maxEnd(ObjUser const& ou) |
| 496 | { | 495 | { |
| 497 | - qpdf.no_ci_stop_if( | 496 | + no_ci_stop_if( |
| 498 | !m->obj_user_to_objects.contains(ou), | 497 | !m->obj_user_to_objects.contains(ou), |
| 499 | "no entry in object user table for requested object user" // | 498 | "no entry in object user table for requested object user" // |
| 500 | ); | 499 | ); |
| 501 | 500 | ||
| 502 | qpdf_offset_t end = 0; | 501 | qpdf_offset_t end = 0; |
| 503 | for (auto const& og: m->obj_user_to_objects[ou]) { | 502 | for (auto const& og: m->obj_user_to_objects[ou]) { |
| 504 | - qpdf.no_ci_stop_if( | 503 | + no_ci_stop_if( |
| 505 | !m->obj_cache.contains(og), "unknown object referenced in object user table" // | 504 | !m->obj_cache.contains(og), "unknown object referenced in object user table" // |
| 506 | ); | 505 | ); |
| 507 | end = std::max(end, m->obj_cache[og].end_after_space); | 506 | end = std::max(end, m->obj_cache[og].end_after_space); |
| @@ -517,7 +516,7 @@ Lin::getLinearizationOffset(QPDFObjGen og) | @@ -517,7 +516,7 @@ Lin::getLinearizationOffset(QPDFObjGen og) | ||
| 517 | if (typ == 1) { | 516 | if (typ == 1) { |
| 518 | return entry.getOffset(); | 517 | return entry.getOffset(); |
| 519 | } | 518 | } |
| 520 | - qpdf.no_ci_stop_if( | 519 | + no_ci_stop_if( |
| 521 | typ != 2, "getLinearizationOffset called for xref entry not of type 1 or 2" // | 520 | typ != 2, "getLinearizationOffset called for xref entry not of type 1 or 2" // |
| 522 | ); | 521 | ); |
| 523 | // For compressed objects, return the offset of the object stream that contains them. | 522 | // For compressed objects, return the offset of the object stream that contains them. |
| @@ -551,7 +550,7 @@ Lin::lengthNextN(int first_object, int n) | @@ -551,7 +550,7 @@ Lin::lengthNextN(int first_object, int n) | ||
| 551 | for (int i = 0; i < n; ++i) { | 550 | for (int i = 0; i < n; ++i) { |
| 552 | QPDFObjGen og(first_object + i, 0); | 551 | QPDFObjGen og(first_object + i, 0); |
| 553 | if (m->xref_table.contains(og)) { | 552 | if (m->xref_table.contains(og)) { |
| 554 | - qpdf.no_ci_stop_if( | 553 | + no_ci_stop_if( |
| 555 | !m->obj_cache.contains(og), | 554 | !m->obj_cache.contains(og), |
| 556 | "found unknown object while calculating length for linearization data" // | 555 | "found unknown object while calculating length for linearization data" // |
| 557 | ); | 556 | ); |
| @@ -585,7 +584,7 @@ Lin::checkHPageOffset( | @@ -585,7 +584,7 @@ Lin::checkHPageOffset( | ||
| 585 | qpdf_offset_t table_offset = adjusted_offset(m->page_offset_hints.first_page_offset); | 584 | qpdf_offset_t table_offset = adjusted_offset(m->page_offset_hints.first_page_offset); |
| 586 | QPDFObjGen first_page_og(pages.at(0).getObjGen()); | 585 | QPDFObjGen first_page_og(pages.at(0).getObjGen()); |
| 587 | if (!m->xref_table.contains(first_page_og)) { | 586 | if (!m->xref_table.contains(first_page_og)) { |
| 588 | - qpdf.stopOnError("supposed first page object is not known"); | 587 | + stopOnError("supposed first page object is not known"); |
| 589 | } | 588 | } |
| 590 | qpdf_offset_t offset = getLinearizationOffset(first_page_og); | 589 | qpdf_offset_t offset = getLinearizationOffset(first_page_og); |
| 591 | if (table_offset != offset) { | 590 | if (table_offset != offset) { |
| @@ -596,7 +595,7 @@ Lin::checkHPageOffset( | @@ -596,7 +595,7 @@ Lin::checkHPageOffset( | ||
| 596 | QPDFObjGen page_og(pages.at(pageno).getObjGen()); | 595 | QPDFObjGen page_og(pages.at(pageno).getObjGen()); |
| 597 | int first_object = page_og.getObj(); | 596 | int first_object = page_og.getObj(); |
| 598 | if (!m->xref_table.contains(page_og)) { | 597 | if (!m->xref_table.contains(page_og)) { |
| 599 | - qpdf.stopOnError("unknown object in page offset hint table"); | 598 | + stopOnError("unknown object in page offset hint table"); |
| 600 | } | 599 | } |
| 601 | offset = getLinearizationOffset(page_og); | 600 | offset = getLinearizationOffset(page_og); |
| 602 | 601 | ||
| @@ -636,7 +635,7 @@ Lin::checkHPageOffset( | @@ -636,7 +635,7 @@ Lin::checkHPageOffset( | ||
| 636 | 635 | ||
| 637 | for (size_t i = 0; i < toS(he.nshared_objects); ++i) { | 636 | for (size_t i = 0; i < toS(he.nshared_objects); ++i) { |
| 638 | int idx = he.shared_identifiers.at(i); | 637 | int idx = he.shared_identifiers.at(i); |
| 639 | - qpdf.no_ci_stop_if( | 638 | + no_ci_stop_if( |
| 640 | !shared_idx_to_obj.contains(idx), | 639 | !shared_idx_to_obj.contains(idx), |
| 641 | "unable to get object for item in shared objects hint table"); | 640 | "unable to get object for item in shared objects hint table"); |
| 642 | 641 | ||
| @@ -645,7 +644,7 @@ Lin::checkHPageOffset( | @@ -645,7 +644,7 @@ Lin::checkHPageOffset( | ||
| 645 | 644 | ||
| 646 | for (size_t i = 0; i < toS(ce.nshared_objects); ++i) { | 645 | for (size_t i = 0; i < toS(ce.nshared_objects); ++i) { |
| 647 | int idx = ce.shared_identifiers.at(i); | 646 | int idx = ce.shared_identifiers.at(i); |
| 648 | - qpdf.no_ci_stop_if( | 647 | + no_ci_stop_if( |
| 649 | idx >= m->c_shared_object_data.nshared_total, | 648 | idx >= m->c_shared_object_data.nshared_total, |
| 650 | "index out of bounds for shared object hint table" // | 649 | "index out of bounds for shared object hint table" // |
| 651 | ); | 650 | ); |
| @@ -718,7 +717,7 @@ Lin::checkHSharedObject(std::vector<QPDFObjectHandle> const& pages, std::map<int | @@ -718,7 +717,7 @@ Lin::checkHSharedObject(std::vector<QPDFObjectHandle> const& pages, std::map<int | ||
| 718 | 717 | ||
| 719 | QPDFObjGen og(cur_object, 0); | 718 | QPDFObjGen og(cur_object, 0); |
| 720 | if (!m->xref_table.contains(og)) { | 719 | if (!m->xref_table.contains(og)) { |
| 721 | - qpdf.stopOnError("unknown object in shared object hint table"); | 720 | + stopOnError("unknown object in shared object hint table"); |
| 722 | } | 721 | } |
| 723 | qpdf_offset_t offset = getLinearizationOffset(og); | 722 | qpdf_offset_t offset = getLinearizationOffset(og); |
| 724 | qpdf_offset_t h_offset = adjusted_offset(so.first_shared_offset); | 723 | qpdf_offset_t h_offset = adjusted_offset(so.first_shared_offset); |
| @@ -768,7 +767,7 @@ Lin::checkHOutlines() | @@ -768,7 +767,7 @@ Lin::checkHOutlines() | ||
| 768 | return; | 767 | return; |
| 769 | } | 768 | } |
| 770 | QPDFObjGen og(outlines.getObjGen()); | 769 | QPDFObjGen og(outlines.getObjGen()); |
| 771 | - qpdf.no_ci_stop_if( | 770 | + no_ci_stop_if( |
| 772 | !m->xref_table.contains(og), "unknown object in outlines hint table" // | 771 | !m->xref_table.contains(og), "unknown object in outlines hint table" // |
| 773 | ); | 772 | ); |
| 774 | qpdf_offset_t offset = getLinearizationOffset(og); | 773 | qpdf_offset_t offset = getLinearizationOffset(og); |
| @@ -1128,7 +1127,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | @@ -1128,7 +1127,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | ||
| 1128 | 1127 | ||
| 1129 | // Part 4: open document objects. We don't care about the order. | 1128 | // Part 4: open document objects. We don't care about the order. |
| 1130 | 1129 | ||
| 1131 | - qpdf.no_ci_stop_if( | 1130 | + no_ci_stop_if( |
| 1132 | lc_root.size() != 1, "found other than one root while calculating linearization data" // | 1131 | lc_root.size() != 1, "found other than one root while calculating linearization data" // |
| 1133 | ); | 1132 | ); |
| 1134 | 1133 | ||
| @@ -1142,11 +1141,11 @@ Lin::calculateLinearizationData(T const& object_stream_data) | @@ -1142,11 +1141,11 @@ Lin::calculateLinearizationData(T const& object_stream_data) | ||
| 1142 | // any option to set this and also disregards /OpenAction. We will do the same. | 1141 | // any option to set this and also disregards /OpenAction. We will do the same. |
| 1143 | 1142 | ||
| 1144 | // First, place the actual first page object itself. | 1143 | // First, place the actual first page object itself. |
| 1145 | - qpdf.no_ci_stop_if( | 1144 | + no_ci_stop_if( |
| 1146 | pages.empty(), "no pages found while calculating linearization data" // | 1145 | pages.empty(), "no pages found while calculating linearization data" // |
| 1147 | ); | 1146 | ); |
| 1148 | QPDFObjGen first_page_og(pages.at(0).getObjGen()); | 1147 | QPDFObjGen first_page_og(pages.at(0).getObjGen()); |
| 1149 | - qpdf.no_ci_stop_if( | 1148 | + no_ci_stop_if( |
| 1150 | !lc_first_page_private.erase(first_page_og), "unable to linearize first page" // | 1149 | !lc_first_page_private.erase(first_page_og), "unable to linearize first page" // |
| 1151 | ); | 1150 | ); |
| 1152 | m->c_linp.first_page_object = pages.at(0).getObjectID(); | 1151 | m->c_linp.first_page_object = pages.at(0).getObjectID(); |
| @@ -1182,7 +1181,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | @@ -1182,7 +1181,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | ||
| 1182 | // Place this page's page object | 1181 | // Place this page's page object |
| 1183 | 1182 | ||
| 1184 | QPDFObjGen page_og(pages.at(i).getObjGen()); | 1183 | QPDFObjGen page_og(pages.at(i).getObjGen()); |
| 1185 | - qpdf.no_ci_stop_if( | 1184 | + no_ci_stop_if( |
| 1186 | !lc_other_page_private.erase(page_og), | 1185 | !lc_other_page_private.erase(page_og), |
| 1187 | "unable to linearize page " + std::to_string(i) // | 1186 | "unable to linearize page " + std::to_string(i) // |
| 1188 | ); | 1187 | ); |
| @@ -1195,7 +1194,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | @@ -1195,7 +1194,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | ||
| 1195 | m->c_page_offset_data.entries.at(i).nobjects = 1; | 1194 | m->c_page_offset_data.entries.at(i).nobjects = 1; |
| 1196 | 1195 | ||
| 1197 | ObjUser ou(ObjUser::ou_page, i); | 1196 | ObjUser ou(ObjUser::ou_page, i); |
| 1198 | - qpdf.no_ci_stop_if( | 1197 | + no_ci_stop_if( |
| 1199 | !m->obj_user_to_objects.contains(ou), | 1198 | !m->obj_user_to_objects.contains(ou), |
| 1200 | "found unreferenced page while calculating linearization data" // | 1199 | "found unreferenced page while calculating linearization data" // |
| 1201 | ); | 1200 | ); |
| @@ -1231,7 +1230,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | @@ -1231,7 +1230,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | ||
| 1231 | // Place the pages tree. | 1230 | // Place the pages tree. |
| 1232 | std::set<QPDFObjGen> pages_ogs = | 1231 | std::set<QPDFObjGen> pages_ogs = |
| 1233 | m->obj_user_to_objects[ObjUser(ObjUser::ou_root_key, "/Pages")]; | 1232 | m->obj_user_to_objects[ObjUser(ObjUser::ou_root_key, "/Pages")]; |
| 1234 | - qpdf.no_ci_stop_if( | 1233 | + no_ci_stop_if( |
| 1235 | pages_ogs.empty(), "found empty pages tree while calculating linearization data" // | 1234 | pages_ogs.empty(), "found empty pages tree while calculating linearization data" // |
| 1236 | ); | 1235 | ); |
| 1237 | for (auto const& og: pages_ogs) { | 1236 | for (auto const& og: pages_ogs) { |
| @@ -1288,7 +1287,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | @@ -1288,7 +1287,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | ||
| 1288 | size_t num_placed = | 1287 | size_t num_placed = |
| 1289 | m->part4.size() + m->part6.size() + m->part7.size() + m->part8.size() + m->part9.size(); | 1288 | m->part4.size() + m->part6.size() + m->part7.size() + m->part8.size() + m->part9.size(); |
| 1290 | size_t num_wanted = m->object_to_obj_users.size(); | 1289 | size_t num_wanted = m->object_to_obj_users.size(); |
| 1291 | - qpdf.no_ci_stop_if( | 1290 | + no_ci_stop_if( |
| 1292 | // This can happen with damaged files, e.g. if the root is part of the the pages tree. | 1291 | // This can happen with damaged files, e.g. if the root is part of the the pages tree. |
| 1293 | num_placed != num_wanted, | 1292 | num_placed != num_wanted, |
| 1294 | "QPDF::calculateLinearizationData: wrong number of objects placed (num_placed = " + | 1293 | "QPDF::calculateLinearizationData: wrong number of objects placed (num_placed = " + |
| @@ -1326,7 +1325,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | @@ -1326,7 +1325,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | ||
| 1326 | shared.emplace_back(obj); | 1325 | shared.emplace_back(obj); |
| 1327 | } | 1326 | } |
| 1328 | } | 1327 | } |
| 1329 | - qpdf.no_ci_stop_if( | 1328 | + no_ci_stop_if( |
| 1330 | std::cmp_not_equal( | 1329 | std::cmp_not_equal( |
| 1331 | m->c_shared_object_data.nshared_total, m->c_shared_object_data.entries.size()), | 1330 | m->c_shared_object_data.nshared_total, m->c_shared_object_data.entries.size()), |
| 1332 | "shared object hint table has wrong number of entries" // | 1331 | "shared object hint table has wrong number of entries" // |
| @@ -1337,7 +1336,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | @@ -1337,7 +1336,7 @@ Lin::calculateLinearizationData(T const& object_stream_data) | ||
| 1337 | for (size_t i = 1; i < npages; ++i) { | 1336 | for (size_t i = 1; i < npages; ++i) { |
| 1338 | CHPageOffsetEntry& pe = m->c_page_offset_data.entries.at(i); | 1337 | CHPageOffsetEntry& pe = m->c_page_offset_data.entries.at(i); |
| 1339 | ObjUser ou(ObjUser::ou_page, i); | 1338 | ObjUser ou(ObjUser::ou_page, i); |
| 1340 | - qpdf.no_ci_stop_if( | 1339 | + no_ci_stop_if( |
| 1341 | !m->obj_user_to_objects.contains(ou), | 1340 | !m->obj_user_to_objects.contains(ou), |
| 1342 | "found unreferenced page while calculating linearization data" // | 1341 | "found unreferenced page while calculating linearization data" // |
| 1343 | ); | 1342 | ); |
| @@ -1420,12 +1419,12 @@ Lin::outputLengthNextN( | @@ -1420,12 +1419,12 @@ Lin::outputLengthNextN( | ||
| 1420 | 1419 | ||
| 1421 | int first = obj[in_object].renumber; | 1420 | int first = obj[in_object].renumber; |
| 1422 | int last = first + n; | 1421 | int last = first + n; |
| 1423 | - qpdf.no_ci_stop_if( | 1422 | + no_ci_stop_if( |
| 1424 | first <= 0, "found object that is not renumbered while writing linearization data"); | 1423 | first <= 0, "found object that is not renumbered while writing linearization data"); |
| 1425 | qpdf_offset_t length = 0; | 1424 | qpdf_offset_t length = 0; |
| 1426 | for (int i = first; i < last; ++i) { | 1425 | for (int i = first; i < last; ++i) { |
| 1427 | auto l = new_obj[i].length; | 1426 | auto l = new_obj[i].length; |
| 1428 | - qpdf.no_ci_stop_if( | 1427 | + no_ci_stop_if( |
| 1429 | l == 0, "found item with unknown length while writing linearization data" // | 1428 | l == 0, "found item with unknown length while writing linearization data" // |
| 1430 | ); | 1429 | ); |
| 1431 | length += l; | 1430 | length += l; |
| @@ -1502,7 +1501,7 @@ Lin::calculateHPageOffset(QPDFWriter::NewObjTable const& new_obj, QPDFWriter::Ob | @@ -1502,7 +1501,7 @@ Lin::calculateHPageOffset(QPDFWriter::NewObjTable const& new_obj, QPDFWriter::Ob | ||
| 1502 | for (auto& phe_i: phe) { | 1501 | for (auto& phe_i: phe) { |
| 1503 | // Adjust delta entries | 1502 | // Adjust delta entries |
| 1504 | if (phe_i.delta_nobjects < min_nobjects || phe_i.delta_page_length < min_length) { | 1503 | if (phe_i.delta_nobjects < min_nobjects || phe_i.delta_page_length < min_length) { |
| 1505 | - qpdf.stopOnError( | 1504 | + stopOnError( |
| 1506 | "found too small delta nobjects or delta page length while writing " | 1505 | "found too small delta nobjects or delta page length while writing " |
| 1507 | "linearization data"); | 1506 | "linearization data"); |
| 1508 | } | 1507 | } |
| @@ -1537,7 +1536,7 @@ Lin::calculateHSharedObject(QPDFWriter::NewObjTable const& new_obj, QPDFWriter:: | @@ -1537,7 +1536,7 @@ Lin::calculateHSharedObject(QPDFWriter::NewObjTable const& new_obj, QPDFWriter:: | ||
| 1537 | soe.emplace_back(); | 1536 | soe.emplace_back(); |
| 1538 | soe.at(i).delta_group_length = length; | 1537 | soe.at(i).delta_group_length = length; |
| 1539 | } | 1538 | } |
| 1540 | - qpdf.no_ci_stop_if( | 1539 | + no_ci_stop_if( |
| 1541 | soe.size() != toS(cso.nshared_total), "soe has wrong size after initialization" // | 1540 | soe.size() != toS(cso.nshared_total), "soe has wrong size after initialization" // |
| 1542 | ); | 1541 | ); |
| 1543 | 1542 | ||
| @@ -1553,7 +1552,7 @@ Lin::calculateHSharedObject(QPDFWriter::NewObjTable const& new_obj, QPDFWriter:: | @@ -1553,7 +1552,7 @@ Lin::calculateHSharedObject(QPDFWriter::NewObjTable const& new_obj, QPDFWriter:: | ||
| 1553 | 1552 | ||
| 1554 | for (size_t i = 0; i < toS(cso.nshared_total); ++i) { | 1553 | for (size_t i = 0; i < toS(cso.nshared_total); ++i) { |
| 1555 | // Adjust deltas | 1554 | // Adjust deltas |
| 1556 | - qpdf.no_ci_stop_if( | 1555 | + no_ci_stop_if( |
| 1557 | soe.at(i).delta_group_length < min_length, | 1556 | soe.at(i).delta_group_length < min_length, |
| 1558 | "found too small group length while writing linearization data" // | 1557 | "found too small group length while writing linearization data" // |
| 1559 | ); | 1558 | ); |
| @@ -1687,7 +1686,7 @@ Lin::writeHSharedObject(BitWriter& w) | @@ -1687,7 +1686,7 @@ Lin::writeHSharedObject(BitWriter& w) | ||
| 1687 | for (size_t i = 0; i < toS(nitems); ++i) { | 1686 | for (size_t i = 0; i < toS(nitems); ++i) { |
| 1688 | // If signature were present, we'd have to write a 128-bit hash. | 1687 | // If signature were present, we'd have to write a 128-bit hash. |
| 1689 | if (entries.at(i).signature_present != 0) { | 1688 | if (entries.at(i).signature_present != 0) { |
| 1690 | - qpdf.stopOnError("found unexpected signature present while writing linearization data"); | 1689 | + stopOnError("found unexpected signature present while writing linearization data"); |
| 1691 | } | 1690 | } |
| 1692 | } | 1691 | } |
| 1693 | write_vector_int(w, nitems, entries, t.nbits_nobjects, &HSharedObjectEntry::nobjects_minus_one); | 1692 | write_vector_int(w, nitems, entries, t.nbits_nobjects, &HSharedObjectEntry::nobjects_minus_one); |
libqpdf/QPDF_objects.cc
| @@ -123,7 +123,7 @@ Objects::parse(char const* password) | @@ -123,7 +123,7 @@ Objects::parse(char const* password) | ||
| 123 | // Find the header anywhere in the first 1024 bytes of the file. | 123 | // Find the header anywhere in the first 1024 bytes of the file. |
| 124 | PatternFinder hf(qpdf, &QPDF::findHeader); | 124 | PatternFinder hf(qpdf, &QPDF::findHeader); |
| 125 | if (!m->file->findFirst("%PDF-", 0, 1024, hf)) { | 125 | if (!m->file->findFirst("%PDF-", 0, 1024, hf)) { |
| 126 | - qpdf.warn(qpdf.damagedPDF("", -1, "can't find PDF header")); | 126 | + warn(damagedPDF("", -1, "can't find PDF header")); |
| 127 | // QPDFWriter writes files that usually require at least version 1.2 for /FlateDecode | 127 | // QPDFWriter writes files that usually require at least version 1.2 for /FlateDecode |
| 128 | m->pdf_version = "1.2"; | 128 | m->pdf_version = "1.2"; |
| 129 | } | 129 | } |
| @@ -147,14 +147,14 @@ Objects::parse(char const* password) | @@ -147,14 +147,14 @@ Objects::parse(char const* password) | ||
| 147 | 147 | ||
| 148 | try { | 148 | try { |
| 149 | if (xref_offset == 0) { | 149 | if (xref_offset == 0) { |
| 150 | - throw qpdf.damagedPDF("", -1, "can't find startxref"); | 150 | + throw damagedPDF("", -1, "can't find startxref"); |
| 151 | } | 151 | } |
| 152 | try { | 152 | try { |
| 153 | read_xref(xref_offset); | 153 | read_xref(xref_offset); |
| 154 | } catch (QPDFExc&) { | 154 | } catch (QPDFExc&) { |
| 155 | throw; | 155 | throw; |
| 156 | } catch (std::exception& e) { | 156 | } catch (std::exception& e) { |
| 157 | - throw qpdf.damagedPDF("", -1, std::string("error reading xref: ") + e.what()); | 157 | + throw damagedPDF("", -1, std::string("error reading xref: ") + e.what()); |
| 158 | } | 158 | } |
| 159 | } catch (QPDFExc& e) { | 159 | } catch (QPDFExc& e) { |
| 160 | if (m->attempt_recovery) { | 160 | if (m->attempt_recovery) { |
| @@ -168,7 +168,7 @@ Objects::parse(char const* password) | @@ -168,7 +168,7 @@ Objects::parse(char const* password) | ||
| 168 | m->parsed = true; | 168 | m->parsed = true; |
| 169 | if (!m->xref_table.empty() && !qpdf.getRoot().getKey("/Pages").isDictionary()) { | 169 | if (!m->xref_table.empty() && !qpdf.getRoot().getKey("/Pages").isDictionary()) { |
| 170 | // QPDFs created from JSON have an empty xref table and no root object yet. | 170 | // QPDFs created from JSON have an empty xref table and no root object yet. |
| 171 | - throw qpdf.damagedPDF("", -1, "unable to find page tree"); | 171 | + throw damagedPDF("", -1, "unable to find page tree"); |
| 172 | } | 172 | } |
| 173 | } | 173 | } |
| 174 | 174 | ||
| @@ -208,8 +208,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | @@ -208,8 +208,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | ||
| 208 | const auto max_warnings = m->warnings.size() + 1000U; | 208 | const auto max_warnings = m->warnings.size() + 1000U; |
| 209 | auto check_warnings = [this, max_warnings]() { | 209 | auto check_warnings = [this, max_warnings]() { |
| 210 | if (m->warnings.size() > max_warnings) { | 210 | if (m->warnings.size() > max_warnings) { |
| 211 | - throw qpdf.damagedPDF( | ||
| 212 | - "", -1, "too many errors while reconstructing cross-reference table"); | 211 | + throw damagedPDF("", -1, "too many errors while reconstructing cross-reference table"); |
| 213 | } | 212 | } |
| 214 | }; | 213 | }; |
| 215 | 214 | ||
| @@ -217,9 +216,9 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | @@ -217,9 +216,9 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | ||
| 217 | // We may find more objects, which may contain dangling references. | 216 | // We may find more objects, which may contain dangling references. |
| 218 | m->fixed_dangling_refs = false; | 217 | m->fixed_dangling_refs = false; |
| 219 | 218 | ||
| 220 | - qpdf.warn(qpdf.damagedPDF("", -1, "file is damaged")); | ||
| 221 | - qpdf.warn(e); | ||
| 222 | - qpdf.warn(qpdf.damagedPDF("", -1, "Attempting to reconstruct cross-reference table")); | 219 | + warn(damagedPDF("", -1, "file is damaged")); |
| 220 | + warn(e); | ||
| 221 | + warn(damagedPDF("", -1, "Attempting to reconstruct cross-reference table")); | ||
| 223 | 222 | ||
| 224 | // Delete all references to type 1 (uncompressed) objects | 223 | // Delete all references to type 1 (uncompressed) objects |
| 225 | std::vector<QPDFObjGen> to_delete; | 224 | std::vector<QPDFObjGen> to_delete; |
| @@ -253,7 +252,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | @@ -253,7 +252,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | ||
| 253 | if (obj <= m->xref_table_max_id) { | 252 | if (obj <= m->xref_table_max_id) { |
| 254 | found_objects.emplace_back(obj, gen, token_start); | 253 | found_objects.emplace_back(obj, gen, token_start); |
| 255 | } else { | 254 | } else { |
| 256 | - qpdf.warn(qpdf.damagedPDF( | 255 | + warn(damagedPDF( |
| 257 | "", -1, "ignoring object with impossibly large id " + std::to_string(obj))); | 256 | "", -1, "ignoring object with impossibly large id " + std::to_string(obj))); |
| 258 | } | 257 | } |
| 259 | } | 258 | } |
| @@ -278,7 +277,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | @@ -278,7 +277,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | ||
| 278 | 277 | ||
| 279 | if (qpdf.getRoot().getKey("/Pages").isDictionary()) { | 278 | if (qpdf.getRoot().getKey("/Pages").isDictionary()) { |
| 280 | QTC::TC("qpdf", "QPDF startxref more than 1024 before end"); | 279 | QTC::TC("qpdf", "QPDF startxref more than 1024 before end"); |
| 281 | - qpdf.warn(qpdf.damagedPDF( | 280 | + warn(damagedPDF( |
| 282 | "", -1, "startxref was more than 1024 bytes before end of file")); | 281 | "", -1, "startxref was more than 1024 bytes before end of file")); |
| 283 | qpdf.initializeEncryption(); | 282 | qpdf.initializeEncryption(); |
| 284 | m->parsed = true; | 283 | m->parsed = true; |
| @@ -313,7 +312,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | @@ -313,7 +312,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | ||
| 313 | m->trailer = t; | 312 | m->trailer = t; |
| 314 | break; | 313 | break; |
| 315 | } | 314 | } |
| 316 | - qpdf.warn(qpdf.damagedPDF("trailer", *it, "recovered trailer has no /Root entry")); | 315 | + warn(damagedPDF("trailer", *it, "recovered trailer has no /Root entry")); |
| 317 | } | 316 | } |
| 318 | check_warnings(); | 317 | check_warnings(); |
| 319 | } | 318 | } |
| @@ -347,7 +346,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | @@ -347,7 +346,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | ||
| 347 | try { | 346 | try { |
| 348 | read_xref(max_offset, true); | 347 | read_xref(max_offset, true); |
| 349 | } catch (std::exception&) { | 348 | } catch (std::exception&) { |
| 350 | - qpdf.warn(qpdf.damagedPDF( | 349 | + warn(damagedPDF( |
| 351 | "", -1, "error decoding candidate xref stream while recovering damaged file")); | 350 | "", -1, "error decoding candidate xref stream while recovering damaged file")); |
| 352 | } | 351 | } |
| 353 | QTC::TC("qpdf", "QPDF recover xref stream"); | 352 | QTC::TC("qpdf", "QPDF recover xref stream"); |
| @@ -368,7 +367,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | @@ -368,7 +367,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | ||
| 368 | } | 367 | } |
| 369 | if (root) { | 368 | if (root) { |
| 370 | if (!m->trailer) { | 369 | if (!m->trailer) { |
| 371 | - qpdf.warn(qpdf.damagedPDF( | 370 | + warn(damagedPDF( |
| 372 | "", -1, "unable to find trailer dictionary while recovering damaged file")); | 371 | "", -1, "unable to find trailer dictionary while recovering damaged file")); |
| 373 | m->trailer = QPDFObjectHandle::newDictionary(); | 372 | m->trailer = QPDFObjectHandle::newDictionary(); |
| 374 | } | 373 | } |
| @@ -381,13 +380,12 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | @@ -381,13 +380,12 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | ||
| 381 | // could try to get the trailer from there. This may make it possible to recover files with | 380 | // could try to get the trailer from there. This may make it possible to recover files with |
| 382 | // bad startxref pointers even when they have object streams. | 381 | // bad startxref pointers even when they have object streams. |
| 383 | 382 | ||
| 384 | - throw qpdf.damagedPDF( | ||
| 385 | - "", -1, "unable to find trailer dictionary while recovering damaged file"); | 383 | + throw damagedPDF("", -1, "unable to find trailer dictionary while recovering damaged file"); |
| 386 | } | 384 | } |
| 387 | if (m->xref_table.empty()) { | 385 | if (m->xref_table.empty()) { |
| 388 | // We cannot check for an empty xref table in parse because empty tables are valid when | 386 | // We cannot check for an empty xref table in parse because empty tables are valid when |
| 389 | // creating QPDF objects from JSON. | 387 | // creating QPDF objects from JSON. |
| 390 | - throw qpdf.damagedPDF("", -1, "unable to find objects while recovering damaged file"); | 388 | + throw damagedPDF("", -1, "unable to find objects while recovering damaged file"); |
| 391 | } | 389 | } |
| 392 | check_warnings(); | 390 | check_warnings(); |
| 393 | if (!m->parsed) { | 391 | if (!m->parsed) { |
| @@ -396,7 +394,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | @@ -396,7 +394,7 @@ Objects::reconstruct_xref(QPDFExc& e, bool found_startxref) | ||
| 396 | check_warnings(); | 394 | check_warnings(); |
| 397 | if (m->all_pages.empty()) { | 395 | if (m->all_pages.empty()) { |
| 398 | m->parsed = false; | 396 | m->parsed = false; |
| 399 | - throw qpdf.damagedPDF("", -1, "unable to find any pages while recovering damaged file"); | 397 | + throw damagedPDF("", -1, "unable to find any pages while recovering damaged file"); |
| 400 | } | 398 | } |
| 401 | } | 399 | } |
| 402 | 400 | ||
| @@ -443,7 +441,7 @@ Objects::read_xref(qpdf_offset_t xref_offset, bool in_stream_recovery) | @@ -443,7 +441,7 @@ Objects::read_xref(qpdf_offset_t xref_offset, bool in_stream_recovery) | ||
| 443 | // where it is terminated by arbitrary whitespace. | 441 | // where it is terminated by arbitrary whitespace. |
| 444 | if ((strncmp(buf, "xref", 4) == 0) && util::is_space(buf[4])) { | 442 | if ((strncmp(buf, "xref", 4) == 0) && util::is_space(buf[4])) { |
| 445 | if (skipped_space) { | 443 | if (skipped_space) { |
| 446 | - qpdf.warn(qpdf.damagedPDF("", -1, "extraneous whitespace seen before xref")); | 444 | + warn(damagedPDF("", -1, "extraneous whitespace seen before xref")); |
| 447 | } | 445 | } |
| 448 | QTC::TC( | 446 | QTC::TC( |
| 449 | "qpdf", | 447 | "qpdf", |
| @@ -462,12 +460,12 @@ Objects::read_xref(qpdf_offset_t xref_offset, bool in_stream_recovery) | @@ -462,12 +460,12 @@ Objects::read_xref(qpdf_offset_t xref_offset, bool in_stream_recovery) | ||
| 462 | xref_offset = read_xrefStream(xref_offset, in_stream_recovery); | 460 | xref_offset = read_xrefStream(xref_offset, in_stream_recovery); |
| 463 | } | 461 | } |
| 464 | if (visited.contains(xref_offset)) { | 462 | if (visited.contains(xref_offset)) { |
| 465 | - throw qpdf.damagedPDF("", -1, "loop detected following xref tables"); | 463 | + throw damagedPDF("", -1, "loop detected following xref tables"); |
| 466 | } | 464 | } |
| 467 | } | 465 | } |
| 468 | 466 | ||
| 469 | if (!m->trailer) { | 467 | if (!m->trailer) { |
| 470 | - throw qpdf.damagedPDF("", -1, "unable to find trailer while reading xref"); | 468 | + throw damagedPDF("", -1, "unable to find trailer while reading xref"); |
| 471 | } | 469 | } |
| 472 | int size = m->trailer.getKey("/Size").getIntValueAsInt(); | 470 | int size = m->trailer.getKey("/Size").getIntValueAsInt(); |
| 473 | int max_obj = 0; | 471 | int max_obj = 0; |
| @@ -478,7 +476,7 @@ Objects::read_xref(qpdf_offset_t xref_offset, bool in_stream_recovery) | @@ -478,7 +476,7 @@ Objects::read_xref(qpdf_offset_t xref_offset, bool in_stream_recovery) | ||
| 478 | max_obj = std::max(max_obj, *(m->deleted_objects.rbegin())); | 476 | max_obj = std::max(max_obj, *(m->deleted_objects.rbegin())); |
| 479 | } | 477 | } |
| 480 | if ((size < 1) || (size - 1 != max_obj)) { | 478 | if ((size < 1) || (size - 1 != max_obj)) { |
| 481 | - qpdf.warn(qpdf.damagedPDF( | 479 | + warn(damagedPDF( |
| 482 | "", | 480 | "", |
| 483 | -1, | 481 | -1, |
| 484 | ("reported number of objects (" + std::to_string(size) + | 482 | ("reported number of objects (" + std::to_string(size) + |
| @@ -615,7 +613,7 @@ Objects::read_bad_xrefEntry(qpdf_offset_t& f1, int& f2, char& type) | @@ -615,7 +613,7 @@ Objects::read_bad_xrefEntry(qpdf_offset_t& f1, int& f2, char& type) | ||
| 615 | } | 613 | } |
| 616 | 614 | ||
| 617 | if (invalid) { | 615 | if (invalid) { |
| 618 | - qpdf.warn(qpdf.damagedPDF("xref table", "accepting invalid xref table entry")); | 616 | + warn(damagedPDF("xref table", "accepting invalid xref table entry")); |
| 619 | } | 617 | } |
| 620 | 618 | ||
| 621 | f1 = QUtil::string_to_ll(f1_str.c_str()); | 619 | f1 = QUtil::string_to_ll(f1_str.c_str()); |
| @@ -692,7 +690,7 @@ Objects::read_xrefTable(qpdf_offset_t xref_offset) | @@ -692,7 +690,7 @@ Objects::read_xrefTable(qpdf_offset_t xref_offset) | ||
| 692 | int num = 0; | 690 | int num = 0; |
| 693 | int bytes = 0; | 691 | int bytes = 0; |
| 694 | if (!parse_xrefFirst(line, obj, num, bytes)) { | 692 | if (!parse_xrefFirst(line, obj, num, bytes)) { |
| 695 | - throw qpdf.damagedPDF("xref table", "xref syntax invalid"); | 693 | + throw damagedPDF("xref table", "xref syntax invalid"); |
| 696 | } | 694 | } |
| 697 | m->file->seek(m->file->getLastOffset() + bytes, SEEK_SET); | 695 | m->file->seek(m->file->getLastOffset() + bytes, SEEK_SET); |
| 698 | for (qpdf_offset_t i = obj; i - num < obj; ++i) { | 696 | for (qpdf_offset_t i = obj; i - num < obj; ++i) { |
| @@ -705,7 +703,7 @@ Objects::read_xrefTable(qpdf_offset_t xref_offset) | @@ -705,7 +703,7 @@ Objects::read_xrefTable(qpdf_offset_t xref_offset) | ||
| 705 | int f2 = 0; | 703 | int f2 = 0; |
| 706 | char type = '\0'; | 704 | char type = '\0'; |
| 707 | if (!read_xrefEntry(f1, f2, type)) { | 705 | if (!read_xrefEntry(f1, f2, type)) { |
| 708 | - throw qpdf.damagedPDF( | 706 | + throw damagedPDF( |
| 709 | "xref table", "invalid xref entry (obj=" + std::to_string(i) + ")"); | 707 | "xref table", "invalid xref entry (obj=" + std::to_string(i) + ")"); |
| 710 | } | 708 | } |
| 711 | if (type == 'f') { | 709 | if (type == 'f') { |
| @@ -725,17 +723,17 @@ Objects::read_xrefTable(qpdf_offset_t xref_offset) | @@ -725,17 +723,17 @@ Objects::read_xrefTable(qpdf_offset_t xref_offset) | ||
| 725 | // Set offset to previous xref table if any | 723 | // Set offset to previous xref table if any |
| 726 | QPDFObjectHandle cur_trailer = m->objects.readTrailer(); | 724 | QPDFObjectHandle cur_trailer = m->objects.readTrailer(); |
| 727 | if (!cur_trailer.isDictionary()) { | 725 | if (!cur_trailer.isDictionary()) { |
| 728 | - throw qpdf.damagedPDF("", "expected trailer dictionary"); | 726 | + throw damagedPDF("", "expected trailer dictionary"); |
| 729 | } | 727 | } |
| 730 | 728 | ||
| 731 | if (!m->trailer) { | 729 | if (!m->trailer) { |
| 732 | setTrailer(cur_trailer); | 730 | setTrailer(cur_trailer); |
| 733 | 731 | ||
| 734 | if (!m->trailer.hasKey("/Size")) { | 732 | if (!m->trailer.hasKey("/Size")) { |
| 735 | - throw qpdf.damagedPDF("trailer", "trailer dictionary lacks /Size key"); | 733 | + throw damagedPDF("trailer", "trailer dictionary lacks /Size key"); |
| 736 | } | 734 | } |
| 737 | if (!m->trailer.getKey("/Size").isInteger()) { | 735 | if (!m->trailer.getKey("/Size").isInteger()) { |
| 738 | - throw qpdf.damagedPDF("trailer", "/Size key in trailer dictionary is not an integer"); | 736 | + throw damagedPDF("trailer", "/Size key in trailer dictionary is not an integer"); |
| 739 | } | 737 | } |
| 740 | } | 738 | } |
| 741 | 739 | ||
| @@ -748,14 +746,14 @@ Objects::read_xrefTable(qpdf_offset_t xref_offset) | @@ -748,14 +746,14 @@ Objects::read_xrefTable(qpdf_offset_t xref_offset) | ||
| 748 | // /Prev key instead of the xref stream's. | 746 | // /Prev key instead of the xref stream's. |
| 749 | (void)read_xrefStream(cur_trailer.getKey("/XRefStm").getIntValue()); | 747 | (void)read_xrefStream(cur_trailer.getKey("/XRefStm").getIntValue()); |
| 750 | } else { | 748 | } else { |
| 751 | - throw qpdf.damagedPDF("xref stream", xref_offset, "invalid /XRefStm"); | 749 | + throw damagedPDF("xref stream", xref_offset, "invalid /XRefStm"); |
| 752 | } | 750 | } |
| 753 | } | 751 | } |
| 754 | } | 752 | } |
| 755 | 753 | ||
| 756 | if (cur_trailer.hasKey("/Prev")) { | 754 | if (cur_trailer.hasKey("/Prev")) { |
| 757 | if (!cur_trailer.getKey("/Prev").isInteger()) { | 755 | if (!cur_trailer.getKey("/Prev").isInteger()) { |
| 758 | - throw qpdf.damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer"); | 756 | + throw damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer"); |
| 759 | } | 757 | } |
| 760 | return cur_trailer.getKey("/Prev").getIntValue(); | 758 | return cur_trailer.getKey("/Prev").getIntValue(); |
| 761 | } | 759 | } |
| @@ -781,7 +779,7 @@ Objects::read_xrefStream(qpdf_offset_t xref_offset, bool in_stream_recovery) | @@ -781,7 +779,7 @@ Objects::read_xrefStream(qpdf_offset_t xref_offset, bool in_stream_recovery) | ||
| 781 | } | 779 | } |
| 782 | } | 780 | } |
| 783 | 781 | ||
| 784 | - throw qpdf.damagedPDF("", xref_offset, "xref not found"); | 782 | + throw damagedPDF("", xref_offset, "xref not found"); |
| 785 | return 0; // unreachable | 783 | return 0; // unreachable |
| 786 | } | 784 | } |
| 787 | 785 | ||
| @@ -912,7 +910,7 @@ Objects::processXRefStream( | @@ -912,7 +910,7 @@ Objects::processXRefStream( | ||
| 912 | qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj, bool in_stream_recovery) | 910 | qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj, bool in_stream_recovery) |
| 913 | { | 911 | { |
| 914 | auto damaged = [this, xref_offset](std::string_view msg) -> QPDFExc { | 912 | auto damaged = [this, xref_offset](std::string_view msg) -> QPDFExc { |
| 915 | - return qpdf.damagedPDF("xref stream", xref_offset, msg.data()); | 913 | + return damagedPDF("xref stream", xref_offset, msg.data()); |
| 916 | }; | 914 | }; |
| 917 | 915 | ||
| 918 | auto dict = xref_obj.getDict(); | 916 | auto dict = xref_obj.getDict(); |
| @@ -932,7 +930,7 @@ Objects::processXRefStream( | @@ -932,7 +930,7 @@ Objects::processXRefStream( | ||
| 932 | if (expected_size > actual_size) { | 930 | if (expected_size > actual_size) { |
| 933 | throw x; | 931 | throw x; |
| 934 | } else { | 932 | } else { |
| 935 | - qpdf.warn(x); | 933 | + warn(x); |
| 936 | } | 934 | } |
| 937 | } | 935 | } |
| 938 | 936 | ||
| @@ -992,7 +990,7 @@ Objects::processXRefStream( | @@ -992,7 +990,7 @@ Objects::processXRefStream( | ||
| 992 | 990 | ||
| 993 | if (dict.hasKey("/Prev")) { | 991 | if (dict.hasKey("/Prev")) { |
| 994 | if (!dict.getKey("/Prev").isInteger()) { | 992 | if (!dict.getKey("/Prev").isInteger()) { |
| 995 | - throw qpdf.damagedPDF( | 993 | + throw damagedPDF( |
| 996 | "xref stream", "/Prev key in xref stream dictionary is not an integer"); | 994 | "xref stream", "/Prev key in xref stream dictionary is not an integer"); |
| 997 | } | 995 | } |
| 998 | return dict.getKey("/Prev").getIntValue(); | 996 | return dict.getKey("/Prev").getIntValue(); |
| @@ -1030,13 +1028,13 @@ Objects::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2) | @@ -1030,13 +1028,13 @@ Objects::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2) | ||
| 1030 | 1028 | ||
| 1031 | if (f0 == 2) { | 1029 | if (f0 == 2) { |
| 1032 | if (f1 == obj) { | 1030 | if (f1 == obj) { |
| 1033 | - qpdf.warn(qpdf.damagedPDF( | ||
| 1034 | - "xref stream", "self-referential object stream " + std::to_string(obj))); | 1031 | + warn( |
| 1032 | + damagedPDF("xref stream", "self-referential object stream " + std::to_string(obj))); | ||
| 1035 | return; | 1033 | return; |
| 1036 | } | 1034 | } |
| 1037 | if (f1 > m->xref_table_max_id) { | 1035 | if (f1 > m->xref_table_max_id) { |
| 1038 | // ignore impossibly large object stream ids | 1036 | // ignore impossibly large object stream ids |
| 1039 | - qpdf.warn(qpdf.damagedPDF( | 1037 | + warn(damagedPDF( |
| 1040 | "xref stream", | 1038 | "xref stream", |
| 1041 | "object stream id " + std::to_string(f1) + " for object " + std::to_string(obj) + | 1039 | "object stream id " + std::to_string(f1) + " for object " + std::to_string(obj) + |
| 1042 | " is impossibly large")); | 1040 | " is impossibly large")); |
| @@ -1061,8 +1059,7 @@ Objects::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2) | @@ -1061,8 +1059,7 @@ Objects::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2) | ||
| 1061 | break; | 1059 | break; |
| 1062 | 1060 | ||
| 1063 | default: | 1061 | default: |
| 1064 | - throw qpdf.damagedPDF( | ||
| 1065 | - "xref stream", "unknown xref stream entry type " + std::to_string(f0)); | 1062 | + throw damagedPDF("xref stream", "unknown xref stream entry type " + std::to_string(f0)); |
| 1066 | break; | 1063 | break; |
| 1067 | } | 1064 | } |
| 1068 | } | 1065 | } |
| @@ -1182,9 +1179,9 @@ Objects::readTrailer() | @@ -1182,9 +1179,9 @@ Objects::readTrailer() | ||
| 1182 | if (empty) { | 1179 | if (empty) { |
| 1183 | // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in | 1180 | // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in |
| 1184 | // actual PDF files and Adobe Reader appears to ignore them. | 1181 | // actual PDF files and Adobe Reader appears to ignore them. |
| 1185 | - qpdf.warn(qpdf.damagedPDF("trailer", "empty object treated as null")); | 1182 | + warn(damagedPDF("trailer", "empty object treated as null")); |
| 1186 | } else if (object.isDictionary() && m->objects.readToken(*m->file).isWord("stream")) { | 1183 | } else if (object.isDictionary() && m->objects.readToken(*m->file).isWord("stream")) { |
| 1187 | - qpdf.warn(qpdf.damagedPDF("trailer", m->file->tell(), "stream keyword found in trailer")); | 1184 | + warn(damagedPDF("trailer", m->file->tell(), "stream keyword found in trailer")); |
| 1188 | } | 1185 | } |
| 1189 | // Override last_offset so that it points to the beginning of the object we just read | 1186 | // Override last_offset so that it points to the beginning of the object we just read |
| 1190 | m->file->setLastOffset(offset); | 1187 | m->file->setLastOffset(offset); |
| @@ -1210,8 +1207,7 @@ Objects::readObject(std::string const& description, QPDFObjGen og) | @@ -1210,8 +1207,7 @@ Objects::readObject(std::string const& description, QPDFObjGen og) | ||
| 1210 | if (empty) { | 1207 | if (empty) { |
| 1211 | // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in | 1208 | // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in |
| 1212 | // actual PDF files and Adobe Reader appears to ignore them. | 1209 | // actual PDF files and Adobe Reader appears to ignore them. |
| 1213 | - qpdf.warn( | ||
| 1214 | - qpdf.damagedPDF(*m->file, m->file->getLastOffset(), "empty object treated as null")); | 1210 | + warn(damagedPDF(*m->file, m->file->getLastOffset(), "empty object treated as null")); |
| 1215 | return object; | 1211 | return object; |
| 1216 | } | 1212 | } |
| 1217 | auto token = readToken(*m->file); | 1213 | auto token = readToken(*m->file); |
| @@ -1220,7 +1216,7 @@ Objects::readObject(std::string const& description, QPDFObjGen og) | @@ -1220,7 +1216,7 @@ Objects::readObject(std::string const& description, QPDFObjGen og) | ||
| 1220 | token = readToken(*m->file); | 1216 | token = readToken(*m->file); |
| 1221 | } | 1217 | } |
| 1222 | if (!token.isWord("endobj")) { | 1218 | if (!token.isWord("endobj")) { |
| 1223 | - qpdf.warn(qpdf.damagedPDF("expected endobj")); | 1219 | + warn(damagedPDF("expected endobj")); |
| 1224 | } | 1220 | } |
| 1225 | return object; | 1221 | return object; |
| 1226 | } | 1222 | } |
| @@ -1241,9 +1237,9 @@ Objects::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offse | @@ -1241,9 +1237,9 @@ Objects::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offse | ||
| 1241 | 1237 | ||
| 1242 | if (!length_obj.isInteger()) { | 1238 | if (!length_obj.isInteger()) { |
| 1243 | if (length_obj.null()) { | 1239 | if (length_obj.null()) { |
| 1244 | - throw qpdf.damagedPDF(offset, "stream dictionary lacks /Length key"); | 1240 | + throw damagedPDF(offset, "stream dictionary lacks /Length key"); |
| 1245 | } | 1241 | } |
| 1246 | - throw qpdf.damagedPDF(offset, "/Length key in stream dictionary is not an integer"); | 1242 | + throw damagedPDF(offset, "/Length key in stream dictionary is not an integer"); |
| 1247 | } | 1243 | } |
| 1248 | 1244 | ||
| 1249 | length = toS(length_obj.getUIntValue()); | 1245 | length = toS(length_obj.getUIntValue()); |
| @@ -1251,11 +1247,11 @@ Objects::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offse | @@ -1251,11 +1247,11 @@ Objects::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offse | ||
| 1251 | m->file->seek(stream_offset, SEEK_SET); | 1247 | m->file->seek(stream_offset, SEEK_SET); |
| 1252 | m->file->seek(toO(length), SEEK_CUR); | 1248 | m->file->seek(toO(length), SEEK_CUR); |
| 1253 | if (!readToken(*m->file).isWord("endstream")) { | 1249 | if (!readToken(*m->file).isWord("endstream")) { |
| 1254 | - throw qpdf.damagedPDF("expected endstream"); | 1250 | + throw damagedPDF("expected endstream"); |
| 1255 | } | 1251 | } |
| 1256 | } catch (QPDFExc& e) { | 1252 | } catch (QPDFExc& e) { |
| 1257 | if (m->attempt_recovery) { | 1253 | if (m->attempt_recovery) { |
| 1258 | - qpdf.warn(e); | 1254 | + warn(e); |
| 1259 | length = recoverStreamLength(m->file, og, stream_offset); | 1255 | length = recoverStreamLength(m->file, og, stream_offset); |
| 1260 | } else { | 1256 | } else { |
| 1261 | throw; | 1257 | throw; |
| @@ -1295,7 +1291,7 @@ Objects::validateStreamLineEnd(QPDFObjectHandle& object, QPDFObjGen og, qpdf_off | @@ -1295,7 +1291,7 @@ Objects::validateStreamLineEnd(QPDFObjectHandle& object, QPDFObjGen og, qpdf_off | ||
| 1295 | // Treat the \r by itself as the whitespace after endstream and start reading | 1291 | // Treat the \r by itself as the whitespace after endstream and start reading |
| 1296 | // stream data in spite of not having seen a newline. | 1292 | // stream data in spite of not having seen a newline. |
| 1297 | m->file->unreadCh(ch); | 1293 | m->file->unreadCh(ch); |
| 1298 | - qpdf.warn(qpdf.damagedPDF( | 1294 | + warn(damagedPDF( |
| 1299 | m->file->tell(), "stream keyword followed by carriage return only")); | 1295 | m->file->tell(), "stream keyword followed by carriage return only")); |
| 1300 | } | 1296 | } |
| 1301 | } | 1297 | } |
| @@ -1303,12 +1299,11 @@ Objects::validateStreamLineEnd(QPDFObjectHandle& object, QPDFObjGen og, qpdf_off | @@ -1303,12 +1299,11 @@ Objects::validateStreamLineEnd(QPDFObjectHandle& object, QPDFObjGen og, qpdf_off | ||
| 1303 | } | 1299 | } |
| 1304 | if (!util::is_space(ch)) { | 1300 | if (!util::is_space(ch)) { |
| 1305 | m->file->unreadCh(ch); | 1301 | m->file->unreadCh(ch); |
| 1306 | - qpdf.warn(qpdf.damagedPDF( | 1302 | + warn(damagedPDF( |
| 1307 | m->file->tell(), "stream keyword not followed by proper line terminator")); | 1303 | m->file->tell(), "stream keyword not followed by proper line terminator")); |
| 1308 | return; | 1304 | return; |
| 1309 | } | 1305 | } |
| 1310 | - qpdf.warn( | ||
| 1311 | - qpdf.damagedPDF(m->file->tell(), "stream keyword followed by extraneous whitespace")); | 1306 | + warn(damagedPDF(m->file->tell(), "stream keyword followed by extraneous whitespace")); |
| 1312 | } | 1307 | } |
| 1313 | } | 1308 | } |
| 1314 | 1309 | ||
| @@ -1319,7 +1314,7 @@ Objects::readObjectInStream(is::OffsetBuffer& input, int stream_id, int obj_id) | @@ -1319,7 +1314,7 @@ Objects::readObjectInStream(is::OffsetBuffer& input, int stream_id, int obj_id) | ||
| 1319 | if (empty) { | 1314 | if (empty) { |
| 1320 | // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in | 1315 | // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in |
| 1321 | // actual PDF files and Adobe Reader appears to ignore them. | 1316 | // actual PDF files and Adobe Reader appears to ignore them. |
| 1322 | - qpdf.warn(QPDFExc( | 1317 | + warn(QPDFExc( |
| 1323 | qpdf_e_damaged_pdf, | 1318 | qpdf_e_damaged_pdf, |
| 1324 | m->file->getName() + " object stream " + std::to_string(stream_id), | 1319 | m->file->getName() + " object stream " + std::to_string(stream_id), |
| 1325 | +"object " + std::to_string(obj_id) + " 0, offset " + | 1320 | +"object " + std::to_string(obj_id) + " 0, offset " + |
| @@ -1347,7 +1342,7 @@ Objects::recoverStreamLength( | @@ -1347,7 +1342,7 @@ Objects::recoverStreamLength( | ||
| 1347 | std::shared_ptr<InputSource> input, QPDFObjGen og, qpdf_offset_t stream_offset) | 1342 | std::shared_ptr<InputSource> input, QPDFObjGen og, qpdf_offset_t stream_offset) |
| 1348 | { | 1343 | { |
| 1349 | // Try to reconstruct stream length by looking for endstream or endobj | 1344 | // Try to reconstruct stream length by looking for endstream or endobj |
| 1350 | - qpdf.warn(qpdf.damagedPDF(*input, stream_offset, "attempting to recover stream length")); | 1345 | + warn(damagedPDF(*input, stream_offset, "attempting to recover stream length")); |
| 1351 | 1346 | ||
| 1352 | PatternFinder ef(qpdf, &QPDF::findEndstream); | 1347 | PatternFinder ef(qpdf, &QPDF::findEndstream); |
| 1353 | size_t length = 0; | 1348 | size_t length = 0; |
| @@ -1386,10 +1381,10 @@ Objects::recoverStreamLength( | @@ -1386,10 +1381,10 @@ Objects::recoverStreamLength( | ||
| 1386 | } | 1381 | } |
| 1387 | 1382 | ||
| 1388 | if (length == 0) { | 1383 | if (length == 0) { |
| 1389 | - qpdf.warn(qpdf.damagedPDF( | 1384 | + warn(damagedPDF( |
| 1390 | *input, stream_offset, "unable to recover stream data; treating stream as empty")); | 1385 | *input, stream_offset, "unable to recover stream data; treating stream as empty")); |
| 1391 | } else { | 1386 | } else { |
| 1392 | - qpdf.warn(qpdf.damagedPDF( | 1387 | + warn(damagedPDF( |
| 1393 | *input, stream_offset, "recovered stream length: " + std::to_string(length))); | 1388 | *input, stream_offset, "recovered stream length: " + std::to_string(length))); |
| 1394 | } | 1389 | } |
| 1395 | 1390 | ||
| @@ -1409,24 +1404,24 @@ Objects::read_object_start(qpdf_offset_t offset) | @@ -1409,24 +1404,24 @@ Objects::read_object_start(qpdf_offset_t offset) | ||
| 1409 | QPDFTokenizer::Token tobjid = readToken(*m->file); | 1404 | QPDFTokenizer::Token tobjid = readToken(*m->file); |
| 1410 | bool objidok = tobjid.isInteger(); | 1405 | bool objidok = tobjid.isInteger(); |
| 1411 | if (!objidok) { | 1406 | if (!objidok) { |
| 1412 | - throw qpdf.damagedPDF(offset, "expected n n obj"); | 1407 | + throw damagedPDF(offset, "expected n n obj"); |
| 1413 | } | 1408 | } |
| 1414 | QPDFTokenizer::Token tgen = readToken(*m->file); | 1409 | QPDFTokenizer::Token tgen = readToken(*m->file); |
| 1415 | bool genok = tgen.isInteger(); | 1410 | bool genok = tgen.isInteger(); |
| 1416 | if (!genok) { | 1411 | if (!genok) { |
| 1417 | - throw qpdf.damagedPDF(offset, "expected n n obj"); | 1412 | + throw damagedPDF(offset, "expected n n obj"); |
| 1418 | } | 1413 | } |
| 1419 | QPDFTokenizer::Token tobj = readToken(*m->file); | 1414 | QPDFTokenizer::Token tobj = readToken(*m->file); |
| 1420 | 1415 | ||
| 1421 | bool objok = tobj.isWord("obj"); | 1416 | bool objok = tobj.isWord("obj"); |
| 1422 | 1417 | ||
| 1423 | if (!objok) { | 1418 | if (!objok) { |
| 1424 | - throw qpdf.damagedPDF(offset, "expected n n obj"); | 1419 | + throw damagedPDF(offset, "expected n n obj"); |
| 1425 | } | 1420 | } |
| 1426 | int objid = QUtil::string_to_int(tobjid.getValue().c_str()); | 1421 | int objid = QUtil::string_to_int(tobjid.getValue().c_str()); |
| 1427 | int generation = QUtil::string_to_int(tgen.getValue().c_str()); | 1422 | int generation = QUtil::string_to_int(tgen.getValue().c_str()); |
| 1428 | if (objid == 0) { | 1423 | if (objid == 0) { |
| 1429 | - throw qpdf.damagedPDF(offset, "object with ID 0"); | 1424 | + throw damagedPDF(offset, "object with ID 0"); |
| 1430 | } | 1425 | } |
| 1431 | return {objid, generation}; | 1426 | return {objid, generation}; |
| 1432 | } | 1427 | } |
| @@ -1447,20 +1442,20 @@ Objects::readObjectAtOffset( | @@ -1447,20 +1442,20 @@ Objects::readObjectAtOffset( | ||
| 1447 | // "0000000000 00000 n", which is not correct, but it won't hurt anything for us to ignore | 1442 | // "0000000000 00000 n", which is not correct, but it won't hurt anything for us to ignore |
| 1448 | // these. | 1443 | // these. |
| 1449 | if (offset == 0) { | 1444 | if (offset == 0) { |
| 1450 | - qpdf.warn(qpdf.damagedPDF(-1, "object has offset 0")); | 1445 | + warn(damagedPDF(-1, "object has offset 0")); |
| 1451 | return; | 1446 | return; |
| 1452 | } | 1447 | } |
| 1453 | 1448 | ||
| 1454 | try { | 1449 | try { |
| 1455 | og = read_object_start(offset); | 1450 | og = read_object_start(offset); |
| 1456 | if (exp_og != og) { | 1451 | if (exp_og != og) { |
| 1457 | - QPDFExc e = qpdf.damagedPDF(offset, "expected " + exp_og.unparse(' ') + " obj"); | 1452 | + QPDFExc e = damagedPDF(offset, "expected " + exp_og.unparse(' ') + " obj"); |
| 1458 | if (try_recovery) { | 1453 | if (try_recovery) { |
| 1459 | // Will be retried below | 1454 | // Will be retried below |
| 1460 | throw e; | 1455 | throw e; |
| 1461 | } else { | 1456 | } else { |
| 1462 | // We can try reading the object anyway even if the ID doesn't match. | 1457 | // We can try reading the object anyway even if the ID doesn't match. |
| 1463 | - qpdf.warn(e); | 1458 | + warn(e); |
| 1464 | } | 1459 | } |
| 1465 | } | 1460 | } |
| 1466 | } catch (QPDFExc& e) { | 1461 | } catch (QPDFExc& e) { |
| @@ -1474,7 +1469,7 @@ Objects::readObjectAtOffset( | @@ -1474,7 +1469,7 @@ Objects::readObjectAtOffset( | ||
| 1474 | readObjectAtOffset(false, new_offset, description, exp_og); | 1469 | readObjectAtOffset(false, new_offset, description, exp_og); |
| 1475 | return; | 1470 | return; |
| 1476 | } | 1471 | } |
| 1477 | - qpdf.warn(qpdf.damagedPDF( | 1472 | + warn(damagedPDF( |
| 1478 | "", | 1473 | "", |
| 1479 | -1, | 1474 | -1, |
| 1480 | ("object " + exp_og.unparse(' ') + | 1475 | ("object " + exp_og.unparse(' ') + |
| @@ -1493,7 +1488,7 @@ Objects::readObjectAtOffset( | @@ -1493,7 +1488,7 @@ Objects::readObjectAtOffset( | ||
| 1493 | while (true) { | 1488 | while (true) { |
| 1494 | char ch; | 1489 | char ch; |
| 1495 | if (!m->file->read(&ch, 1)) { | 1490 | if (!m->file->read(&ch, 1)) { |
| 1496 | - throw qpdf.damagedPDF(m->file->tell(), "EOF after endobj"); | 1491 | + throw damagedPDF(m->file->tell(), "EOF after endobj"); |
| 1497 | } | 1492 | } |
| 1498 | if (!isspace(static_cast<unsigned char>(ch))) { | 1493 | if (!isspace(static_cast<unsigned char>(ch))) { |
| 1499 | m->file->seek(-1, SEEK_CUR); | 1494 | m->file->seek(-1, SEEK_CUR); |
| @@ -1552,7 +1547,7 @@ Objects::readObjectAtOffset( | @@ -1552,7 +1547,7 @@ Objects::readObjectAtOffset( | ||
| 1552 | while (true) { | 1547 | while (true) { |
| 1553 | char ch; | 1548 | char ch; |
| 1554 | if (!m->file->read(&ch, 1)) { | 1549 | if (!m->file->read(&ch, 1)) { |
| 1555 | - throw qpdf.damagedPDF(m->file->tell(), "EOF after endobj"); | 1550 | + throw damagedPDF(m->file->tell(), "EOF after endobj"); |
| 1556 | } | 1551 | } |
| 1557 | if (!isspace(static_cast<unsigned char>(ch))) { | 1552 | if (!isspace(static_cast<unsigned char>(ch))) { |
| 1558 | m->file->seek(-1, SEEK_CUR); | 1553 | m->file->seek(-1, SEEK_CUR); |
| @@ -1574,7 +1569,7 @@ Objects::resolve(QPDFObjGen og) | @@ -1574,7 +1569,7 @@ Objects::resolve(QPDFObjGen og) | ||
| 1574 | if (m->resolving.contains(og)) { | 1569 | if (m->resolving.contains(og)) { |
| 1575 | // This can happen if an object references itself directly or indirectly in some key that | 1570 | // This can happen if an object references itself directly or indirectly in some key that |
| 1576 | // has to be resolved during object parsing, such as stream length. | 1571 | // has to be resolved during object parsing, such as stream length. |
| 1577 | - qpdf.warn(qpdf.damagedPDF("", "loop detected resolving object " + og.unparse(' '))); | 1572 | + warn(damagedPDF("", "loop detected resolving object " + og.unparse(' '))); |
| 1578 | updateCache(og, QPDFObject::create<QPDF_Null>(), -1, -1); | 1573 | updateCache(og, QPDFObject::create<QPDF_Null>(), -1, -1); |
| 1579 | return m->obj_cache[og].object; | 1574 | return m->obj_cache[og].object; |
| 1580 | } | 1575 | } |
| @@ -1594,13 +1589,13 @@ Objects::resolve(QPDFObjGen og) | @@ -1594,13 +1589,13 @@ Objects::resolve(QPDFObjGen og) | ||
| 1594 | break; | 1589 | break; |
| 1595 | 1590 | ||
| 1596 | default: | 1591 | default: |
| 1597 | - throw qpdf.damagedPDF( | 1592 | + throw damagedPDF( |
| 1598 | "", -1, ("object " + og.unparse('/') + " has unexpected xref entry type")); | 1593 | "", -1, ("object " + og.unparse('/') + " has unexpected xref entry type")); |
| 1599 | } | 1594 | } |
| 1600 | } catch (QPDFExc& e) { | 1595 | } catch (QPDFExc& e) { |
| 1601 | - qpdf.warn(e); | 1596 | + warn(e); |
| 1602 | } catch (std::exception& e) { | 1597 | } catch (std::exception& e) { |
| 1603 | - qpdf.warn(qpdf.damagedPDF( | 1598 | + warn(damagedPDF( |
| 1604 | "", -1, ("object " + og.unparse('/') + ": error reading object: " + e.what()))); | 1599 | "", -1, ("object " + og.unparse('/') + ": error reading object: " + e.what()))); |
| 1605 | } | 1600 | } |
| 1606 | } | 1601 | } |
| @@ -1636,7 +1631,7 @@ Objects::resolveObjectsInStream(int obj_stream_number) | @@ -1636,7 +1631,7 @@ Objects::resolveObjectsInStream(int obj_stream_number) | ||
| 1636 | // Force resolution of object stream | 1631 | // Force resolution of object stream |
| 1637 | Stream obj_stream = qpdf.getObject(obj_stream_number, 0); | 1632 | Stream obj_stream = qpdf.getObject(obj_stream_number, 0); |
| 1638 | if (!obj_stream) { | 1633 | if (!obj_stream) { |
| 1639 | - throw qpdf.damagedPDF( | 1634 | + throw damagedPDF( |
| 1640 | "object " + std::to_string(obj_stream_number) + " 0", | 1635 | "object " + std::to_string(obj_stream_number) + " 0", |
| 1641 | "supposed object stream " + std::to_string(obj_stream_number) + " is not a stream"); | 1636 | "supposed object stream " + std::to_string(obj_stream_number) + " is not a stream"); |
| 1642 | } | 1637 | } |
| @@ -1649,7 +1644,7 @@ Objects::resolveObjectsInStream(int obj_stream_number) | @@ -1649,7 +1644,7 @@ Objects::resolveObjectsInStream(int obj_stream_number) | ||
| 1649 | 1644 | ||
| 1650 | QPDFObjectHandle dict = obj_stream.getDict(); | 1645 | QPDFObjectHandle dict = obj_stream.getDict(); |
| 1651 | if (!dict.isDictionaryOfType("/ObjStm")) { | 1646 | if (!dict.isDictionaryOfType("/ObjStm")) { |
| 1652 | - qpdf.warn(qpdf.damagedPDF( | 1647 | + warn(damagedPDF( |
| 1653 | "object " + std::to_string(obj_stream_number) + " 0", | 1648 | "object " + std::to_string(obj_stream_number) + " 0", |
| 1654 | "supposed object stream " + std::to_string(obj_stream_number) + " has wrong type")); | 1649 | "supposed object stream " + std::to_string(obj_stream_number) + " has wrong type")); |
| 1655 | } | 1650 | } |
| @@ -1657,7 +1652,7 @@ Objects::resolveObjectsInStream(int obj_stream_number) | @@ -1657,7 +1652,7 @@ Objects::resolveObjectsInStream(int obj_stream_number) | ||
| 1657 | unsigned int n{0}; | 1652 | unsigned int n{0}; |
| 1658 | int first{0}; | 1653 | int first{0}; |
| 1659 | if (!(dict.getKey("/N").getValueAsUInt(n) && dict.getKey("/First").getValueAsInt(first))) { | 1654 | if (!(dict.getKey("/N").getValueAsUInt(n) && dict.getKey("/First").getValueAsInt(first))) { |
| 1660 | - throw qpdf.damagedPDF( | 1655 | + throw damagedPDF( |
| 1661 | "object " + std::to_string(obj_stream_number) + " 0", | 1656 | "object " + std::to_string(obj_stream_number) + " 0", |
| 1662 | "object stream " + std::to_string(obj_stream_number) + " has incorrect keys"); | 1657 | "object stream " + std::to_string(obj_stream_number) + " has incorrect keys"); |
| 1663 | } | 1658 | } |
| @@ -1674,7 +1669,7 @@ Objects::resolveObjectsInStream(int obj_stream_number) | @@ -1674,7 +1669,7 @@ Objects::resolveObjectsInStream(int obj_stream_number) | ||
| 1674 | auto b_start = stream_data.data(); | 1669 | auto b_start = stream_data.data(); |
| 1675 | 1670 | ||
| 1676 | if (first >= end_offset) { | 1671 | if (first >= end_offset) { |
| 1677 | - throw qpdf.damagedPDF( | 1672 | + throw damagedPDF( |
| 1678 | "object " + std::to_string(obj_stream_number) + " 0", | 1673 | "object " + std::to_string(obj_stream_number) + " 0", |
| 1679 | "object stream " + std::to_string(obj_stream_number) + " has invalid /First entry"); | 1674 | "object stream " + std::to_string(obj_stream_number) + " has invalid /First entry"); |
| 1680 | } | 1675 | } |
| @@ -1694,17 +1689,17 @@ Objects::resolveObjectsInStream(int obj_stream_number) | @@ -1694,17 +1689,17 @@ Objects::resolveObjectsInStream(int obj_stream_number) | ||
| 1694 | long long offset = QUtil::string_to_int(toffset.getValue().c_str()); | 1689 | long long offset = QUtil::string_to_int(toffset.getValue().c_str()); |
| 1695 | 1690 | ||
| 1696 | if (num == obj_stream_number) { | 1691 | if (num == obj_stream_number) { |
| 1697 | - qpdf.warn(damaged(num, id_offset, "object stream claims to contain itself")); | 1692 | + warn(damaged(num, id_offset, "object stream claims to contain itself")); |
| 1698 | continue; | 1693 | continue; |
| 1699 | } | 1694 | } |
| 1700 | 1695 | ||
| 1701 | if (num < 1) { | 1696 | if (num < 1) { |
| 1702 | - qpdf.warn(damaged(num, id_offset, "object id is invalid"s)); | 1697 | + warn(damaged(num, id_offset, "object id is invalid"s)); |
| 1703 | continue; | 1698 | continue; |
| 1704 | } | 1699 | } |
| 1705 | 1700 | ||
| 1706 | if (offset <= last_offset) { | 1701 | if (offset <= last_offset) { |
| 1707 | - qpdf.warn(damaged( | 1702 | + warn(damaged( |
| 1708 | num, | 1703 | num, |
| 1709 | input.getLastOffset(), | 1704 | input.getLastOffset(), |
| 1710 | "offset " + std::to_string(offset) + | 1705 | "offset " + std::to_string(offset) + |
| @@ -1718,7 +1713,7 @@ Objects::resolveObjectsInStream(int obj_stream_number) | @@ -1718,7 +1713,7 @@ Objects::resolveObjectsInStream(int obj_stream_number) | ||
| 1718 | } | 1713 | } |
| 1719 | 1714 | ||
| 1720 | if (first + offset >= end_offset) { | 1715 | if (first + offset >= end_offset) { |
| 1721 | - qpdf.warn(damaged( | 1716 | + warn(damaged( |
| 1722 | num, input.getLastOffset(), "offset " + std::to_string(offset) + " is too large")); | 1717 | num, input.getLastOffset(), "offset " + std::to_string(offset) + " is too large")); |
| 1723 | continue; | 1718 | continue; |
| 1724 | } | 1719 | } |
| @@ -1934,7 +1929,7 @@ Objects::tableSize() | @@ -1934,7 +1929,7 @@ Objects::tableSize() | ||
| 1934 | // Temporary fix. Long-term solution is | 1929 | // Temporary fix. Long-term solution is |
| 1935 | // - QPDFObjGen to enforce objgens are valid and sensible | 1930 | // - QPDFObjGen to enforce objgens are valid and sensible |
| 1936 | // - xref table and obj cache to protect against insertion of impossibly large obj ids | 1931 | // - xref table and obj cache to protect against insertion of impossibly large obj ids |
| 1937 | - qpdf.stopOnError("Impossibly large object id encountered."); | 1932 | + stopOnError("Impossibly large object id encountered."); |
| 1938 | } | 1933 | } |
| 1939 | if (max_obj < 1.1 * std::max(toI(m->obj_cache.size()), max_xref)) { | 1934 | if (max_obj < 1.1 * std::max(toI(m->obj_cache.size()), max_xref)) { |
| 1940 | return toS(++max_obj); | 1935 | return toS(++max_obj); |
libqpdf/QPDF_optimization.cc
| @@ -218,7 +218,7 @@ Pages ::pushInheritedAttributesToPageInternal( | @@ -218,7 +218,7 @@ Pages ::pushInheritedAttributesToPageInternal( | ||
| 218 | // Warn when flattening, but not if the key is at the top level (i.e. "/Parent" not | 218 | // Warn when flattening, but not if the key is at the top level (i.e. "/Parent" not |
| 219 | // set), as we don't change these; but flattening removes intermediate /Pages nodes. | 219 | // set), as we don't change these; but flattening removes intermediate /Pages nodes. |
| 220 | if (warn_skipped_keys && cur_pages.hasKey("/Parent")) { | 220 | if (warn_skipped_keys && cur_pages.hasKey("/Parent")) { |
| 221 | - qpdf.warn( | 221 | + warn( |
| 222 | qpdf_e_pages, | 222 | qpdf_e_pages, |
| 223 | "Pages object: object " + cur_pages.id_gen().unparse(' '), | 223 | "Pages object: object " + cur_pages.id_gen().unparse(' '), |
| 224 | 0, | 224 | 0, |
libqpdf/qpdf/QPDF_private.hh
| @@ -322,6 +322,36 @@ class QPDF::Doc | @@ -322,6 +322,36 @@ class QPDF::Doc | ||
| 322 | { | 322 | { |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | + void stopOnError(std::string const& message); | ||
| 326 | + void warn(QPDFExc const& e); | ||
| 327 | + void warn( | ||
| 328 | + qpdf_error_code_e error_code, | ||
| 329 | + std::string const& object, | ||
| 330 | + qpdf_offset_t offset, | ||
| 331 | + std::string const& message); | ||
| 332 | + | ||
| 333 | + static QPDFExc damagedPDF( | ||
| 334 | + InputSource& input, | ||
| 335 | + std::string const& object, | ||
| 336 | + qpdf_offset_t offset, | ||
| 337 | + std::string const& message); | ||
| 338 | + QPDFExc | ||
| 339 | + damagedPDF(InputSource& input, qpdf_offset_t offset, std::string const& message) const; | ||
| 340 | + QPDFExc damagedPDF( | ||
| 341 | + std::string const& object, qpdf_offset_t offset, std::string const& message) const; | ||
| 342 | + QPDFExc damagedPDF(std::string const& object, std::string const& message) const; | ||
| 343 | + QPDFExc damagedPDF(qpdf_offset_t offset, std::string const& message) const; | ||
| 344 | + QPDFExc damagedPDF(std::string const& message) const; | ||
| 345 | + | ||
| 346 | + void | ||
| 347 | + no_ci_stop_if( | ||
| 348 | + bool condition, std::string const& message, std::string const& context = {}) const | ||
| 349 | + { | ||
| 350 | + if (condition) { | ||
| 351 | + throw damagedPDF(context, message); | ||
| 352 | + } | ||
| 353 | + } | ||
| 354 | + | ||
| 325 | protected: | 355 | protected: |
| 326 | QPDF& qpdf; | 356 | QPDF& qpdf; |
| 327 | QPDF::Members* m; | 357 | QPDF::Members* m; |
| @@ -989,13 +1019,4 @@ inline QPDF::Doc::Objects::Foreign::Copier::Copier(QPDF& qpdf) : | @@ -989,13 +1019,4 @@ inline QPDF::Doc::Objects::Foreign::Copier::Copier(QPDF& qpdf) : | ||
| 989 | { | 1019 | { |
| 990 | } | 1020 | } |
| 991 | 1021 | ||
| 992 | -// Throw a generic exception for unusual error conditions that do not be covered during CI testing. | ||
| 993 | -inline void | ||
| 994 | -QPDF::no_ci_stop_if(bool condition, std::string const& message, std::string const& context) | ||
| 995 | -{ | ||
| 996 | - if (condition) { | ||
| 997 | - throw damagedPDF(context, message); | ||
| 998 | - } | ||
| 999 | -} | ||
| 1000 | - | ||
| 1001 | #endif // QPDF_PRIVATE_HH | 1022 | #endif // QPDF_PRIVATE_HH |