diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-29 04:21:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-29 04:21:29 +0000 |
commit | 683f1f3ddde13390781318b9fe4a6841ea35d145 (patch) | |
tree | c21fddf99f2e5233bb3f22bbafd0d711fe7c5d95 /fuzzer/fuzz.py | |
parent | Initial commit. (diff) | |
download | python-tomli-upstream.tar.xz python-tomli-upstream.zip |
Adding upstream version 2.0.1.upstream/2.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'fuzzer/fuzz.py')
-rw-r--r-- | fuzzer/fuzz.py | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/fuzzer/fuzz.py b/fuzzer/fuzz.py new file mode 100644 index 0000000..a97b2f7 --- /dev/null +++ b/fuzzer/fuzz.py @@ -0,0 +1,79 @@ +import atheris + +with atheris.instrument_imports(): + from math import isnan + import sys + import warnings + + import tomli_w + + import tomli + +# Disable any caching used so that the same lines of code run +# on a given input consistently. +tomli._re.cached_tz = tomli._re.cached_tz.__wrapped__ + +# Suppress all warnings. +warnings.simplefilter("ignore") + + +def test_one_input(input_bytes: bytes) -> None: + # We need a Unicode string, not bytes + fdp = atheris.FuzzedDataProvider(input_bytes) + data = fdp.ConsumeUnicode(sys.maxsize) + + try: + toml_obj = tomli.loads(data) + except (tomli.TOMLDecodeError, RecursionError): + return + except BaseException: + print_err(data) + raise + + try: + recovered_data = tomli_w.dumps(toml_obj) + except RecursionError: + return + except BaseException: + print_err(data) + raise + + roundtripped_obj = tomli.loads(recovered_data) + normalize_toml_obj(roundtripped_obj) + normalize_toml_obj(toml_obj) + if roundtripped_obj != toml_obj: + sys.stderr.write( + f"Original dict:\n{toml_obj}\nRoundtripped dict:\n{roundtripped_obj}\n" + ) + sys.stderr.flush() + print_err(data) + raise Exception("Dicts not equal after roundtrip") + + +def print_err(data): + codepoints = [hex(ord(x)) for x in data] + sys.stderr.write(f"Input was {type(data)}:\n{data}\nCodepoints:\n{codepoints}\n") + sys.stderr.flush() + + +def normalize_toml_obj(toml_obj: dict) -> None: + """Make NaNs equal when compared (without using recursion).""" + to_process = [toml_obj] + while to_process: + cont = to_process.pop() + for k, v in cont.items() if isinstance(cont, dict) else enumerate(cont): + if isinstance(v, float) and isnan(v): + cont[k] = "nan" + elif isinstance(v, (dict, list)): + to_process.append(v) + + +def main(): + # For possible options, see https://llvm.org/docs/LibFuzzer.html#options + fuzzer_options = sys.argv + atheris.Setup(fuzzer_options, test_one_input) + atheris.Fuzz() + + +if __name__ == "__main__": + main() |