From 0ae344d002755d1f218fe4fbd818a814bc3ebdbc Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sun, 23 Jun 2019 14:31:35 -0400 Subject: [PATCH] Add fuzzers to exercise specific pipeline classes --- .gitignore | 1 - fuzz/ascii85_fuzzer.cc | 52 +++++++++++++ .../a0113b6bc9b18c0d120bdf79f10a4928dc6fc908 | 43 +++++++++++ fuzz/build.mk | 16 +++- fuzz/dct_fuzzer.cc | 52 +++++++++++++ .../4255e4e69733376eb7681d1aad44d39252ae4a75 | Bin 0 -> 2951 bytes fuzz/flate_fuzzer.cc | 52 +++++++++++++ .../de72db41219fa2fc5113b4634a7c2bb437d48938 | Bin 0 -> 147 bytes fuzz/hex_fuzzer.cc | 52 +++++++++++++ .../1c43fc2a41e55a9e1cecce2013254b632f5afac4 | 70 ++++++++++++++++++ fuzz/lzw_fuzzer.cc | 52 +++++++++++++ .../d95e70dee47eb085060d6e01534f7c3c17e3ae56 | Bin 0 -> 38344 bytes fuzz/pngpredictor_fuzzer.cc | 52 +++++++++++++ .../70ade8c4239563ca806d2d297a4e48099156c450 | Bin 0 -> 1056 bytes fuzz/qtest/fuzz.test | 61 +++++++++++---- fuzz/runlength_fuzzer.cc | 52 +++++++++++++ .../075cf1366a47754ffc0f59797ecd60eb221c8a0d | Bin 0 -> 275 bytes .../0928451e068252ef8f3d1878a5c1f81b86dc9eb8 | 1 + .../4354588bbf0979da3b05eb7cadd13b74141ad49c | 1 + .../4ffb8ea47113554fbac0d5ba533838e3dd7aa23a | 1 + .../b307a53d7d354fe2dbd4b13dca43ddacfaea91e1 | 1 + .../c78ebd3c85a39a596d9f5cfd2b8d240bc1b9c125 | 1 + fuzz/tiffpredictor_fuzzer.cc | 53 +++++++++++++ .../9c848d2c383eb26a026d0b4428421c5e43c2d7b9 | Bin 0 -> 48 bytes 24 files changed, 594 insertions(+), 19 deletions(-) create mode 100644 fuzz/ascii85_fuzzer.cc create mode 100644 fuzz/ascii85_fuzzer_seed_corpus/a0113b6bc9b18c0d120bdf79f10a4928dc6fc908 create mode 100644 fuzz/dct_fuzzer.cc create mode 100644 fuzz/dct_fuzzer_seed_corpus/4255e4e69733376eb7681d1aad44d39252ae4a75 create mode 100644 fuzz/flate_fuzzer.cc create mode 100644 fuzz/flate_fuzzer_seed_corpus/de72db41219fa2fc5113b4634a7c2bb437d48938 create mode 100644 fuzz/hex_fuzzer.cc create mode 100644 fuzz/hex_fuzzer_seed_corpus/1c43fc2a41e55a9e1cecce2013254b632f5afac4 create mode 100644 fuzz/lzw_fuzzer.cc create mode 100644 fuzz/lzw_fuzzer_seed_corpus/d95e70dee47eb085060d6e01534f7c3c17e3ae56 create mode 100644 fuzz/pngpredictor_fuzzer.cc create mode 100644 fuzz/pngpredictor_fuzzer_seed_corpus/70ade8c4239563ca806d2d297a4e48099156c450 create mode 100644 fuzz/runlength_fuzzer.cc create mode 100644 fuzz/runlength_fuzzer_seed_corpus/075cf1366a47754ffc0f59797ecd60eb221c8a0d create mode 100644 fuzz/runlength_fuzzer_seed_corpus/0928451e068252ef8f3d1878a5c1f81b86dc9eb8 create mode 100644 fuzz/runlength_fuzzer_seed_corpus/4354588bbf0979da3b05eb7cadd13b74141ad49c create mode 100644 fuzz/runlength_fuzzer_seed_corpus/4ffb8ea47113554fbac0d5ba533838e3dd7aa23a create mode 100644 fuzz/runlength_fuzzer_seed_corpus/b307a53d7d354fe2dbd4b13dca43ddacfaea91e1 create mode 100644 fuzz/runlength_fuzzer_seed_corpus/c78ebd3c85a39a596d9f5cfd2b8d240bc1b9c125 create mode 100644 fuzz/tiffpredictor_fuzzer.cc create mode 100644 fuzz/tiffpredictor_fuzzer_seed_corpus/9c848d2c383eb26a026d0b4428421c5e43c2d7b9 diff --git a/.gitignore b/.gitignore index d938c24c..2eb7fe16 100644 --- a/.gitignore +++ b/.gitignore @@ -25,5 +25,4 @@ manual/html.xsl manual/print.xsl qpdf/build/ zlib-flate/build/ -fuzz/qpdf_fuzzer_seed_corpus/ distribution/ diff --git a/fuzz/ascii85_fuzzer.cc b/fuzz/ascii85_fuzzer.cc new file mode 100644 index 00000000..40422e5b --- /dev/null +++ b/fuzz/ascii85_fuzzer.cc @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +class FuzzHelper +{ + public: + FuzzHelper(unsigned char const* data, size_t size); + void run(); + + private: + void doChecks(); + + unsigned char const* data; + size_t size; +}; + +FuzzHelper::FuzzHelper(unsigned char const* data, size_t size) : + data(data), + size(size) +{ +} + +void +FuzzHelper::doChecks() +{ + Pl_Discard discard; + Pl_ASCII85Decoder p("decode", &discard); + p.write(const_cast(data), size); + p.finish(); +} + +void +FuzzHelper::run() +{ + try + { + doChecks(); + } + catch (std::runtime_error const& e) + { + std::cerr << "runtime_error: " << e.what() << std::endl; + } +} + +extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size) +{ + FuzzHelper f(data, size); + f.run(); + return 0; +} diff --git a/fuzz/ascii85_fuzzer_seed_corpus/a0113b6bc9b18c0d120bdf79f10a4928dc6fc908 b/fuzz/ascii85_fuzzer_seed_corpus/a0113b6bc9b18c0d120bdf79f10a4928dc6fc908 new file mode 100644 index 00000000..0237ac51 --- /dev/null +++ b/fuzz/ascii85_fuzzer_seed_corpus/a0113b6bc9b18c0d120bdf79f10a4928dc6fc908 @@ -0,0 +1,43 @@ +70!<9iWTSm7KiWTSm7fWNCiWTSm8,rWHiWTSm8H8`MiWTSm8cSiRiWTSm +9)nrWiWTSm9E5&\iWTSm9`P/aiWTSm:&k8fiWTSm:B1AkiWTSm:]LJpiWTSm +;#gSuiWTSm;?-]%iWTSm;ZHf*iWTSm;uco/iWTSm<<*#4iWTSmiWTSm=9&>CiWTSm=TAGHiWTSm=o\P&M<.ZglicMP!!!"'J]"ig!!9c9E!!)4J#6=g,>KOe_2$i.E#lc1Zi<9Je!!!$!,nT#= +#\X23#\ZI(!!)7krVuot-+)V7#\Za0!!)7[rVuot-+Mn; +#\[$8!!)7KrVuot-+r1?#\[<@!!)7;rVuot-,AIC#\[TH!!)7+rVuot-,eaG +#\[lP!!)6prVuot--5$K#\\/X!!)6`rVuot--Y#\X2>!!)9Aqu?]r,o#>B#\XJF!!)91qu?]r,oGVF +#\XbN!!)9!qu?]r,oknJ#\Y%V!!)8fqu?]r,p;1N#\Y=^!!)8Vqu?]r,p_IR +#\YUf!!)8Fqu?]r,q.aV#\Ymn!!)86qu?]r,qS$Z#\Z1!!!)8&qu?]r,r"<^ +#\ZI)!!)7kqu?]r,rFTb#\Za1!!)7[qu?]r,rjlf#\[$9!!)7Kqu?]r,s:/j +#\[QcOH>QcOH>Q(M<0BV#_5(Ziro\gF:@ITK>7VbLuJRDs3dTsiWT +UG&;APTlc'+Liro\hahs3?M<0BV#b_gf"UKgtF:u(`!!!"Q^iTn'"=+Q:"UP +.Tahs4%OH>QcOH>QcOH>Q(M<0BV(lLfgMbOV<:]u[VM+f0#a$_0]zM,Y`'M$ +,*fQi6sbahs4"F=$ufM<0BV#`0NHMd6aJF1!q`($, +La&Mb=>67L4oV%#\-p0uu*'$.'3I^kop\iW4rW,`0m+FNP$V=!!!"m+QWb4 +7M_,io18?,Mb`F=$ufKYWH+F:?1n~>trailing garbage diff --git a/fuzz/build.mk b/fuzz/build.mk index 43b65906..44db5326 100644 --- a/fuzz/build.mk +++ b/fuzz/build.mk @@ -1,7 +1,16 @@ # This directory contains support for Google's oss-fuzz project. See # https://github.com/google/oss-fuzz/tree/master/projects/qpdf -FUZZERS = qpdf_fuzzer +FUZZERS = \ + qpdf_fuzzer \ + ascii85_fuzzer \ + dct_fuzzer \ + flate_fuzzer \ + hex_fuzzer \ + lzw_fuzzer \ + pngpredictor_fuzzer \ + runlength_fuzzer \ + tiffpredictor_fuzzer DEFAULT_FUZZ_RUNNER := standalone_fuzz_target_runner OBJ_DEFAULT_FUZZ := fuzz/$(OUTPUT_DIR)/$(DEFAULT_FUZZ_RUNNER).$(OBJ) @@ -9,7 +18,8 @@ OBJ_DEFAULT_FUZZ := fuzz/$(OUTPUT_DIR)/$(DEFAULT_FUZZ_RUNNER).$(OBJ) BINS_fuzz = $(foreach B,$(FUZZERS),fuzz/$(OUTPUT_DIR)/$(call binname,$(B))) TARGETS_fuzz = $(OBJ_DEFAULT_FUZZ) $(BINS_fuzz) fuzz_corpus -INCLUDES_fuzz = include +# Fuzzers test private classes too, so we need libqpdf in the include path +INCLUDES_fuzz = include libqpdf # LIB_FUZZING_ENGINE is overridden by oss-fuzz LIB_FUZZING_ENGINE ?= $(OBJ_DEFAULT_FUZZ) @@ -129,6 +139,8 @@ install_fuzz: $(STATIC_BINS_fuzz) fi; \ if test -d fuzz/$(OUTPUT_DIR)/$${B}_seed_corpus; then \ (cd fuzz/$(OUTPUT_DIR)/$${B}_seed_corpus; zip -q -r $(OUT)/$${B}_seed_corpus.zip .); \ + elif test -d fuzz/$${B}_seed_corpus; then \ + (cd fuzz/$${B}_seed_corpus; zip -q -r $(OUT)/$${B}_seed_corpus.zip .); \ fi; \ done diff --git a/fuzz/dct_fuzzer.cc b/fuzz/dct_fuzzer.cc new file mode 100644 index 00000000..450b4df2 --- /dev/null +++ b/fuzz/dct_fuzzer.cc @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +class FuzzHelper +{ + public: + FuzzHelper(unsigned char const* data, size_t size); + void run(); + + private: + void doChecks(); + + unsigned char const* data; + size_t size; +}; + +FuzzHelper::FuzzHelper(unsigned char const* data, size_t size) : + data(data), + size(size) +{ +} + +void +FuzzHelper::doChecks() +{ + Pl_Discard discard; + Pl_DCT p("decode", &discard); + p.write(const_cast(data), size); + p.finish(); +} + +void +FuzzHelper::run() +{ + try + { + doChecks(); + } + catch (std::runtime_error const& e) + { + std::cerr << "runtime_error: " << e.what() << std::endl; + } +} + +extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size) +{ + FuzzHelper f(data, size); + f.run(); + return 0; +} diff --git a/fuzz/dct_fuzzer_seed_corpus/4255e4e69733376eb7681d1aad44d39252ae4a75 b/fuzz/dct_fuzzer_seed_corpus/4255e4e69733376eb7681d1aad44d39252ae4a75 new file mode 100644 index 0000000000000000000000000000000000000000..3e76ddcff6d3252a5b30bcfc71a5555afbe6bc4f GIT binary patch literal 2951 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<&w6?W(baqXeJZ0*%=`&`|TC{k{(q+q6 ztX#Ee^OmjKw(r=v>(JpNM~@vpaq`rq%U7;myME*5t%r{uKY9A>`HPpYK7RWA(=m|@`bJenM-lOIQBa-2(r0&z4sj+Tzp Wsb5D+N9t4$qm?yPS}WoIZvp_`7$Kzq literal 0 HcmV?d00001 diff --git a/fuzz/flate_fuzzer.cc b/fuzz/flate_fuzzer.cc new file mode 100644 index 00000000..700f7cd7 --- /dev/null +++ b/fuzz/flate_fuzzer.cc @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +class FuzzHelper +{ + public: + FuzzHelper(unsigned char const* data, size_t size); + void run(); + + private: + void doChecks(); + + unsigned char const* data; + size_t size; +}; + +FuzzHelper::FuzzHelper(unsigned char const* data, size_t size) : + data(data), + size(size) +{ +} + +void +FuzzHelper::doChecks() +{ + Pl_Discard discard; + Pl_Flate p("decode", &discard, Pl_Flate::a_deflate); + p.write(const_cast(data), size); + p.finish(); +} + +void +FuzzHelper::run() +{ + try + { + doChecks(); + } + catch (std::runtime_error const& e) + { + std::cerr << "runtime_error: " << e.what() << std::endl; + } +} + +extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size) +{ + FuzzHelper f(data, size); + f.run(); + return 0; +} diff --git a/fuzz/flate_fuzzer_seed_corpus/de72db41219fa2fc5113b4634a7c2bb437d48938 b/fuzz/flate_fuzzer_seed_corpus/de72db41219fa2fc5113b4634a7c2bb437d48938 new file mode 100644 index 0000000000000000000000000000000000000000..79b2da1bb621aa5f4e71817ee1c41b4eb767f9e7 GIT binary patch literal 147 zcmb=J^Y-9I-Ub5(<_)&>Mh1?7fmh$}Y(DW#f&m6T)JMXY3;_!4aJI+^W;mPGh!MtK k;9v%0GKieuhO=3Vm|$#&#uykAXreisEpmcAT0DRg06nr4`2YX_ literal 0 HcmV?d00001 diff --git a/fuzz/hex_fuzzer.cc b/fuzz/hex_fuzzer.cc new file mode 100644 index 00000000..b1ad2199 --- /dev/null +++ b/fuzz/hex_fuzzer.cc @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +class FuzzHelper +{ + public: + FuzzHelper(unsigned char const* data, size_t size); + void run(); + + private: + void doChecks(); + + unsigned char const* data; + size_t size; +}; + +FuzzHelper::FuzzHelper(unsigned char const* data, size_t size) : + data(data), + size(size) +{ +} + +void +FuzzHelper::doChecks() +{ + Pl_Discard discard; + Pl_ASCIIHexDecoder p("decode", &discard); + p.write(const_cast(data), size); + p.finish(); +} + +void +FuzzHelper::run() +{ + try + { + doChecks(); + } + catch (std::runtime_error const& e) + { + std::cerr << "runtime_error: " << e.what() << std::endl; + } +} + +extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size) +{ + FuzzHelper f(data, size); + f.run(); + return 0; +} diff --git a/fuzz/hex_fuzzer_seed_corpus/1c43fc2a41e55a9e1cecce2013254b632f5afac4 b/fuzz/hex_fuzzer_seed_corpus/1c43fc2a41e55a9e1cecce2013254b632f5afac4 new file mode 100644 index 00000000..9721a35a --- /dev/null +++ b/fuzz/hex_fuzzer_seed_corpus/1c43fc2a41e55a9e1cecce2013254b632f5afac4 @@ -0,0 +1,70 @@ +45000028e20508074600002ce205080747000030e205080748000034e20 +5080749000038e20508074a00003ce20508074b000040e20508074c0000 +44e20508074d000048e20508074e00004ce20508074f000050e20508075 +0000054e205080751000058e20508075200005ce205080753000060e205 +080754000064e205080755000068e20508075600006ce20508075700007 +0e205080758000074e205080759000078e20508075a00005589e55383ec +04e8000000005b81c3b44c01008b93f8ffffff85d27405e8de000000e83 +5060000e840070100585bc9c3ff3508e10508ff250ce1050800000000ff +2510e105086800000000e9e0ffffffff2514e105086808000000e9d0fff +fffff2518e105086810000000e9c0ffffffff251ce105086818000000e9 +b0ffffffff2520e105086820000000e9a0ffffffff2524e105086828000 +000e990ffffffff2528e105086830000000e980ffffffff252ce1050868 +38000000e970ffffffff2530e105086840000000e960ffffffff2534e10 +5086848000000e950ffffffff2538e105086850000000e940ffffffff25 +3ce105086858000000e930ffffffff2540e105086860000000e920fffff +fff2544e105086868000000e910ffffffff2548e105086870000000e900 +ffffffff254ce105086878000000e9f0feffffff2550e10508688000000 +0e9e0feffffff2554e105086888000000e9d0feffffff2558e105086890 +000000e9c0feffffff255ce105086898000000e9b0feffffff2560e1050 +868a0000000e9a0feffffff2564e1050868a8000000e990feffffff2568 +e1050868b0000000e980feffffff256ce1050868b8000000e970fefffff +f2570e1050868c0000000e960feffffff2574e1050868c8000000e950fe +ffffff2578e1050868d0000000e940feffffff257ce1050868d8000000e +930feffffff2580e1050868e0000000e920feffffff2584e1050868e800 +0000e910feffffff2588e1050868f0000000e900feffffff258ce105086 +8f8000000e9f0fdffffff2590e105086800010000e9e0fdffffff2594e1 +05086808010000e9d0fdffffff2598e105086810010000e9c0fdffffff2 +59ce105086818010000e9b0fdffffff25a0e105086820010000e9a0fdff +ffff25a4e105086828010000e990fdffffff25a8e105086830010000e98 +0fdffffff25ace105086838010000e970fdffffff25b0e1050868400100 +00e960fdffffff25b4e105086848010000e950fdffffff25b8e10508685 +0010000e940fdffffff25bce105086858010000e930fdffffff25c0e105 +086860010000e920fdffffff25c4e105086868010000e910fdffffff25c +8e105086870010000e900fdffffff25cce105086878010000e9f0fcffff +FF25D0E105086880010000E9E0FCFFFFFF25D4E105086888010000E9D0F +CFFFFFF25D8E105086890010000E9C0FCFFFFFF25DCE105086898010000 +E9B0FCFFFFFF25E0E1050868A0010000E9A0FCFFFFFF25E4E1050868A80 +10000E990FCFFFFFF25E8E1050868B0010000E980FCFFFFFF25ECE10508 +68B8010000E970FCFFFFFF25F0E1050868C0010000E960FCFFFFFF25F4E +1050868C8010000E950FCFFFFFF25F8E1050868D0010000E940FCFFFFFF +25FCE1050868D801 0000E930FCFFFFFF2500E2050868E0010000E920FCF +FFFFF2504E2050868E8010000E910FCFFFFFF2508E2050868F0010000E9 +00FCFFFFFF250CE2050868F8010000E9F0FBFFFFFF2510E205086800020 +000E9E0FBFFFFFF2514E205086808020000E9D0FBFFFFFF2518E2050868 +10020000E9C0FBFFFFFF251CE205086818020000E9B0FBFFFFFF2520E20 +5086820020000E9A0FBFFFFFF2524E205086828020000E990FBFFFFFF25 +28E2050 8683 0020000E980FBFFFFFF252CE205086838020000E970FBFFF +FFF2530E205086840020000E960FBFFFFFF2534E205086848020000E950 +FBFFFFFF2538E205086850020000E940FBFFFFFF253CE20508685802000 +0E930FBFFFFFF2540E205086860020000E920FBFFFFFF2544E205086868 +020000E910FBFFFFFF2548E205086870020000E900FBFFFFFF254CE2050 +86878020000E9F0FAFFFFFF2550E205086880020000E9E0FAFFFFFF2554 +e205086888020000e9d0faffffff2558e205086890020000e9c0fafffff +f255ce205086898020000e9b0faffffff2560e2050868a0020000e9a0fa +ffffff2564e2050868a8020000e990faffffff2568e2050868b0020000e +980faffffff256ce2050868b8020000e970faffffff2570e2050868c002 +0000e960faffffff2574e2050868c8020000e950faffffff2578e205086 +8d0020000e940faffff00000000000000000000000031ed5e89e183e4f0 +50545268009b050868109b0508515668f0e60408e893fbfffff49090909 +0909090909090909090905589e583ec08803dc8e3050800740ceb1c83c0 +04a388e20508ffd2a188e205088b1085d275ebc605c8e3050801c9c3905 +589e583ec08a110e0050885c07412b80000000085c07409c7042410e005 +08ffd0c9c3909090909090909090909090905589e583ec188b45088b4d0 +c8b50048b00894c2408c744240c0000000089542404890424e897fe0000 +c9c3908d7426005589e583ec08891c248b5d0c897424048b75088b4b048 +b56048b06330331d131d209c1751a8b4b088b46088b5b0c8b560c31c831 +da09d00f94c089c283e2018b1c2489d08b74240489ec5dc38d742600a12 +0e505085589e585c075088b4508a320e505085dc38d76008dbc27000000 +00a120e505085589e585c0750da124e5050883c001a324e505085dc3908 +d7426005584c089e5740cc705>trailing farbage diff --git a/fuzz/lzw_fuzzer.cc b/fuzz/lzw_fuzzer.cc new file mode 100644 index 00000000..da31f41b --- /dev/null +++ b/fuzz/lzw_fuzzer.cc @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +class FuzzHelper +{ + public: + FuzzHelper(unsigned char const* data, size_t size); + void run(); + + private: + void doChecks(); + + unsigned char const* data; + size_t size; +}; + +FuzzHelper::FuzzHelper(unsigned char const* data, size_t size) : + data(data), + size(size) +{ +} + +void +FuzzHelper::doChecks() +{ + Pl_Discard discard; + Pl_LZWDecoder p("decode", &discard, false); + p.write(const_cast(data), size); + p.finish(); +} + +void +FuzzHelper::run() +{ + try + { + doChecks(); + } + catch (std::runtime_error const& e) + { + std::cerr << "runtime_error: " << e.what() << std::endl; + } +} + +extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size) +{ + FuzzHelper f(data, size); + f.run(); + return 0; +} diff --git a/fuzz/lzw_fuzzer_seed_corpus/d95e70dee47eb085060d6e01534f7c3c17e3ae56 b/fuzz/lzw_fuzzer_seed_corpus/d95e70dee47eb085060d6e01534f7c3c17e3ae56 new file mode 100644 index 0000000000000000000000000000000000000000..5109c45a6fcc985c1ff5b0152809728fa0710e89 GIT binary patch literal 38344 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 G!v6ufpH%4p literal 0 HcmV?d00001 diff --git a/fuzz/pngpredictor_fuzzer.cc b/fuzz/pngpredictor_fuzzer.cc new file mode 100644 index 00000000..8a8c5d7d --- /dev/null +++ b/fuzz/pngpredictor_fuzzer.cc @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +class FuzzHelper +{ + public: + FuzzHelper(unsigned char const* data, size_t size); + void run(); + + private: + void doChecks(); + + unsigned char const* data; + size_t size; +}; + +FuzzHelper::FuzzHelper(unsigned char const* data, size_t size) : + data(data), + size(size) +{ +} + +void +FuzzHelper::doChecks() +{ + Pl_Discard discard; + Pl_PNGFilter p("decode", &discard, Pl_PNGFilter::a_decode, 32, 1, 8); + p.write(const_cast(data), size); + p.finish(); +} + +void +FuzzHelper::run() +{ + try + { + doChecks(); + } + catch (std::runtime_error const& e) + { + std::cerr << "runtime_error: " << e.what() << std::endl; + } +} + +extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size) +{ + FuzzHelper f(data, size); + f.run(); + return 0; +} diff --git a/fuzz/pngpredictor_fuzzer_seed_corpus/70ade8c4239563ca806d2d297a4e48099156c450 b/fuzz/pngpredictor_fuzzer_seed_corpus/70ade8c4239563ca806d2d297a4e48099156c450 new file mode 100644 index 0000000000000000000000000000000000000000..ad8c632b375e7478a72e4520bb8972e29f3edf99 GIT binary patch literal 1056 zcmaixO%8%E5QQIQXgQN-FrLB01GqC`a{3qNnHF9`FP`<^fOS4Bn9k*s%b>&@0nnSjC17Zu&%O zh?MkJ2X;UVMDMsne@+`3AlgF%K$`#`(czQ|V#6W18WM)97c@8vDI@@Fy+B#$EAg?R z>Zt(^;c3u@Q#xY$E*#W_maED->#o>4(Sjoa@fV0SUw4Ou5CJ2giM34uO-xP4C-t0> VrUZz3 $qpdf_n_files], + ['ascii85' => 1], + ['dct' => 1], + ['flate' => 1], + ['hex' => 1], + ['lzw' => 1], + ['pngpredictor' => 1], + ['runlength' => 6], + ['tiffpredictor' => 1], + ); + +my $n_tests = 0; +# One test for each directory for file count, two tests for each file +# in each directory +foreach my $d (@fuzzers) { - die "wrong number of files seen in fuzz.test"; + $n_tests += 1 + (2 * $d->[1]); } -foreach my $f (@files) +foreach my $d (@fuzzers) { - my $sum = basename($f); - $td->runtest("checksum $sum", - {$td->STRING => get_sha1_checksum($f)}, - {$td->STRING => $sum}); - $td->runtest("fuzz check $sum", - {$td->COMMAND => "qpdf_fuzzer $f"}, - {$td->REGEXP => ".*$f successful\n", - $td->EXIT_STATUS => 0}, + my $k = $d->[0]; + my $dir = "../${k}_fuzzer_seed_corpus"; + if (! -d $dir) + { + $dir = "../build/${k}_fuzzer_seed_corpus"; + } + my @files = glob("$dir/*"); + $td->runtest("file count for $dir", + {$td->STRING => scalar(@files) . "\n"}, + {$td->STRING => $d->[1] . "\n"}, $td->NORMALIZE_NEWLINES); + + foreach my $f (@files) + { + my $sum = basename($f); + $td->runtest("$k checksum $sum", + {$td->STRING => get_sha1_checksum($f)}, + {$td->STRING => $sum}); + $td->runtest("$k fuzz check $sum", + {$td->COMMAND => "${k}_fuzzer $f"}, + {$td->REGEXP => ".*$f successful\n", + $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + } } -$td->report(2 * $n_files); +$td->report($n_tests); sub get_sha1_checksum { diff --git a/fuzz/runlength_fuzzer.cc b/fuzz/runlength_fuzzer.cc new file mode 100644 index 00000000..bacd3dd8 --- /dev/null +++ b/fuzz/runlength_fuzzer.cc @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +class FuzzHelper +{ + public: + FuzzHelper(unsigned char const* data, size_t size); + void run(); + + private: + void doChecks(); + + unsigned char const* data; + size_t size; +}; + +FuzzHelper::FuzzHelper(unsigned char const* data, size_t size) : + data(data), + size(size) +{ +} + +void +FuzzHelper::doChecks() +{ + Pl_Discard discard; + Pl_RunLength p("decode", &discard, Pl_RunLength::a_decode); + p.write(const_cast(data), size); + p.finish(); +} + +void +FuzzHelper::run() +{ + try + { + doChecks(); + } + catch (std::runtime_error const& e) + { + std::cerr << "runtime_error: " << e.what() << std::endl; + } +} + +extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size) +{ + FuzzHelper f(data, size); + f.run(); + return 0; +} diff --git a/fuzz/runlength_fuzzer_seed_corpus/075cf1366a47754ffc0f59797ecd60eb221c8a0d b/fuzz/runlength_fuzzer_seed_corpus/075cf1366a47754ffc0f59797ecd60eb221c8a0d new file mode 100644 index 0000000000000000000000000000000000000000..0fac6b58e7918b596eaa12acd0e5e31017200e62 GIT binary patch literal 275 zcmV+u0qp(+VPa!sWr25xcLHW-X#aYD009C61O)~M2nh-c3=Iws5D^j+6crX17#SKH z9337XAR!_nBqb&%C@Cr{EG;fCFflSSG&MFiI5|2yJUu=?KtV!7L`6nNNJ&adOifNt zP*GA-R8>}2SXo+ITwPvYU}0ioWMyV&XlZI|Y;A6DaB*^Tbai%jczJqze0_d@e}I94 zgM@{Khlq)ai;RtqkC2g)la!T~mzbHFo1C4VpP-?lqok##r>Lo_tE{cAuduPQv$VCg zx45~wyS%-=zrex5!^FkL$H>Xb%goKr&(P7*)6~`0*Vx(G+uYsW-{9fm+J3B@9^>R^Yr!h_xSnx`~3a>|A6gihnN5W literal 0 HcmV?d00001 diff --git a/fuzz/runlength_fuzzer_seed_corpus/0928451e068252ef8f3d1878a5c1f81b86dc9eb8 b/fuzz/runlength_fuzzer_seed_corpus/0928451e068252ef8f3d1878a5c1f81b86dc9eb8 new file mode 100644 index 00000000..fc26c6f6 --- /dev/null +++ b/fuzz/runlength_fuzzer_seed_corpus/0928451e068252ef8f3d1878a5c1f81b86dc9eb8 @@ -0,0 +1 @@ +čwüqrstv€ \ No newline at end of file diff --git a/fuzz/runlength_fuzzer_seed_corpus/4354588bbf0979da3b05eb7cadd13b74141ad49c b/fuzz/runlength_fuzzer_seed_corpus/4354588bbf0979da3b05eb7cadd13b74141ad49c new file mode 100644 index 00000000..0c97dde2 --- /dev/null +++ b/fuzz/runlength_fuzzer_seed_corpus/4354588bbf0979da3b05eb7cadd13b74141ad49c @@ -0,0 +1 @@ +wabababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab€ \ No newline at end of file diff --git a/fuzz/runlength_fuzzer_seed_corpus/4ffb8ea47113554fbac0d5ba533838e3dd7aa23a b/fuzz/runlength_fuzzer_seed_corpus/4ffb8ea47113554fbac0d5ba533838e3dd7aa23a new file mode 100644 index 00000000..2a645eef --- /dev/null +++ b/fuzz/runlength_fuzzer_seed_corpus/4ffb8ea47113554fbac0d5ba533838e3dd7aa23a @@ -0,0 +1 @@ +~abababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababaűb€ \ No newline at end of file diff --git a/fuzz/runlength_fuzzer_seed_corpus/b307a53d7d354fe2dbd4b13dca43ddacfaea91e1 b/fuzz/runlength_fuzzer_seed_corpus/b307a53d7d354fe2dbd4b13dca43ddacfaea91e1 new file mode 100644 index 00000000..85bb323e --- /dev/null +++ b/fuzz/runlength_fuzzer_seed_corpus/b307a53d7d354fe2dbd4b13dca43ddacfaea91e1 @@ -0,0 +1 @@ +čwüqrstvęx€ \ No newline at end of file diff --git a/fuzz/runlength_fuzzer_seed_corpus/c78ebd3c85a39a596d9f5cfd2b8d240bc1b9c125 b/fuzz/runlength_fuzzer_seed_corpus/c78ebd3c85a39a596d9f5cfd2b8d240bc1b9c125 new file mode 100644 index 00000000..5416677b --- /dev/null +++ b/fuzz/runlength_fuzzer_seed_corpus/c78ebd3c85a39a596d9f5cfd2b8d240bc1b9c125 @@ -0,0 +1 @@ +€ \ No newline at end of file diff --git a/fuzz/tiffpredictor_fuzzer.cc b/fuzz/tiffpredictor_fuzzer.cc new file mode 100644 index 00000000..35d2f415 --- /dev/null +++ b/fuzz/tiffpredictor_fuzzer.cc @@ -0,0 +1,53 @@ +#include +#include +#include +#include + +class FuzzHelper +{ + public: + FuzzHelper(unsigned char const* data, size_t size); + void run(); + + private: + void doChecks(); + + unsigned char const* data; + size_t size; +}; + +FuzzHelper::FuzzHelper(unsigned char const* data, size_t size) : + data(data), + size(size) +{ +} + +void +FuzzHelper::doChecks() +{ + Pl_Discard discard; + Pl_TIFFPredictor p("decoder", &discard, + Pl_TIFFPredictor::a_decode, 16, 1, 8); + p.write(const_cast(data), size); + p.finish(); +} + +void +FuzzHelper::run() +{ + try + { + doChecks(); + } + catch (std::runtime_error const& e) + { + std::cerr << "runtime_error: " << e.what() << std::endl; + } +} + +extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size) +{ + FuzzHelper f(data, size); + f.run(); + return 0; +} diff --git a/fuzz/tiffpredictor_fuzzer_seed_corpus/9c848d2c383eb26a026d0b4428421c5e43c2d7b9 b/fuzz/tiffpredictor_fuzzer_seed_corpus/9c848d2c383eb26a026d0b4428421c5e43c2d7b9 new file mode 100644 index 0000000000000000000000000000000000000000..30ba8de7761b8472fae4e5856516d2dc6bcce046 GIT binary patch literal 48 WcmZQ%#1Fz5|3kpHZ{HXgnHT|Q#tK*f literal 0 HcmV?d00001