From ebb10f3256067c6e4ebea9a21a92d0199ac7fdf9 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Fri, 12 Jan 2024 07:11:46 -0500 Subject: Fix null pointer issue on array copy --- fuzz/CMakeLists.txt | 4 +++- fuzz/qpdf_extra/65681.fuzz | Bin 0 -> 60590 bytes fuzz/qtest/fuzz.test | 2 +- libqpdf/QPDF_Array.cc | 3 +++ qpdf/qpdf.testcov | 1 + qpdf/qtest/many-nulls.test | 6 +++++- qpdf/test_driver.cc | 12 +++++++++++- 7 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 fuzz/qpdf_extra/65681.fuzz diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt index db9bfd71..df1fa807 100644 --- a/fuzz/CMakeLists.txt +++ b/fuzz/CMakeLists.txt @@ -109,7 +109,9 @@ set(CORPUS_OTHER 28262.fuzz 30507.fuzz 37740.fuzz - 57639.fuzz) + 57639.fuzz + 65681.fuzz +) set(CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/qpdf_corpus) file(MAKE_DIRECTORY ${CORPUS_DIR}) diff --git a/fuzz/qpdf_extra/65681.fuzz b/fuzz/qpdf_extra/65681.fuzz new file mode 100644 index 00000000..7892f7c0 Binary files /dev/null and b/fuzz/qpdf_extra/65681.fuzz differ diff --git a/fuzz/qtest/fuzz.test b/fuzz/qtest/fuzz.test index 26995dac..adce995c 100644 --- a/fuzz/qtest/fuzz.test +++ b/fuzz/qtest/fuzz.test @@ -20,7 +20,7 @@ my @fuzzers = ( ['pngpredictor' => 1], ['runlength' => 6], ['tiffpredictor' => 1], - ['qpdf' => 53], # increment when adding new files + ['qpdf' => 54], # increment when adding new files ); my $n_tests = 0; diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index c8cfe110..7d6f4539 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -1,5 +1,6 @@ #include +#include #include #include @@ -74,8 +75,10 @@ QPDF_Array::copy(bool shallow) if (shallow) { return do_create(new QPDF_Array(*this)); } else { + QTC::TC("qpdf", "QPDF_Array copy", sp ? 0 : 1); if (sp) { auto* result = new QPDF_Array(); + result->sp = std::make_unique(); result->sp->size = sp->size; for (auto const& element: sp->elements) { auto const& obj = element.second; diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 397cbf97..6d0f8a4b 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -692,3 +692,4 @@ QPDF recover xref stream 0 QPDFJob misplaced page range 0 QPDFJob duplicated range 0 QPDFJob json over/under no file 0 +QPDF_Array copy 1 diff --git a/qpdf/qtest/many-nulls.test b/qpdf/qtest/many-nulls.test index 744075f0..8a723d53 100644 --- a/qpdf/qtest/many-nulls.test +++ b/qpdf/qtest/many-nulls.test @@ -29,5 +29,9 @@ $td->runtest("run check file", {$td->COMMAND => "qpdf --check a.pdf"}, {$td->FILE => "many-nulls.out", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); +$td->runtest("copy sparse array", + {$td->COMMAND => "test_driver 97 many-nulls.pdf"}, + {$td->STRING => "test 97 done\n", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); cleanup(); -$td->report(3); +$td->report(4); diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 2b8eb761..472a96a1 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -3366,6 +3366,16 @@ test_96(QPDF& pdf, char const* arg2) assert(s.unparseBinary() == ""); } +static void +test_97(QPDF& pdf, char const* arg2) +{ + // Shallow array copy. This test uses many-nulls.pdf. + auto nulls = pdf.getTrailer().getKey("/Nulls").getArrayItem(0); + assert(nulls.isArray() && nulls.getArrayNItems() > 10000); + auto nulls2 = nulls.shallowCopy(); + assert(nulls.unparse() == nulls2.unparse()); +} + void runtest(int n, char const* filename1, char const* arg2) { @@ -3467,7 +3477,7 @@ runtest(int n, char const* filename1, char const* arg2) {78, test_78}, {79, test_79}, {80, test_80}, {81, test_81}, {82, test_82}, {83, test_83}, {84, test_84}, {85, test_85}, {86, test_86}, {87, test_87}, {88, test_88}, {89, test_89}, {90, test_90}, {91, test_91}, {92, test_92}, {93, test_93}, {94, test_94}, {95, test_95}, - {96, test_96}}; + {96, test_96}, {97, test_97}}; auto fn = test_functions.find(n); if (fn == test_functions.end()) { -- cgit v1.2.3-54-g00ecf