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