From c9c7d5893383fe86756255db7d1fb61d39409bfa Mon Sep 17 00:00:00 2001 From: Arthur Chan Date: Thu, 5 Nov 2026 03:35:15 +0000 Subject: [PATCH] OSS-Fuzz: Add new fuzzer/corpus/seeds targets deserialisers Signed-off-by: Arthur Chan --- .../dictionaries/fuzz_marshal.dict | 53 +++++++ .../_xxtestfuzz/dictionaries/fuzz_pickle.dict | 71 ++++++++++ .../fuzz_marshal_corpus/big_tuple_v4.marshal | Bin 0 -> 5005 bytes .../code_nested_v4.marshal | Bin 0 -> 290 bytes .../code_object_v4.marshal | Bin 0 -> 98 bytes .../fuzz_marshal_corpus/containers_v2.marshal | Bin 0 -> 127 bytes .../fuzz_marshal_corpus/containers_v3.marshal | Bin 0 -> 127 bytes .../fuzz_marshal_corpus/containers_v4.marshal | Bin 0 -> 109 bytes .../float_variants_v4.marshal | Bin 0 -> 50 bytes .../negative_and_huge_ints_v4.marshal | Bin 0 -> 45 bytes .../recursive_list_v4.marshal | Bin 0 -> 10 bytes .../fuzz_marshal_corpus/strings_v2.marshal | Bin 0 -> 791 bytes .../fuzz_marshal_corpus/strings_v3.marshal | Bin 0 -> 791 bytes .../fuzz_marshal_corpus/strings_v4.marshal | Bin 0 -> 779 bytes .../fuzz_marshal_corpus/types_v2.marshal | Bin 0 -> 102 bytes .../fuzz_marshal_corpus/types_v3.marshal | Bin 0 -> 102 bytes .../fuzz_marshal_corpus/types_v4.marshal | Bin 0 -> 99 bytes .../fuzz_pickle_corpus/basic_dict_p0.pickle | 27 ++++ .../fuzz_pickle_corpus/basic_dict_p1.pickle | Bin 0 -> 128 bytes .../fuzz_pickle_corpus/basic_dict_p2.pickle | Bin 0 -> 122 bytes .../fuzz_pickle_corpus/basic_dict_p3.pickle | Bin 0 -> 82 bytes .../fuzz_pickle_corpus/basic_dict_p4.pickle | Bin 0 -> 71 bytes .../fuzz_pickle_corpus/basic_dict_p5.pickle | Bin 0 -> 71 bytes .../bytes_and_bytearray.pickle | Bin 0 -> 623 bytes .../complex_and_ellipsis.pickle | Bin 0 -> 78 bytes .../empty_stream_variants.pickle | Bin 0 -> 27 bytes .../fuzz_pickle_corpus/float_values.pickle | Bin 0 -> 70 bytes .../fuzz_pickle_corpus/framed_proto4.pickle | Bin 0 -> 2066 bytes .../fuzz_pickle_corpus/global_ref_type.pickle | Bin 0 -> 23 bytes .../fuzz_pickle_corpus/long_int.pickle | Bin 0 -> 222 bytes .../fuzz_pickle_corpus/memo_reuse.pickle | Bin 0 -> 53 bytes .../fuzz_pickle_corpus/neg_int_p2.pickle | 1 + .../fuzz_pickle_corpus/nested_p0.pickle | 41 ++++++ .../fuzz_pickle_corpus/nested_p1.pickle | Bin 0 -> 185 bytes .../fuzz_pickle_corpus/nested_p2.pickle | Bin 0 -> 184 bytes .../fuzz_pickle_corpus/nested_p3.pickle | Bin 0 -> 178 bytes .../fuzz_pickle_corpus/nested_p4.pickle | Bin 0 -> 100 bytes .../fuzz_pickle_corpus/nested_p5.pickle | Bin 0 -> 100 bytes .../fuzz_pickle_corpus/proto0_text.pickle | 12 ++ .../fuzz_pickle_corpus/recursive_list.pickle | Bin 0 -> 17 bytes .../stopiteration_and_range.pickle | Bin 0 -> 67 bytes .../fuzz_pickle_corpus/unicode_strs.pickle | Bin 0 -> 544 bytes Modules/_xxtestfuzz/fuzz_tests.txt | 2 + Modules/_xxtestfuzz/fuzzer.c | 134 ++++++++++++++++++ 44 files changed, 341 insertions(+) create mode 100644 Modules/_xxtestfuzz/dictionaries/fuzz_marshal.dict create mode 100644 Modules/_xxtestfuzz/dictionaries/fuzz_pickle.dict create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/big_tuple_v4.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/code_nested_v4.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/code_object_v4.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/containers_v2.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/containers_v3.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/containers_v4.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/float_variants_v4.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/negative_and_huge_ints_v4.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/recursive_list_v4.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/strings_v2.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/strings_v3.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/strings_v4.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/types_v2.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/types_v3.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_marshal_corpus/types_v4.marshal create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/basic_dict_p0.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/basic_dict_p1.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/basic_dict_p2.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/basic_dict_p3.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/basic_dict_p4.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/basic_dict_p5.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/bytes_and_bytearray.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/complex_and_ellipsis.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/empty_stream_variants.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/float_values.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/framed_proto4.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/global_ref_type.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/long_int.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/memo_reuse.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/neg_int_p2.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/nested_p0.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/nested_p1.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/nested_p2.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/nested_p3.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/nested_p4.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/nested_p5.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/proto0_text.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/recursive_list.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/stopiteration_and_range.pickle create mode 100644 Modules/_xxtestfuzz/fuzz_pickle_corpus/unicode_strs.pickle diff --git a/Modules/_xxtestfuzz/dictionaries/fuzz_marshal.dict b/Modules/_xxtestfuzz/dictionaries/fuzz_marshal.dict new file mode 100644 index 00000000000000..3ac1e4ed01d2e8 --- /dev/null +++ b/Modules/_xxtestfuzz/dictionaries/fuzz_marshal.dict @@ -0,0 +1,53 @@ +# marshal type codes (with and without the 0x80 REF flag) and structure tokens +"N" +"F" +"T" +"S" +"i" +"I" +"f" +"g" +"x" +"y" +"A" +"s" +"t" +"u" +"r" +"e" +"c" +"(" +"[" +"{" +"<" +">" +")" +"0" +"C" +"w" +"\x80" +"\x81" +"\x84" +"\x88" +"\x89" +"\x8a" +"\x8d" +"\x8e" +"\x91" +"\xa0" +"\xa1" +"\xa2" +"\xa3" +"\xa4" +"\xa5" +"\xa6" +"\xa7" +"\xa8" +"\xa9" +"\xc0" +"\xc1" +"\xe0" +"\xe9" +"ab" +"aaa" +"\x00\x01" diff --git a/Modules/_xxtestfuzz/dictionaries/fuzz_pickle.dict b/Modules/_xxtestfuzz/dictionaries/fuzz_pickle.dict new file mode 100644 index 00000000000000..2e705efa49fce9 --- /dev/null +++ b/Modules/_xxtestfuzz/dictionaries/fuzz_pickle.dict @@ -0,0 +1,71 @@ +# pickle opcode bytes (protocol 0-5) and typical atoms +"\x80" +"\x80\x02" +"\x80\x04" +"\x80\x05" +"(" +")" +"]" +"}" +"." +"t" +"G" +"X" +"U" +"T" +"V" +"S" +"C" +"B" +"L" +"K" +"M" +"J" +"F" +"I" +"o" +"i" +"R" +"P" +"Q" +"N" +"e" +"a" +"s" +"u" +"r" +"p" +"q" +"h" +"j" +"0" +"1" +"g" +"f" +"\x8a" +"\x8b" +"\x8c" +"\x8d" +"\x8e" +"\x8f" +"\x90" +"\x91" +"\x92" +"\x93" +"\x94" +"\x95" +"\x96" +"\x97" +"\x98" +"builtins" +"__main__" +"copyreg" +"_reconstructor" +"collections" +"OrderedDict" +"defaultdict" +"encode" +"loads" +"\x8cbuiltins" +"\x8cdict" +"\x94" diff --git a/Modules/_xxtestfuzz/fuzz_marshal_corpus/big_tuple_v4.marshal b/Modules/_xxtestfuzz/fuzz_marshal_corpus/big_tuple_v4.marshal new file mode 100644 index 0000000000000000000000000000000000000000..90dd1b285434090edd46759f325695cfd826a80b GIT binary patch literal 5005 zcmWm2Lx30t006;@ZQHhO+qP}nwr$(CZQE*-Hg=k3_A!r5`7%gAz^i~iy$XcD__G3D z1w}9fM+k&OD1=5Bghe=nM+8JfBt%9OL`5`2M-0S7EW}0}#6>*BM*<{7A|yrCS*nyWJNY)M-JpfF62fYArwXt6h$!w>E3`%% zv_(6#M+bC7Cv-*^bVWCGM-TKwFZ4zq^hH1P#{dk(APmM348<@E#|VtXD2&D!jKw&N z#{^8oBuvH>OvN-z#|+HGEX>9n%*8y+#{w+GA}q!dEX6V`#|o^(Dy+sDti?L4#|CV~ zCTzwQY{fQg#}4eoF6_o0?8QFp#{nF~AsogL9K|sl#|fOoDV)X`oW(hu#|2!(C0xc8 zT*Wn9#|_-XE!@T(+{HcI#{)dXBRs|vJjF9S#|yl~EBuAO@fvUN5B|klyu*8Zz(;(- zXMDj|e8YGAz)$?bfB21nKmh@*0wFMhASi+%I6@#KLLoH5AS}WmJR%?>A|W!OAS$9E zI$|IuVj(u-ATHt|J`x}y5+N~?ASsd|IZ_}cQXw_cAT81%Ju)C8G9fdvAS<#VJ8~c= zav?YJATRPEKMJ5A3ZXEHpeTx=I7*--N})8$pe)LvJSw0fDxor}pem}NI%=RMYN0mj zpf2j6J{q7Q8lf?opedT6Ia;74TA?-Cpe@>=JvyKxI-xVVpewqeJ9?ledZ9P^pfCEN zKL%hR24OIUU?_%RI7VP3MqxC@U@XRAJSJcwCSfwBU@E3zI%Z%dW??qwU@qoiJ{Djh z7GW`#U@4YiIaXjLR$(>PU@g{RJvLw?HeoZiU@Nv^J9c0vc40U6U@!JzKMvp^4&gA4 z;3$saI8NXsPT@4p;4IGJJTBlOF5xn+;3}@+I&R=5Zs9iW;4bdrJ|5s99^o;b;3=Nr zIbPr;Ug0nNjn{aCfABBf;vL@O13uytKI03%;v2r>2Y%ug{=;ts1pY%H1V#`9MKAMKUBu3Zz6T zq(&N~MLMKM24qAgWJVTbMK)wd4&+2GOR7Mq4MKx4M4b(&})J7fDMLpC<12jY1WMLV=d z2XsUybVe6+MK^Ru5A;MY^hO`_ML+b%01U(+48{-)#V`!V2#mxijK&y@#W;+|1Wd#v zOvV&U#WYOE49vtV%*Gtd#XQW%0xZNLEXEQn#WF0%3arE`ti~Fw#X79V25iJ8Y{nLB z#Wrlm4(!A(?8YAK#XjuE0UX339L5nG#W5Vm37o_!oW>cP#W|eE1zf}>T*eh##Wh^V z4cx>n+{PW;#Xa1|13bhdJjN3|#WOs|3%tZD{Dr^q8gK9q{>59o!+U(dM|{F(e8E?I z!*~3^PyE7v_>F)de+Y!Y2!fyphTsT+kO+m)2!pT)hwzAih=_#9h=QnyhUkcan23eg zh=aI@hxkZ4JD1)*nhw`X^il~IjsDi4fhU%z+ny7`^sDrwwhx%xM zhG>MwXo99_hURF2mS~06XoI$BhxX`zj_8EW=z^~3hVJNrp6G?%=!3rKhyECVff$6r z7=ob~hT#~2kr;*17=y7Ghw+$ziI{}Rn1ZR8hUu7rnV5yyn1i{Phxu55g;<2eSc0Wk zhUHj+l~{$;hy6H!gE)l4ID(@%hT}Ma zlQ@ObID@k|hx53Ai@1c#xPq&=hU>V2o4AGBxP!a6hx>Sdhj@g?c!H;RhUa+khyMXj Cb_m=6 literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_marshal_corpus/code_nested_v4.marshal b/Modules/_xxtestfuzz/fuzz_marshal_corpus/code_nested_v4.marshal new file mode 100644 index 0000000000000000000000000000000000000000..a6e08893ba1ac9e810280b7256d8706959e02443 GIT binary patch literal 290 zcmYdhKmv?V_Gd02V=6;1gA_v%Lpq}-Q!-2jq<|HOnSuDT2auS`5Dk|LW;BJeg&D#a zi<$HpikXBNJlGi+@&!W~bb`+Yf)le zda5SVEyl!KjG4tuKv4ySTg*1acDESQih!mufNUvN01^!hccc{-2+gs)%&j`hazf$+ z#va$1mKV8IFR-Zoyu__q%mP%@$0yI?r^yJ`xsu^CP=uj~4M^PLu*uC&Da}c>D+1XJ WHWbA8z|6?V_?d~3QLPB*SOx&O+c4e$ literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_marshal_corpus/code_object_v4.marshal b/Modules/_xxtestfuzz/fuzz_marshal_corpus/code_object_v4.marshal new file mode 100644 index 0000000000000000000000000000000000000000..c3e16fc62aea0465557e87bf804551dfa5c40ed4 GIT binary patch literal 98 zcmYdhKmv?V_Gbixq!q6W=2NF8!ViSj72O!E&%9a5fuOc literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_marshal_corpus/containers_v2.marshal b/Modules/_xxtestfuzz/fuzz_marshal_corpus/containers_v2.marshal new file mode 100644 index 0000000000000000000000000000000000000000..a30df32ed72288059aa404330a3dcbdd7abadf59 GIT binary patch literal 127 zcmb;}Wn^GrNU6>QQJG92f*C}x00{%IT!{u)0976=lM{_i1|(LTT4Dn>3$Cja#7!%< N1B-$T&twJJ005|)4fp^6 literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_marshal_corpus/containers_v3.marshal b/Modules/_xxtestfuzz/fuzz_marshal_corpus/containers_v3.marshal new file mode 100644 index 0000000000000000000000000000000000000000..30eff82157ba71f07d96a389044a3e275cd93367 GIT binary patch literal 127 zcmb>a!pOkDkW&2;M7?AJ5zHWh1xOfxCR!^g^=YngKh*^93hfw|+kJupTPK;{X6V)DHgu literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_marshal_corpus/negative_and_huge_ints_v4.marshal b/Modules/_xxtestfuzz/fuzz_marshal_corpus/negative_and_huge_ints_v4.marshal new file mode 100644 index 0000000000000000000000000000000000000000..198f649326c5d11af288c405d638bd60117f3783 GIT binary patch literal 45 jcma!MVPIg$`ThU@e;^G3EIF(&CWvNv36%W*62t@m?W+q5 literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_marshal_corpus/recursive_list_v4.marshal b/Modules/_xxtestfuzz/fuzz_marshal_corpus/recursive_list_v4.marshal new file mode 100644 index 0000000000000000000000000000000000000000..b4f6d3c06906fcdd387c0565682cee4894c0afc9 GIT binary patch literal 10 Pcmcc3$iTo*1jGyg3flos literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_marshal_corpus/strings_v2.marshal b/Modules/_xxtestfuzz/fuzz_marshal_corpus/strings_v2.marshal new file mode 100644 index 0000000000000000000000000000000000000000..5bd92b22019b12c9f742250c1439f0ea3b1af33c GIT binary patch literal 791 zcma!MV_;w?1!9I$Mj(+`$^;^lN}0h_a;XkbG;tIV9Rj6?fB|-RPu}76$@wX%ql_UM F2movuaPI&B literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_marshal_corpus/strings_v3.marshal b/Modules/_xxtestfuzz/fuzz_marshal_corpus/strings_v3.marshal new file mode 100644 index 0000000000000000000000000000000000000000..168cd577dffd3ea7157c2f68ac9885022379e2e0 GIT binary patch literal 791 zcma!MV_;zT0>lho7=c9M7bXyy^o1ErC4bQYiYAT%qC?>8Az*+V-jjEDeR6(E>L_D~ G1_A)j^KgONtGq3#l=h@R-#{sTd*Dg$ebAy literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_marshal_corpus/types_v4.marshal b/Modules/_xxtestfuzz/fuzz_marshal_corpus/types_v4.marshal new file mode 100644 index 0000000000000000000000000000000000000000..fdab933222b7bd3fb9afb7cc34b33e229d1991e1 GIT binary patch literal 99 zcma#%V_;x-sRbgg{r~^}4J(iZ0|E@sAxsl2S_&3z=dInKj%UKztyGU<48sg)GVO$@wX% z$;Di$c_0Q?A*%*hsv-1kkil8z>v$+z2r8-b`(U?4^1D(ytNt literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_pickle_corpus/basic_dict_p4.pickle b/Modules/_xxtestfuzz/fuzz_pickle_corpus/basic_dict_p4.pickle new file mode 100644 index 0000000000000000000000000000000000000000..514bbed0808ca7609a0e8a651a73e241ad6ddbd8 GIT binary patch literal 71 zcmZo*nQFrT0ku;!dRP;43NjL>cr*5}B&C)lPKlkO;qJf!k?&!wnBvS>ImNG|Gqr~` QJux>Iq|lqGZAz&g0IF{kmH+?% literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_pickle_corpus/basic_dict_p5.pickle b/Modules/_xxtestfuzz/fuzz_pickle_corpus/basic_dict_p5.pickle new file mode 100644 index 0000000000000000000000000000000000000000..980e794161ac476f90a6d54d1a8b7bfa4e63d0aa GIT binary patch literal 71 zcmZo*ood4X0ku;!dRP;43NjL>cr*5}B&C)lPKlkO;qJf!k?&!wnBvS>ImNG|Gqr~` QJux>Iq|lqGZAz&g0IIbVmjD0& literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_pickle_corpus/bytes_and_bytearray.pickle b/Modules/_xxtestfuzz/fuzz_pickle_corpus/bytes_and_bytearray.pickle new file mode 100644 index 0000000000000000000000000000000000000000..23f30ad629b918102bb85a6c5857882ce3ce7909 GIT binary patch literal 623 zcmZo*nVQ1H00yyBG@Nu8A?#6-xDc4)!~hC0MkZz!RyKAHPA+a9UOs*SK_OugQ894| zNhxU=Svh$HMI~hwRW)@DO)YI5T|IpRLnC7oQ!{f5ODk&|TRVFPM<-_&S2uSLPcLsD zUqAnVz@Xre(6I1`$f)R;*tqzF#H8eu)U@=B%&hF3+`RmP!lL4m(z5c3%Bt#`+PeCN z#-`?$*0%PJ&aUpB-oE|`6DLicGIiSY88c_io-=pe`~?daEnc#8+42=DSFK*NcHR07 z8#isOqo2z-TnhaiMs<-ZQGQfDH)7C T9IiPznFYm}#Xv<85RSy7Blm__# literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_pickle_corpus/float_values.pickle b/Modules/_xxtestfuzz/fuzz_pickle_corpus/float_values.pickle new file mode 100644 index 0000000000000000000000000000000000000000..3cd750d01307ae4e8c95ef63dae7cabb4979d00f GIT binary patch literal 70 zcmZo*nQF}d0kKmw+@VYc_Xa4-z5d~u&#kXdEO2+=RQw&{qATHE{{bTBUjGBaNYw)X D5>^mO literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_pickle_corpus/framed_proto4.pickle b/Modules/_xxtestfuzz/fuzz_pickle_corpus/framed_proto4.pickle new file mode 100644 index 0000000000000000000000000000000000000000..42a395ed247be029b57fe8d2771e41f7e94e14aa GIT binary patch literal 2066 zcma*nH&O&K6og^S!Y=rbc`DGZqrYblJG5$mZa zqZhFuY>wCzuDpmX;o6JX7H+(V9pToC*cI-)h&|!ni`W+)yodwg(TfPFsG=8fDD2&& zB#wm55y!%{7jYuocoC<Q_7Q`w~b{VdMwXBTTb>fYFR zQKu~QegyYLmS?izsjeG0ik3Z1_~};mrCP$xzcJ`#>Kj40Llu2d) literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_pickle_corpus/memo_reuse.pickle b/Modules/_xxtestfuzz/fuzz_pickle_corpus/memo_reuse.pickle new file mode 100644 index 0000000000000000000000000000000000000000..59918eb3e138af4970812ab714e81d0438692d35 GIT binary patch literal 53 xcmZo*nX1JA0ku;!dKeR@!~!X{;*7+i)RZY1%n+E`!S5oy}k1*sjV@%uh z5lMxVSg$2cD`doWL_X~|ktb%v8Rrr6UPQcAt(S?SfQ^1-_fm0g1(yY#%@60AXw@ zgs4N?A#sp~qAEkuAvL51WMhA3zF|TsWp7MdX0|F)Eq9nz-j{u-yU=*AW1^8e==ejD t6u&Spu&{YtU+&ijH(zG?$NX}QmBZTDB#uwmj9y|pdWBv5+7~$V#}9;3F)#oC literal 0 HcmV?d00001 diff --git a/Modules/_xxtestfuzz/fuzz_pickle_corpus/nested_p3.pickle b/Modules/_xxtestfuzz/fuzz_pickle_corpus/nested_p3.pickle new file mode 100644 index 0000000000000000000000000000000000000000..3c66a18b518ad2200d7b945a234ce61a8bbe9b18 GIT binary patch literal 178 zcmYL>yAHxI3`Nr>1sdLukI2N2cArRT( #include #include +#include /* PyMarshal_ReadObjectFromString for fuzz_marshal */ /* Fuzz PyFloat_FromString as a proxy for float(str). */ static int fuzz_builtin_float(const char* data, size_t size) { @@ -595,6 +596,125 @@ static int _run_fuzz(const uint8_t *data, size_t size, int(*fuzzer)(const char* return rv; } +#define MAX_DESERIALISE_TEST_SIZE 0x100000 + +/* Fuzz marshal.loads() via PyMarshal_ReadObjectFromString. marshal is the + deserialiser behind .pyc files and marshal.dumps()/loads(); unmarshalling + attacker-supplied bytes must stay memory-safe (invalid type tags, negative + or oversized length fields, dangling ref tags, malformed code objects). */ +static int fuzz_marshal(const char* data, size_t size) { + if (size > MAX_DESERIALISE_TEST_SIZE) { + return 0; + } + PyObject* obj = PyMarshal_ReadObjectFromString(data, (Py_ssize_t)size); + if (obj == NULL) { + /* Expected for attacker-controlled bytes: truncated streams raise + EOFError, invalid tags raise ValueError, malformed code objects + raise TypeError, deeply nested data raises RecursionError and + oversized length fields raise MemoryError. */ + if (PyErr_ExceptionMatches(PyExc_EOFError) || + PyErr_ExceptionMatches(PyExc_ValueError) || + PyErr_ExceptionMatches(PyExc_TypeError) || + PyErr_ExceptionMatches(PyExc_RecursionError) || + PyErr_ExceptionMatches(PyExc_MemoryError)) + { + PyErr_Clear(); + } + } + Py_XDECREF(obj); + return 0; +} + +/* Fuzz the C unpickler over attacker-controlled bytes: pickle is the classic + "never unpickle untrusted data" surface. The load loop stays in C (we + subclass the C _pickle.Unpickler); find_class is overridden to raise so + mutated payloads cannot import arbitrary modules or execute code inside + the fuzzer process, while every opcode-handling code path (stack/memo + manipulation, string and framing parsing, object reconstruction) remains + covered. Memory-safety bugs still crash the sanitizer. */ +static PyObject* pickle_bytesio_type = NULL; +static PyObject* safe_unpickler_type = NULL; + +static const char* safe_unpickler_code = + "class _SafeUnpickler(_pickle.Unpickler):\n" + " def find_class(self, module, name):\n" + " raise _pickle.UnpicklingError('find_class is disabled')\n"; + +/* Called by LLVMFuzzerTestOneInput for initialization */ +static int init_pickle(void) { + PyObject* pickle_module = PyImport_ImportModule("_pickle"); + if (pickle_module == NULL) { + return 0; + } + PyObject* io_module = PyImport_ImportModule("io"); + if (io_module == NULL) { + Py_DECREF(pickle_module); + return 0; + } + pickle_bytesio_type = PyObject_GetAttrString(io_module, "BytesIO"); + Py_DECREF(io_module); + if (pickle_bytesio_type == NULL) { + Py_DECREF(pickle_module); + return 0; + } + + /* Create the restricted Unpickler subclass once. */ + PyObject* globals = PyDict_New(); + if (globals == NULL) { + Py_DECREF(pickle_module); + return 0; + } + if (PyDict_SetItemString(globals, "_pickle", pickle_module) < 0) { + Py_DECREF(globals); + Py_DECREF(pickle_module); + return 0; + } + PyObject* result = PyRun_String(safe_unpickler_code, Py_file_input, + globals, globals); + Py_DECREF(pickle_module); /* the new class holds its own references */ + if (result != NULL) { + Py_DECREF(result); + safe_unpickler_type = PyDict_GetItemString(globals, "_SafeUnpickler"); + Py_XINCREF(safe_unpickler_type); + } + Py_DECREF(globals); + return safe_unpickler_type != NULL; +} + +/* Fuzz _pickle.Unpickler.load() over untrusted bytes */ +static int fuzz_pickle(const char* data, size_t size) { + if (size > MAX_DESERIALISE_TEST_SIZE) { + return 0; + } + PyObject* input = PyObject_CallFunction(pickle_bytesio_type, "y#", + data, (Py_ssize_t)size); + if (input == NULL) { + PyErr_Print(); + abort(); + } + PyObject* unpickler = PyObject_CallFunctionObjArgs(safe_unpickler_type, + input, NULL); + Py_DECREF(input); + if (unpickler == NULL) { + PyErr_Print(); + abort(); + } + PyObject* result = PyObject_CallMethod(unpickler, "load", NULL); + Py_DECREF(unpickler); + if (result == NULL) { + /* Expected for attacker-controlled pickle bytes: invalid streams + raise UnpicklingError/EOFError, and object reconstruction (REDUCE, + SETSTATE, APPEND on built-in containers) can raise arbitrary + exceptions. Python-level failures are cleared here; memory-safety + bugs in the opcode machinery still crash the sanitizer. */ + PyErr_Clear(); + } else { + Py_DECREF(result); + } + return 0; +} + + /* CPython generates a lot of leak warnings for whatever reason. */ int __lsan_is_turned_off(void) { return 1; } @@ -726,6 +846,20 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { #endif #if !defined(_Py_FUZZ_ONE) || defined(_Py_FUZZ_fuzz_pycompile) rv |= _run_fuzz(data, size, fuzz_pycompile); +#endif +#if !defined(_Py_FUZZ_ONE) || defined(_Py_FUZZ_fuzz_marshal) + rv |= _run_fuzz(data, size, fuzz_marshal); +#endif +#if !defined(_Py_FUZZ_ONE) || defined(_Py_FUZZ_fuzz_pickle) + static int PICKLE_INITIALIZED = 0; + if (!PICKLE_INITIALIZED && !init_pickle()) { + PyErr_Print(); + abort(); + } else { + PICKLE_INITIALIZED = 1; + } + + rv |= _run_fuzz(data, size, fuzz_pickle); #endif return rv; }