Commit f565506380efa9c2a82c7860ff6e742734419aa2
Committed by
GitHub
Merge pull request #1655 from m-holger/pa1312
Add CI test for use of a copy of a destroyed QPDFJob object
Showing
4 changed files
with
149 additions
and
25 deletions
manual/release-notes.rst
| @@ -17,8 +17,9 @@ more detail. | @@ -17,8 +17,9 @@ more detail. | ||
| 17 | 12.3.1: not yet released | 17 | 12.3.1: not yet released |
| 18 | - Bug fixes | 18 | - Bug fixes |
| 19 | 19 | ||
| 20 | - - Fix a bug causing ``QPDFJob::createQPDF`` to fail if called | ||
| 21 | - from pikepdf. | 20 | + - Fix failure of ``QPDFJob::run`` and ``QPDFJob::createQPDF`` when |
| 21 | + called with a copy of a destroyed ``QPDFJob`` object. This affects | ||
| 22 | + using the job interface from pikepdf. | ||
| 22 | 23 | ||
| 23 | 12.3.0: January 10, 2026 | 24 | 12.3.0: January 10, 2026 |
| 24 | - Release changes | 25 | - Release changes |
qpdf/qtest/qpdf/test102.pdf
0 → 100644
| 1 | +%PDF-1.3 | ||
| 2 | +%¿÷¢þ | ||
| 3 | +%QDF-1.0 | ||
| 4 | + | ||
| 5 | +%% Original object ID: 1 0 | ||
| 6 | +1 0 obj | ||
| 7 | +<< | ||
| 8 | + /Pages 2 0 R | ||
| 9 | + /Type /Catalog | ||
| 10 | +>> | ||
| 11 | +endobj | ||
| 12 | + | ||
| 13 | +%% Original object ID: 2 0 | ||
| 14 | +2 0 obj | ||
| 15 | +<< | ||
| 16 | + /Count 1 | ||
| 17 | + /Kids [ | ||
| 18 | + 3 0 R | ||
| 19 | + ] | ||
| 20 | + /Type /Pages | ||
| 21 | +>> | ||
| 22 | +endobj | ||
| 23 | + | ||
| 24 | +%% Page 1 | ||
| 25 | +%% Original object ID: 3 0 | ||
| 26 | +3 0 obj | ||
| 27 | +<< | ||
| 28 | + /Contents 4 0 R | ||
| 29 | + /MediaBox [ | ||
| 30 | + 0 | ||
| 31 | + 0 | ||
| 32 | + 612 | ||
| 33 | + 792 | ||
| 34 | + ] | ||
| 35 | + /Parent 2 0 R | ||
| 36 | + /Resources << | ||
| 37 | + /Font << | ||
| 38 | + /F1 6 0 R | ||
| 39 | + >> | ||
| 40 | + /ProcSet 7 0 R | ||
| 41 | + >> | ||
| 42 | + /Type /Page | ||
| 43 | +>> | ||
| 44 | +endobj | ||
| 45 | + | ||
| 46 | +%% Contents for page 1 | ||
| 47 | +%% Original object ID: 4 0 | ||
| 48 | +4 0 obj | ||
| 49 | +<< | ||
| 50 | + /Length 5 0 R | ||
| 51 | +>> | ||
| 52 | +stream | ||
| 53 | +BT | ||
| 54 | + /F1 24 Tf | ||
| 55 | + 72 720 Td | ||
| 56 | + (Potato) Tj | ||
| 57 | +ET | ||
| 58 | +endstream | ||
| 59 | +endobj | ||
| 60 | + | ||
| 61 | +5 0 obj | ||
| 62 | +44 | ||
| 63 | +endobj | ||
| 64 | + | ||
| 65 | +%% Original object ID: 6 0 | ||
| 66 | +6 0 obj | ||
| 67 | +<< | ||
| 68 | + /BaseFont /Helvetica | ||
| 69 | + /Encoding /WinAnsiEncoding | ||
| 70 | + /Name /F1 | ||
| 71 | + /Subtype /Type1 | ||
| 72 | + /Type /Font | ||
| 73 | +>> | ||
| 74 | +endobj | ||
| 75 | + | ||
| 76 | +%% Original object ID: 5 0 | ||
| 77 | +7 0 obj | ||
| 78 | +[ | ||
| 79 | |||
| 80 | + /Text | ||
| 81 | +] | ||
| 82 | +endobj | ||
| 83 | + | ||
| 84 | +xref | ||
| 85 | +0 8 | ||
| 86 | +0000000000 65535 f | ||
| 87 | +0000000052 00000 n | ||
| 88 | +0000000133 00000 n | ||
| 89 | +0000000242 00000 n | ||
| 90 | +0000000484 00000 n | ||
| 91 | +0000000583 00000 n | ||
| 92 | +0000000629 00000 n | ||
| 93 | +0000000774 00000 n | ||
| 94 | +trailer << | ||
| 95 | + /Root 1 0 R | ||
| 96 | + /Size 8 | ||
| 97 | + /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] | ||
| 98 | +>> | ||
| 99 | +startxref | ||
| 100 | +809 | ||
| 101 | +%%EOF |
qpdf/qtest/qpdfjob.test
| @@ -44,7 +44,7 @@ my @good_json = ( | @@ -44,7 +44,7 @@ my @good_json = ( | ||
| 44 | ["underlay-overlay-password", ""], | 44 | ["underlay-overlay-password", ""], |
| 45 | ["misc-options", ""], | 45 | ["misc-options", ""], |
| 46 | ); | 46 | ); |
| 47 | -my $n_tests = 11 + scalar(@bad_json) + (2 * scalar(@good_json)); | 47 | +my $n_tests = 13 + scalar(@bad_json) + (2 * scalar(@good_json)); |
| 48 | 48 | ||
| 49 | 49 | ||
| 50 | foreach my $i (@bad_json) | 50 | foreach my $i (@bad_json) |
| @@ -130,5 +130,13 @@ else | @@ -130,5 +130,13 @@ else | ||
| 130 | {$td->FILE => "qpdfjob-ctest-wide.pdf", $td->EXIT_STATUS => 0}); | 130 | {$td->FILE => "qpdfjob-ctest-wide.pdf", $td->EXIT_STATUS => 0}); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | +$td->runtest("Copied QPDFJob", | ||
| 134 | + {$td->COMMAND => "test_driver 102 -"}, | ||
| 135 | + {$td->STRING => "test 102 done\n", $td->EXIT_STATUS => 0}, | ||
| 136 | + $td->NORMALIZE_NEWLINES); | ||
| 137 | +$td->runtest("check output", | ||
| 138 | + {$td->FILE => "a.pdf"}, | ||
| 139 | + {$td->FILE => "test102.pdf"}); | ||
| 140 | + | ||
| 133 | cleanup(); | 141 | cleanup(); |
| 134 | $td->report($n_tests); | 142 | $td->report($n_tests); |
qpdf/test_driver.cc
| @@ -3584,6 +3584,20 @@ test_101(QPDF& pdf, char const* arg2) | @@ -3584,6 +3584,20 @@ test_101(QPDF& pdf, char const* arg2) | ||
| 3584 | test_helper_throws([](QPDF& q) { (void)QPDFPageLabelDocumentHelper::get(q); }); | 3584 | test_helper_throws([](QPDF& q) { (void)QPDFPageLabelDocumentHelper::get(q); }); |
| 3585 | } | 3585 | } |
| 3586 | 3586 | ||
| 3587 | +static void | ||
| 3588 | +test_102(QPDF& pdf, char const* arg2) | ||
| 3589 | +{ | ||
| 3590 | + // Test using a copy of a QPDFJob object after the original is destroyed | ||
| 3591 | + | ||
| 3592 | + auto j = std::make_unique<QPDFJob>(); | ||
| 3593 | + j->initializeFromJson( | ||
| 3594 | + R"({"inputFile": "minimal.pdf", "outputFile": "a.pdf", "qdf": "", "staticId": ""})"); | ||
| 3595 | + QPDFJob j2 = *j; | ||
| 3596 | + j = nullptr; | ||
| 3597 | + auto q = j2.createQPDF(); | ||
| 3598 | + j2.writeQPDF(*q); | ||
| 3599 | +} | ||
| 3600 | + | ||
| 3587 | void | 3601 | void |
| 3588 | runtest(int n, char const* filename1, char const* arg2) | 3602 | runtest(int n, char const* filename1, char const* arg2) |
| 3589 | { | 3603 | { |
| @@ -3591,7 +3605,7 @@ runtest(int n, char const* filename1, char const* arg2) | @@ -3591,7 +3605,7 @@ runtest(int n, char const* filename1, char const* arg2) | ||
| 3591 | // the test suite to see how the test is invoked to find the file | 3605 | // the test suite to see how the test is invoked to find the file |
| 3592 | // that the test is supposed to operate on. | 3606 | // that the test is supposed to operate on. |
| 3593 | 3607 | ||
| 3594 | - std::set<int> ignore_filename = {61, 62, 81, 83, 84, 85, 86, 87, 92, 95, 96, 101}; | 3608 | + std::set<int> ignore_filename = {61, 62, 81, 83, 84, 85, 86, 87, 92, 95, 96, 101, 102}; |
| 3595 | 3609 | ||
| 3596 | if (n == 0) { | 3610 | if (n == 0) { |
| 3597 | // Throw in some random test cases that don't fit anywhere | 3611 | // Throw in some random test cases that don't fit anywhere |
| @@ -3665,27 +3679,27 @@ runtest(int n, char const* filename1, char const* arg2) | @@ -3665,27 +3679,27 @@ runtest(int n, char const* filename1, char const* arg2) | ||
| 3665 | } | 3679 | } |
| 3666 | 3680 | ||
| 3667 | std::map<int, void (*)(QPDF&, char const*)> test_functions = { | 3681 | std::map<int, void (*)(QPDF&, char const*)> test_functions = { |
| 3668 | - {0, test_0_1}, {1, test_0_1}, {2, test_2}, {3, test_3}, {4, test_4}, | ||
| 3669 | - {5, test_5}, {6, test_6}, {7, test_7}, {8, test_8}, {9, test_9}, | ||
| 3670 | - {10, test_10}, {11, test_11}, {12, test_12}, {13, test_13}, {14, test_14}, | ||
| 3671 | - {15, test_15}, {16, test_16}, {17, test_17}, {18, test_18}, {19, test_19}, | ||
| 3672 | - {20, test_20}, {21, test_21}, {22, test_22}, {23, test_23}, {24, test_24}, | ||
| 3673 | - {25, test_25}, {26, test_26}, {27, test_27}, {28, test_28}, {29, test_29}, | ||
| 3674 | - {30, test_30}, {31, test_31}, {32, test_32}, {33, test_33}, {34, test_34}, | ||
| 3675 | - {35, test_35}, {36, test_36}, {37, test_37}, {38, test_38}, {39, test_39}, | ||
| 3676 | - {40, test_40}, {41, test_41}, {42, test_42}, {43, test_43}, {44, test_44}, | ||
| 3677 | - {45, test_45}, {46, test_46}, {47, test_47}, {48, test_48}, {49, test_49}, | ||
| 3678 | - {50, test_50}, {51, test_51}, {52, test_52}, {53, test_53}, {54, test_54}, | ||
| 3679 | - {55, test_55}, {56, test_56}, {57, test_57}, {58, test_58}, {59, test_59}, | ||
| 3680 | - {60, test_60}, {61, test_61}, {62, test_62}, {63, test_63}, {64, test_64}, | ||
| 3681 | - {65, test_65}, {66, test_66}, {67, test_67}, {68, test_68}, {69, test_69}, | ||
| 3682 | - {70, test_70}, {71, test_71}, {72, test_72}, {73, test_73}, {74, test_74}, | ||
| 3683 | - {75, test_75}, {76, test_76}, {77, test_77}, {78, test_78}, {79, test_79}, | ||
| 3684 | - {80, test_80}, {81, test_81}, {82, test_82}, {83, test_83}, {84, test_84}, | ||
| 3685 | - {85, test_85}, {86, test_86}, {87, test_87}, {88, test_88}, {89, test_89}, | ||
| 3686 | - {90, test_90}, {91, test_91}, {92, test_92}, {93, test_93}, {94, test_94}, | ||
| 3687 | - {95, test_95}, {96, test_96}, {97, test_97}, {98, test_98}, {99, test_99}, | ||
| 3688 | - {100, test_100}, {101, test_101}}; | 3682 | + {0, test_0_1}, {1, test_0_1}, {2, test_2}, {3, test_3}, {4, test_4}, |
| 3683 | + {5, test_5}, {6, test_6}, {7, test_7}, {8, test_8}, {9, test_9}, | ||
| 3684 | + {10, test_10}, {11, test_11}, {12, test_12}, {13, test_13}, {14, test_14}, | ||
| 3685 | + {15, test_15}, {16, test_16}, {17, test_17}, {18, test_18}, {19, test_19}, | ||
| 3686 | + {20, test_20}, {21, test_21}, {22, test_22}, {23, test_23}, {24, test_24}, | ||
| 3687 | + {25, test_25}, {26, test_26}, {27, test_27}, {28, test_28}, {29, test_29}, | ||
| 3688 | + {30, test_30}, {31, test_31}, {32, test_32}, {33, test_33}, {34, test_34}, | ||
| 3689 | + {35, test_35}, {36, test_36}, {37, test_37}, {38, test_38}, {39, test_39}, | ||
| 3690 | + {40, test_40}, {41, test_41}, {42, test_42}, {43, test_43}, {44, test_44}, | ||
| 3691 | + {45, test_45}, {46, test_46}, {47, test_47}, {48, test_48}, {49, test_49}, | ||
| 3692 | + {50, test_50}, {51, test_51}, {52, test_52}, {53, test_53}, {54, test_54}, | ||
| 3693 | + {55, test_55}, {56, test_56}, {57, test_57}, {58, test_58}, {59, test_59}, | ||
| 3694 | + {60, test_60}, {61, test_61}, {62, test_62}, {63, test_63}, {64, test_64}, | ||
| 3695 | + {65, test_65}, {66, test_66}, {67, test_67}, {68, test_68}, {69, test_69}, | ||
| 3696 | + {70, test_70}, {71, test_71}, {72, test_72}, {73, test_73}, {74, test_74}, | ||
| 3697 | + {75, test_75}, {76, test_76}, {77, test_77}, {78, test_78}, {79, test_79}, | ||
| 3698 | + {80, test_80}, {81, test_81}, {82, test_82}, {83, test_83}, {84, test_84}, | ||
| 3699 | + {85, test_85}, {86, test_86}, {87, test_87}, {88, test_88}, {89, test_89}, | ||
| 3700 | + {90, test_90}, {91, test_91}, {92, test_92}, {93, test_93}, {94, test_94}, | ||
| 3701 | + {95, test_95}, {96, test_96}, {97, test_97}, {98, test_98}, {99, test_99}, | ||
| 3702 | + {100, test_100}, {101, test_101}, {102, test_102}}; | ||
| 3689 | 3703 | ||
| 3690 | auto fn = test_functions.find(n); | 3704 | auto fn = test_functions.find(n); |
| 3691 | if (fn == test_functions.end()) { | 3705 | if (fn == test_functions.end()) { |