From c8b42879a6d6bfa18e3ff424bbbbf3d538df4364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B6bl?= Date: Tue, 20 Aug 2024 21:40:44 +0200 Subject: [PATCH 1/5] add generic buffer with args fuzzer --- ...eric_buffer_with_args_gif_to_gif_all_pages | Bin 0 -> 817 bytes ...ric_buffer_with_args_gif_to_webp_all_pages | Bin 0 -> 823 bytes ...ic_buffer_with_args_gif_to_webp_page_three | Bin 0 -> 731 bytes .../generic_buffer_with_args_jpeg_to_png | Bin 0 -> 1005 bytes .../generic_buffer_with_args_webp_to_tiff | Bin 0 -> 662 bytes fuzz/generic_buffer_with_args_fuzzer.cc | 72 ++++++++++++++++++ fuzz/meson.build | 7 ++ 7 files changed, 79 insertions(+) create mode 100644 fuzz/common_fuzzer_corpus/generic_buffer_with_args_gif_to_gif_all_pages create mode 100644 fuzz/common_fuzzer_corpus/generic_buffer_with_args_gif_to_webp_all_pages create mode 100644 fuzz/common_fuzzer_corpus/generic_buffer_with_args_gif_to_webp_page_three create mode 100644 fuzz/common_fuzzer_corpus/generic_buffer_with_args_jpeg_to_png create mode 100644 fuzz/common_fuzzer_corpus/generic_buffer_with_args_webp_to_tiff create mode 100644 fuzz/generic_buffer_with_args_fuzzer.cc diff --git a/fuzz/common_fuzzer_corpus/generic_buffer_with_args_gif_to_gif_all_pages b/fuzz/common_fuzzer_corpus/generic_buffer_with_args_gif_to_gif_all_pages new file mode 100644 index 0000000000000000000000000000000000000000..516fbd62cd3e7dee470dfcbe09a46ccf4005fa64 GIT binary patch literal 817 zcma#fv(+_><$a`$wz zuuSA);ACiF00Bu!Nl{TzadB}zK0bbaeqLT)K|w)wc6I>)0U;qF78Vv^VPPH~9uW}{ zF)=YNE-q$fX0Se@2*v;0ey$O`v~)z6N?3=wG1kq@<+e<>k4# zxq%)B`kIZ64H!7U(BR<YM_&vmX=>sVr#6Eo0%71oLQ9$F)AC#wKdYo&P}Ya zHHqbN_jI$cOypwVWN2Xk0ZBfq(9b1xykWy-J!anEF8e26`6g9ZgM5pnrkB26`FjU!d=# zq@?8K<+-`JfgT6?nvIPO7&ySt;Nai@1`#JGr-XzA!4P0o1G;O;kATa8Os=B3tCfX3 zI2BzNuMsj<;W)^(AZRT|;}L-bfmVira2hDcmdtQD7|7JW*i>#f%B*4)Rib`t$ DD?*34 literal 0 HcmV?d00001 diff --git a/fuzz/common_fuzzer_corpus/generic_buffer_with_args_gif_to_webp_page_three b/fuzz/common_fuzzer_corpus/generic_buffer_with_args_gif_to_webp_page_three new file mode 100644 index 0000000000000000000000000000000000000000..15fdf8247ef624aefafd3ce3a466bb2efb5c2f81 GIT binary patch literal 731 zcmazpNK8+)HIC)dD^E=-h|b9`F3w3UF19TxDou^$a`$wzuuSA);ACiF00Bu!Nl{Tz zadB}zK0bbaeqLT)K|w)wc6I>)0U;qF78Vv^VPPH~9uW}{F)=YNE-q$fX0Se@2*v;0 zey$O`v~)z6N?3=wG1kq@<+e<>k4#xq%)B`kIZ64H!7U(BRMgRZ+ literal 0 HcmV?d00001 diff --git a/fuzz/common_fuzzer_corpus/generic_buffer_with_args_jpeg_to_png b/fuzz/common_fuzzer_corpus/generic_buffer_with_args_jpeg_to_png new file mode 100644 index 0000000000000000000000000000000000000000..28abdb80368d63eb8a0a73edbebbb0a9bd162273 GIT binary patch literal 1005 zcmazp&M3;v%eFO&<NBEy_tuPPHv5DoxcXNX$ts zDS>hVZOu(}QZh?2Qj2U2bdoYlQc?>_GHgwBQq$7%i%M(_4Pv?e-}wKKVUKG?W*P&7 zr>7PJ2Ll5G8-oxdGXo=#1;SE{tYA6}$d-n(PKf)jn3`AB&FaS9h1b|*;VP#|I;N;>4D%dK(z{JSR%*4XX%E|%^6~ovIz$!vMUve7&T5@$f4}C@t|nX#SbdRNkvVZTw>x9l2WQ_>Kd9_CZ=ZQ z7M51dF0O9w9-dyoA)#U65s^{JDXD4c8JStdC8cHM6_r)ZEv;?s9i3g1CQq3GGAU*RJ2VdF$b$$4{OPfBE|D`;VW$K>lK6V1{@LNMiMuAkbe-EG*0{>>z(JGL?foF37^FXviky7|5Pj zD6C}E$RXl1apA^;oXW;QA4HRiE^>*fm^@Vd2=W@(XT*7|i7cPNJ%;etEe0NDMquPI z3o_U#r;UTAJ}$H=Y30cQ|9fB*mh literal 0 HcmV?d00001 diff --git a/fuzz/common_fuzzer_corpus/generic_buffer_with_args_webp_to_tiff b/fuzz/common_fuzzer_corpus/generic_buffer_with_args_webp_to_tiff new file mode 100644 index 0000000000000000000000000000000000000000..11d8f9b60dd749cce69b2152235c839ce8e51c04 GIT binary patch literal 662 zcmazpPEO28wKa<6(ksbKON&m<&n+lQEiTT?&$G>`D%T0LH8s!yilk&Fm*f}Orsd=( zmgtmZ0=1+i<`k!bnY!hfDJ2=UhGr06MrvkyMhS>pP+63io0(!;QdF9%lbe~BSzMlx zSpw6Vlv$FJS^(5&q64(CG%vHnHZw0dL#G1Bvo$o(sf5x=ndu;>K};zq$}dPQD#-*Y zfjFQjH67?y-QtX*%)D${pd~svsb#4-wnj!e5YzMXQgw<;lQPqw?f`lww=}0DvmmDu zY-B7~kf)nl7b62hxT{k@Sb#+Y7Xt$W2N3f!Fo-iS07Vp50eJ;1409Q^1Q;Y3>?T^x za9_H3(Lw_bh7CfTX$*6XS_&AHWV=ldf8ODeCa)~P@b{wqg6vD&+(8%qI4*W>efh+v zVB0+YWnAKH)vV?_CfG$r`#k-Y7XEk9w6yPYmg;K61ngb%D&S7@%+DNalO?o%?3uR4 z+Cs#0Vb7a22ORc@&fn^DzA2=DWm~3Z2+yavHzFQeTx))!J;zeKT&kg}YH7%Cp|f(< z`}}{NnFMsHYlNrUE)ZRjna052>8SNDF}!0Lepf`LUc1H%hu1_l_-#=tOvoq+`?XJBM#z&H`YW(1nRumCD + +extern "C" int +LLVMFuzzerInitialize(int *argc, char ***argv) +{ + vips_concurrency_set(1); + return 0; +} + +static +const char* extractNextLine(const guint8 **data, size_t *size) { + char* extracted_string = nullptr; + for(size_t i = 0; i < (*size); i++) { + if((*data)[i] == '\n') { + extracted_string = (char *)g_malloc(i + 1); + memcpy(extracted_string, *data, i); + extracted_string[i] = '\0'; + *data = (*data) + i + 1; + *size = (*size) - i - 1; + break; + } + } + return (const char*)extracted_string; +} + +extern "C" int +LLVMFuzzerTestOneInput(const guint8 *data, size_t size) +{ + VipsImage *image; + void *buf; + const char *option_string, *suffix; + size_t len; + + option_string = extractNextLine(&data, &size); + if (!option_string) { + return 0; + } + suffix = extractNextLine(&data, &size); + if (!suffix) { + g_free((void*)option_string); + return 0; + } + + if (!(image = vips_image_new_from_buffer(data, size, option_string, nullptr))) { + g_free((void*)option_string); + g_free((void*)suffix); + return 0; + } + + if (image->Xsize > 100 || + image->Ysize > 100 || + image->Bands > 4) { + g_object_unref(image); + g_free((void*)option_string); + g_free((void*)suffix); + return 0; + } + + if (vips_image_write_to_buffer(image, suffix, &buf, &len, nullptr)) { + g_object_unref(image); + g_free((void*)option_string); + g_free((void*)suffix); + return 0; + } + + g_free(buf); + g_free((void*)option_string); + g_free((void*)suffix); + g_object_unref(image); + + return 0; +} diff --git a/fuzz/meson.build b/fuzz/meson.build index f1ecf92c45..a5dd7978b5 100644 --- a/fuzz/meson.build +++ b/fuzz/meson.build @@ -97,6 +97,13 @@ foreach fuzz_basename, fuzz_save_suffix : fuzz_save_buffer_progs ) endforeach + +fuzz_execs += executable('generic_buffer_with_args_fuzzer', + 'generic_buffer_with_args_fuzzer.cc', + dependencies: [libvips_dep, fuzz_deps], + link_args: fuzz_ldflags, +) + # If the fuzzing engine is not OSS-Fuzz, build the unit tests to be run on CI if fuzzing_engine != 'oss-fuzz' test_fuzz = configure_file( From 0c80427af748f16a1daa085c79586da3670e3764 Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Thu, 22 Aug 2024 21:56:17 +0200 Subject: [PATCH 2/5] Simplify --- fuzz/generic_buffer_with_args_fuzzer.cc | 66 ++++++++++++++----------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/fuzz/generic_buffer_with_args_fuzzer.cc b/fuzz/generic_buffer_with_args_fuzzer.cc index 75ec0b8352..0e3253bf7e 100644 --- a/fuzz/generic_buffer_with_args_fuzzer.cc +++ b/fuzz/generic_buffer_with_args_fuzzer.cc @@ -1,5 +1,7 @@ #include +#define MAX_ARG_LEN 4096 // =VIPS_PATH_MAX + extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { @@ -7,20 +9,18 @@ LLVMFuzzerInitialize(int *argc, char ***argv) return 0; } -static -const char* extractNextLine(const guint8 **data, size_t *size) { - char* extracted_string = nullptr; - for(size_t i = 0; i < (*size); i++) { - if((*data)[i] == '\n') { - extracted_string = (char *)g_malloc(i + 1); - memcpy(extracted_string, *data, i); - extracted_string[i] = '\0'; - *data = (*data) + i + 1; - *size = (*size) - i - 1; - break; - } - } - return (const char*)extracted_string; +static char * +ExtractLine(const guint8 *data, size_t size, size_t *n) +{ + const guint8 *end; + + end = static_cast( + memchr(data, '\n', VIPS_MIN(size, MAX_ARG_LEN))); + if (end == nullptr) + return nullptr; + + *n = end - data; + return g_strndup(reinterpret_cast(data), *n); } extern "C" int @@ -28,44 +28,50 @@ LLVMFuzzerTestOneInput(const guint8 *data, size_t size) { VipsImage *image; void *buf; - const char *option_string, *suffix; - size_t len; + char *option_string, *suffix; + size_t len, n; - option_string = extractNextLine(&data, &size); - if (!option_string) { + option_string = ExtractLine(data, size, &n); + if (option_string == nullptr) return 0; - } - suffix = extractNextLine(&data, &size); - if (!suffix) { - g_free((void*)option_string); + + data += n + 1; + size -= n + 1; + + suffix = ExtractLine(data, size, &n); + if (suffix == nullptr) { + g_free(option_string); return 0; } + data += n + 1; + size -= n + 1; + if (!(image = vips_image_new_from_buffer(data, size, option_string, nullptr))) { - g_free((void*)option_string); - g_free((void*)suffix); + g_free(option_string); + g_free(suffix); return 0; } + // We're done with option_string, free early. + g_free(option_string); + if (image->Xsize > 100 || image->Ysize > 100 || image->Bands > 4) { g_object_unref(image); - g_free((void*)option_string); - g_free((void*)suffix); + g_free(suffix); return 0; } if (vips_image_write_to_buffer(image, suffix, &buf, &len, nullptr)) { g_object_unref(image); - g_free((void*)option_string); - g_free((void*)suffix); + g_free(suffix); return 0; } g_free(buf); - g_free((void*)option_string); - g_free((void*)suffix); + g_free(suffix); g_object_unref(image); return 0; From 1228b78aaaf2e0eb435a5427be0c4dd30b05d698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B6bl?= Date: Fri, 23 Aug 2024 12:50:20 +0200 Subject: [PATCH 3/5] fuzz seed corpus: add webpsave leak --- .../generic_buffer_with_args_leak_webpsave | Bin 0 -> 824 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 fuzz/common_fuzzer_corpus/generic_buffer_with_args_leak_webpsave diff --git a/fuzz/common_fuzzer_corpus/generic_buffer_with_args_leak_webpsave b/fuzz/common_fuzzer_corpus/generic_buffer_with_args_leak_webpsave new file mode 100644 index 0000000000000000000000000000000000000000..3adf303fe09eaf38bba6dbe24c13222f421cb511 GIT binary patch literal 824 zcma#fv(+_><YM_&vmX=>sVr#6Eo0%71oLQ9$F)AC#wKdYo&P}Ya zHHqbN_jI$cOypwVWN2Xk0ZBfq(9b1xykWy-J!anEF8e26`6g9ZgM5pnrkB26`FjU!d=# zq@?8K<+-`JfgT6?nvIPO7&ySt;Nai@1`#JGr-XzA!4P0o1G;O;kATa8Os=B3tCfX3 zI2BzNuMsj<;W)^(AZRT|;}L-bfmVira2hDcmdtQD7|7JW*>JV8nA=Vl&PBJ*eNfQ8 z$P~aK$JJ}400}czl(43Kn1SO`f^}(z0b}w6PG!B9#*(5_-Pl4|){Cs2z$C!Y4~k1` E0LLPS^Z)<= literal 0 HcmV?d00001 From 57b1b6773cc69b1f6f08913e28badf33510f051d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B6bl?= Date: Fri, 23 Aug 2024 21:51:35 +0200 Subject: [PATCH 4/5] add more test cases to the seed corpus --- .../generic_buffer_with_args_avif_to_avif | Bin 0 -> 899 bytes .../generic_buffer_with_args_pdf_to_png | 39 ++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 fuzz/common_fuzzer_corpus/generic_buffer_with_args_avif_to_avif create mode 100644 fuzz/common_fuzzer_corpus/generic_buffer_with_args_pdf_to_png diff --git a/fuzz/common_fuzzer_corpus/generic_buffer_with_args_avif_to_avif b/fuzz/common_fuzzer_corpus/generic_buffer_with_args_avif_to_avif new file mode 100644 index 0000000000000000000000000000000000000000..be3b13cbefd96bfbc42ce434446865ae7d003a87 GIT binary patch literal 899 zcmZuv&1(}u6o0e%G{z89ztAG}<4{T}`A{i=#Wb;E4+aWakWyi@nKc7DyTk6LB;cWy zT0Mv#|3N$mUPbVz2zpb|lcFcVLcQ6umiT5j+ln|a^M3F5-kbL^v*5KmylH97R6VCd z7gMLSC1xy8OSfCpQ8kchxG?D?M^3e^yl!*hP}gO)rD{vXJT(m4@ziqOv|ZOk zgKB7|OY=?UwW#pgYVmA-PA!)fQvfh(cs(JLAO0XFKnGww6zC!T4z)V}0+W9I(K#_=Sg0#qWAV5lDn`xjIF6GKL^8(dNj9GqRzI8t; zG`LEZS}4kh9TF}7l0?SMbc5zTG2sY|c*=xsqa4v~)3J23i{&X0Uq&j8oB zTtOwkl^t&EvCAYul6XvMoo-!f9mlG0L9hEqt)eqsRNS8HQSMgIhnY-sdKJwSZGW1> zENL0~zbx4>OC*_;d5$u{!)H){L|4`lcR-2WjI7>5>o{|0Fe88rW;3xF;!iQ7w_F`3 z;A>=pw=^#Yso0_P;LGLG?t?#pi~-rA-?PZ>lI&Qu`eC_rZss>YPDJ;d) literal 0 HcmV?d00001 diff --git a/fuzz/common_fuzzer_corpus/generic_buffer_with_args_pdf_to_png b/fuzz/common_fuzzer_corpus/generic_buffer_with_args_pdf_to_png new file mode 100644 index 0000000000..4b7e8424c7 --- /dev/null +++ b/fuzz/common_fuzzer_corpus/generic_buffer_with_args_pdf_to_png @@ -0,0 +1,39 @@ +[n=-1,page=0,dpi=72,scale=0.1,password=secret] +.png[filter=none] +%PDF-1.1 +%âãÏÓ +1 0 obj +<< +/Pages 2 0 R +/Type /Catalog +>> +endobj +2 0 obj +<< +/MediaBox [0 0 595 842] +/Kids [3 0 R] +/Count 1 +/Type /Pages +>> +endobj +3 0 obj +<< +/Parent 2 0 R +/MediaBox [0 0 595 842] +/Type /Page +>> +endobj xref +0 4 +0000000000 65535 f +0000000015 00000 n +0000000066 00000 n +0000000149 00000 n +trailer + +<< +/Root 1 0 R +/Size 4 +>> +startxref +221 +%%EOF From 0fa1fef720dbf46953b6cc18348d5fbf4250d696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B6bl?= Date: Sat, 24 Aug 2024 19:00:00 +0200 Subject: [PATCH 5/5] add vips_init call --- fuzz/generic_buffer_with_args_fuzzer.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fuzz/generic_buffer_with_args_fuzzer.cc b/fuzz/generic_buffer_with_args_fuzzer.cc index 0e3253bf7e..4983070dd6 100644 --- a/fuzz/generic_buffer_with_args_fuzzer.cc +++ b/fuzz/generic_buffer_with_args_fuzzer.cc @@ -5,6 +5,9 @@ extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { + if (VIPS_INIT(*argv[0])) + return -1; + vips_concurrency_set(1); return 0; }