From 17381cb4c5cb1b834b413ed905de5c5fcd4db46d Mon Sep 17 00:00:00 2001 From: Andrey Bienkowski Date: Thu, 1 Apr 2021 13:51:32 +0300 Subject: [PATCH 1/8] Add a fuzz target --- fuzz/differential_fuzzer.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 fuzz/differential_fuzzer.py diff --git a/fuzz/differential_fuzzer.py b/fuzz/differential_fuzzer.py new file mode 100644 index 00000000..d021c9da --- /dev/null +++ b/fuzz/differential_fuzzer.py @@ -0,0 +1,29 @@ +import sys + +from msgpack import _cmsgpack, fallback + + +def TestOneInput(data): + try: + from_extension = _cmsgpack.unpackb(buf) + except: + return + try: + from_fallback = fallback.unpackb(buf) + except: + return + if from_extension != from_fallback: + raise RuntimeError( + f"Decoding disagreement: input: {data}, from extension: {from_extension}, from fallback: {from_fallback}" + ) + + +def main(): + import atheris + + atheris.Setup(sys.argv, TestOneInput) + atheris.Fuzz() + + +if __name__ == "__main__": + main() From 0b0f5210639321045f3c4da9cc1c0d2e366ab5b2 Mon Sep 17 00:00:00 2001 From: Andrey Bienkowski Date: Thu, 1 Apr 2021 13:53:25 +0300 Subject: [PATCH 2/8] Add a seed corpus Copied from https://github.com/msgpack/msgpack-c/tree/88e94e3776dce2b58193e95f28394026231b939e/fuzz/unpack_pack_fuzzer_seed_corpus --- fuzz/differential_fuzzer_seed_corpus/EmptyArray | 1 + fuzz/differential_fuzzer_seed_corpus/EmptyObject | 1 + .../ExcessiveNesting | 2 ++ .../OpenWeatherMap | Bin 0 -> 420 bytes .../WeatherUnderground | Bin 0 -> 2087 bytes 5 files changed, 4 insertions(+) create mode 100644 fuzz/differential_fuzzer_seed_corpus/EmptyArray create mode 100644 fuzz/differential_fuzzer_seed_corpus/EmptyObject create mode 100644 fuzz/differential_fuzzer_seed_corpus/ExcessiveNesting create mode 100644 fuzz/differential_fuzzer_seed_corpus/OpenWeatherMap create mode 100644 fuzz/differential_fuzzer_seed_corpus/WeatherUnderground diff --git a/fuzz/differential_fuzzer_seed_corpus/EmptyArray b/fuzz/differential_fuzzer_seed_corpus/EmptyArray new file mode 100644 index 00000000..9e99dd5e --- /dev/null +++ b/fuzz/differential_fuzzer_seed_corpus/EmptyArray @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/fuzz/differential_fuzzer_seed_corpus/EmptyObject b/fuzz/differential_fuzzer_seed_corpus/EmptyObject new file mode 100644 index 00000000..5416677b --- /dev/null +++ b/fuzz/differential_fuzzer_seed_corpus/EmptyObject @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/fuzz/differential_fuzzer_seed_corpus/ExcessiveNesting b/fuzz/differential_fuzzer_seed_corpus/ExcessiveNesting new file mode 100644 index 00000000..4800f04b --- /dev/null +++ b/fuzz/differential_fuzzer_seed_corpus/ExcessiveNesting @@ -0,0 +1,2 @@ + +  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx \ No newline at end of file diff --git a/fuzz/differential_fuzzer_seed_corpus/OpenWeatherMap b/fuzz/differential_fuzzer_seed_corpus/OpenWeatherMap new file mode 100644 index 0000000000000000000000000000000000000000..05b87929025cc37123c81fbc33d26f6134dff6ed GIT binary patch literal 420 zcmZwDF-QY36b9f{9Yn`E>*C-dba8Ny77>eJ7Zofnl3vm_aF?WcIqP++sFOJ8;3PH#B%~=v&-nN_y?WVi#NnMDSbOX$oGGxuJCHd;#}fAZ6g)tR~`%36U|p`a~9q|=$EktVN4kT2|%H^ z3AAy%Zcz-X9|S^1Tf36PQigT%xpI-P$UOx~^qHP@jy f`dS=y?5Acnr%Zz~-0FZJ1c$lr)L^v5@$=IUg5w7-sLBk+_WnNV_8SXA-BC5RI}bE7+E5L$?wa%N>vHQEZQy88^+IfW08D zoZv*;WZNc9+fXD99QXkhKcE+W3$Mo^abYR=G#bym^Um`%Uti;#bCODz?Fqv7JxN*m z#~aRhL_F!z)F%fnKH6$eV}`xhl`q_wrQvluA)I1Qf69d0PD2tC@pGjBEW)bNH$zP2 z;P##Fr<-lGg0_gq(Q_|_fe$hFv*O29)kMk5+hG`+wS+krq zvyN5_$1u*JZGt@^-JHj_^+?KWP1pPVzShqHY#wsx-`6lp^qsEWY3qQIyTC|`WD-yM zKnsp&94ltdh>$daJNaK${sh3;B;x>c&I#~1vR1WK`_d=BFrI@AaV10gYF(FpGp4LCeLxl|0vEI`&#ROJFXdw-*d@8co8!W{4 ztrFk#pDLT(nF2Yrmol2v9nF}3W2F^0^^&S!j$hDhv|2X}^R;4|&hOZ=8m*>N%I&Dr zzE5To1yI89o7;t&L}m*45HTCC-bT_-5UH`+N9) znC??S_h<|$=Jt}I+0@L7g{>q6r+@fIZ|O&)&+KM*4x(#$O>t|;jn1>s+#+d zMCA6}r;u-GC-aL?LM$z^kU%EZPy?b6ZEqsr@o4AyVPjT#Wfm07ss;ZR5B99md#Ugv zWXw1z5__MxQJzpAxH@h&-utCmr)ccIBHAt^x_ZPM?}h)6GT_zHQm-du5>X);AE+FA zc8^i?`9j^JJOhR6OLgkS>!CMw%h4ZuG#)%DOR6W}6oNg2R3tAiB;ko*K^NX`ipl*i o%3lfXWmNZdwNsTl*(Y3pJ&p~{JPp9KAT{yT7<2?!!n}C!C+V;pFaQ7m literal 0 HcmV?d00001 From 5f565fb6377ec8ea919fba1d3e640edf302155ab Mon Sep 17 00:00:00 2001 From: Andrey Bienkowski Date: Thu, 1 Apr 2021 14:07:05 +0300 Subject: [PATCH 3/8] Fix a typo --- fuzz/differential_fuzzer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fuzz/differential_fuzzer.py b/fuzz/differential_fuzzer.py index d021c9da..736c708a 100644 --- a/fuzz/differential_fuzzer.py +++ b/fuzz/differential_fuzzer.py @@ -5,11 +5,11 @@ def TestOneInput(data): try: - from_extension = _cmsgpack.unpackb(buf) + from_extension = _cmsgpack.unpackb(data) except: return try: - from_fallback = fallback.unpackb(buf) + from_fallback = fallback.unpackb(data) except: return if from_extension != from_fallback: From f3f6d6b1b389396fe8450f03ca98b99ad9456880 Mon Sep 17 00:00:00 2001 From: Andrey Bienkowski Date: Thu, 1 Apr 2021 14:31:02 +0300 Subject: [PATCH 4/8] I forgot: nan != nan --- fuzz/differential_fuzzer.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fuzz/differential_fuzzer.py b/fuzz/differential_fuzzer.py index 736c708a..7443f6a8 100644 --- a/fuzz/differential_fuzzer.py +++ b/fuzz/differential_fuzzer.py @@ -1,4 +1,5 @@ import sys +import math from msgpack import _cmsgpack, fallback @@ -12,7 +13,10 @@ def TestOneInput(data): from_fallback = fallback.unpackb(data) except: return - if from_extension != from_fallback: + good = from_extension == from_fallback or ( + math.isnan(from_extension) and math.isnan(from_fallback) + ) + if not good: raise RuntimeError( f"Decoding disagreement: input: {data}, from extension: {from_extension}, from fallback: {from_fallback}" ) From 8937329935f74d5e6947e019171e4e906a05a9d1 Mon Sep 17 00:00:00 2001 From: Andrey Bienkowski Date: Thu, 1 Apr 2021 16:07:01 +0300 Subject: [PATCH 5/8] I forgot [nan] != [nan] --- fuzz/differential_fuzzer.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/fuzz/differential_fuzzer.py b/fuzz/differential_fuzzer.py index 7443f6a8..5dd104fc 100644 --- a/fuzz/differential_fuzzer.py +++ b/fuzz/differential_fuzzer.py @@ -4,6 +4,16 @@ from msgpack import _cmsgpack, fallback +def replace_nan(data, sentinel): + if type(data) == float and math.isnan(data): + return sentinel + if type(data) == list: + return [replace_nan(x, sentinel) for x in data] + if type(data) == dict: + return {k: replace_nan(v, sentinel) for k, v in data.items()} + return data + + def TestOneInput(data): try: from_extension = _cmsgpack.unpackb(data) @@ -13,10 +23,8 @@ def TestOneInput(data): from_fallback = fallback.unpackb(data) except: return - good = from_extension == from_fallback or ( - math.isnan(from_extension) and math.isnan(from_fallback) - ) - if not good: + sentinel = object() + if replace_nan(from_extension, sentinel) != replace_nan(from_fallback, sentinel): raise RuntimeError( f"Decoding disagreement: input: {data}, from extension: {from_extension}, from fallback: {from_fallback}" ) From 61fb6290300b4ba7c60591bcd756651797ca0765 Mon Sep 17 00:00:00 2001 From: Andrey Bienkowski Date: Thu, 1 Apr 2021 17:16:42 +0300 Subject: [PATCH 6/8] Add a unit test for the fuzz target --- ...ential_fuzzer.py => test_differential_fuzzer.py} | 10 ++++++++++ .../EmptyArray | 0 .../EmptyObject | 0 .../ExcessiveNesting | 0 .../OpenWeatherMap | Bin .../WeatherUnderground | Bin 6 files changed, 10 insertions(+) rename fuzz/{differential_fuzzer.py => test_differential_fuzzer.py} (74%) rename fuzz/{differential_fuzzer_seed_corpus => test_differential_fuzzer_seed_corpus}/EmptyArray (100%) rename fuzz/{differential_fuzzer_seed_corpus => test_differential_fuzzer_seed_corpus}/EmptyObject (100%) rename fuzz/{differential_fuzzer_seed_corpus => test_differential_fuzzer_seed_corpus}/ExcessiveNesting (100%) rename fuzz/{differential_fuzzer_seed_corpus => test_differential_fuzzer_seed_corpus}/OpenWeatherMap (100%) rename fuzz/{differential_fuzzer_seed_corpus => test_differential_fuzzer_seed_corpus}/WeatherUnderground (100%) diff --git a/fuzz/differential_fuzzer.py b/fuzz/test_differential_fuzzer.py similarity index 74% rename from fuzz/differential_fuzzer.py rename to fuzz/test_differential_fuzzer.py index 5dd104fc..4f4383bf 100644 --- a/fuzz/differential_fuzzer.py +++ b/fuzz/test_differential_fuzzer.py @@ -1,5 +1,7 @@ import sys import math +import os +import pytest from msgpack import _cmsgpack, fallback @@ -30,6 +32,14 @@ def TestOneInput(data): ) +SCRIPT_DIR = os.path.dirname(__file__) +CORPUS_DIR = os.path.join(SCRIPT_DIR, "test_differential_fuzzer_seed_corpus") +CORPUS = [open(os.path.join(CORPUS_DIR, f), 'rb').read() for f in os.listdir(CORPUS_DIR)] +@pytest.mark.parametrize('data', CORPUS) +def test_try_the_seed_corpus(data): + TestOneInput(data) + + def main(): import atheris diff --git a/fuzz/differential_fuzzer_seed_corpus/EmptyArray b/fuzz/test_differential_fuzzer_seed_corpus/EmptyArray similarity index 100% rename from fuzz/differential_fuzzer_seed_corpus/EmptyArray rename to fuzz/test_differential_fuzzer_seed_corpus/EmptyArray diff --git a/fuzz/differential_fuzzer_seed_corpus/EmptyObject b/fuzz/test_differential_fuzzer_seed_corpus/EmptyObject similarity index 100% rename from fuzz/differential_fuzzer_seed_corpus/EmptyObject rename to fuzz/test_differential_fuzzer_seed_corpus/EmptyObject diff --git a/fuzz/differential_fuzzer_seed_corpus/ExcessiveNesting b/fuzz/test_differential_fuzzer_seed_corpus/ExcessiveNesting similarity index 100% rename from fuzz/differential_fuzzer_seed_corpus/ExcessiveNesting rename to fuzz/test_differential_fuzzer_seed_corpus/ExcessiveNesting diff --git a/fuzz/differential_fuzzer_seed_corpus/OpenWeatherMap b/fuzz/test_differential_fuzzer_seed_corpus/OpenWeatherMap similarity index 100% rename from fuzz/differential_fuzzer_seed_corpus/OpenWeatherMap rename to fuzz/test_differential_fuzzer_seed_corpus/OpenWeatherMap diff --git a/fuzz/differential_fuzzer_seed_corpus/WeatherUnderground b/fuzz/test_differential_fuzzer_seed_corpus/WeatherUnderground similarity index 100% rename from fuzz/differential_fuzzer_seed_corpus/WeatherUnderground rename to fuzz/test_differential_fuzzer_seed_corpus/WeatherUnderground From f20b63f6e7ca0145a0f3834c6cc7bc38ba549802 Mon Sep 17 00:00:00 2001 From: Andrey Bienkowski Date: Thu, 1 Apr 2021 17:30:05 +0300 Subject: [PATCH 7/8] Fix the fuzzer --- fuzz/test_differential_fuzzer.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fuzz/test_differential_fuzzer.py b/fuzz/test_differential_fuzzer.py index 4f4383bf..108ddc1f 100644 --- a/fuzz/test_differential_fuzzer.py +++ b/fuzz/test_differential_fuzzer.py @@ -34,8 +34,17 @@ def TestOneInput(data): SCRIPT_DIR = os.path.dirname(__file__) CORPUS_DIR = os.path.join(SCRIPT_DIR, "test_differential_fuzzer_seed_corpus") -CORPUS = [open(os.path.join(CORPUS_DIR, f), 'rb').read() for f in os.listdir(CORPUS_DIR)] -@pytest.mark.parametrize('data', CORPUS) +if os.path.exists(CORPUS_DIR): + CORPUS = [ + open(os.path.join(CORPUS_DIR, f), "rb").read() for f in os.listdir(CORPUS_DIR) + ] +else: + # When this file is executed as a fuzz target the dirrectory + # test_differential_fuzzer_seed_corpus does not exist + CORPUS = [] + + +@pytest.mark.parametrize("data", CORPUS) def test_try_the_seed_corpus(data): TestOneInput(data) From 9109e6e52f6e62bc3af1b17ec533762a0563c779 Mon Sep 17 00:00:00 2001 From: Andrey Bienkowski Date: Fri, 2 Apr 2021 14:45:27 +0300 Subject: [PATCH 8/8] Add .bin extension --- .../{EmptyArray => EmptyArray.bin} | 0 .../{EmptyObject => EmptyObject.bin} | 0 .../{ExcessiveNesting => ExcessiveNesting.bin} | 0 .../{OpenWeatherMap => OpenWeatherMap.bin} | Bin .../{WeatherUnderground => WeatherUnderground.bin} | Bin 5 files changed, 0 insertions(+), 0 deletions(-) rename fuzz/test_differential_fuzzer_seed_corpus/{EmptyArray => EmptyArray.bin} (100%) rename fuzz/test_differential_fuzzer_seed_corpus/{EmptyObject => EmptyObject.bin} (100%) rename fuzz/test_differential_fuzzer_seed_corpus/{ExcessiveNesting => ExcessiveNesting.bin} (100%) rename fuzz/test_differential_fuzzer_seed_corpus/{OpenWeatherMap => OpenWeatherMap.bin} (100%) rename fuzz/test_differential_fuzzer_seed_corpus/{WeatherUnderground => WeatherUnderground.bin} (100%) diff --git a/fuzz/test_differential_fuzzer_seed_corpus/EmptyArray b/fuzz/test_differential_fuzzer_seed_corpus/EmptyArray.bin similarity index 100% rename from fuzz/test_differential_fuzzer_seed_corpus/EmptyArray rename to fuzz/test_differential_fuzzer_seed_corpus/EmptyArray.bin diff --git a/fuzz/test_differential_fuzzer_seed_corpus/EmptyObject b/fuzz/test_differential_fuzzer_seed_corpus/EmptyObject.bin similarity index 100% rename from fuzz/test_differential_fuzzer_seed_corpus/EmptyObject rename to fuzz/test_differential_fuzzer_seed_corpus/EmptyObject.bin diff --git a/fuzz/test_differential_fuzzer_seed_corpus/ExcessiveNesting b/fuzz/test_differential_fuzzer_seed_corpus/ExcessiveNesting.bin similarity index 100% rename from fuzz/test_differential_fuzzer_seed_corpus/ExcessiveNesting rename to fuzz/test_differential_fuzzer_seed_corpus/ExcessiveNesting.bin diff --git a/fuzz/test_differential_fuzzer_seed_corpus/OpenWeatherMap b/fuzz/test_differential_fuzzer_seed_corpus/OpenWeatherMap.bin similarity index 100% rename from fuzz/test_differential_fuzzer_seed_corpus/OpenWeatherMap rename to fuzz/test_differential_fuzzer_seed_corpus/OpenWeatherMap.bin diff --git a/fuzz/test_differential_fuzzer_seed_corpus/WeatherUnderground b/fuzz/test_differential_fuzzer_seed_corpus/WeatherUnderground.bin similarity index 100% rename from fuzz/test_differential_fuzzer_seed_corpus/WeatherUnderground rename to fuzz/test_differential_fuzzer_seed_corpus/WeatherUnderground.bin