From e4675fa2780e6fac8eac7f534f8323edd8825221 Mon Sep 17 00:00:00 2001 From: David Korczynski Date: Wed, 6 Apr 2022 14:27:58 +0100 Subject: [PATCH 1/2] Add initial fuzz test Initial fuzz test for string operations roundtrip --- tests/fuzz_roundtrip.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/fuzz_roundtrip.py diff --git a/tests/fuzz_roundtrip.py b/tests/fuzz_roundtrip.py new file mode 100644 index 0000000..5edf616 --- /dev/null +++ b/tests/fuzz_roundtrip.py @@ -0,0 +1,34 @@ +import sys +import atheris + +with atheris.instrument_imports(): + import rsa + +@atheris.instrument_func +def TestOneInput(input_bytes): + fdp = atheris.FuzzedDataProvider(input_bytes) + key = fdp.ConsumeIntInRange(16, 9999) + message = fdp.ConsumeBytes(atheris.ALL_REMAINING) + + try: + pub, priv = rsa.newkeys(key) + except ValueError: + return + + try: + encrypted = rsa.encrypt(message, pub) + except OverflowError: + return + + decrypted = rsa.decrypt(encrypted, priv) + assert(decrypted == message) + + +def main(): + atheris.instrument_all() + atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) + atheris.Fuzz() + + +if __name__ == "__main__": + main() From e56465b2d43d82d0306c4891a7161113859f1cec Mon Sep 17 00:00:00 2001 From: David Korczynski Date: Tue, 19 Apr 2022 11:17:53 +0100 Subject: [PATCH 2/2] nit --- {tests => fuzz}/fuzz_roundtrip.py | 8 ++++++++ 1 file changed, 8 insertions(+) rename {tests => fuzz}/fuzz_roundtrip.py (55%) diff --git a/tests/fuzz_roundtrip.py b/fuzz/fuzz_roundtrip.py similarity index 55% rename from tests/fuzz_roundtrip.py rename to fuzz/fuzz_roundtrip.py index 5edf616..1c54f1b 100644 --- a/tests/fuzz_roundtrip.py +++ b/fuzz/fuzz_roundtrip.py @@ -13,11 +13,19 @@ def TestOneInput(input_bytes): try: pub, priv = rsa.newkeys(key) except ValueError: + # newskeys raises a ValueError in the event of a legit error. The fuzzer + # will often generate input that triggers such errors, and we can simply + # ignore them, although the fuzzer should continue running and thus we + # return. return try: encrypted = rsa.encrypt(message, pub) except OverflowError: + # encrypt calls into _pad_for_encryption which raises an overflow error. + # Similar to above, the fuzzer will generate inputs that trigger this + # exception and in this event we simply want the fuzzer to continue. + # As such, we return so the fuzzer can continue with its next iteration. return decrypted = rsa.decrypt(encrypted, priv)