From 52c3ebf63169a8d89bae0a465ed00055b65147ab Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Tue, 19 May 2020 20:48:52 +0300 Subject: [PATCH] Fuzzing tests for SSZ --- scripts/run_ssz_fuzzing_test.nims | 46 +++++++++++++++++++ tests/fuzzing/.gitignore | 2 + tests/fuzzing/ssz_decode_Attestation.nim | 4 ++ tests/fuzzing/ssz_decode_AttesterSlashing.nim | 4 ++ tests/fuzzing/ssz_decode_BeaconState.nim | 4 ++ tests/fuzzing/ssz_decode_ProposerSlashing.nim | 4 ++ .../ssz_decode_SignedAggregateAndProof.nim | 4 ++ .../fuzzing/ssz_decode_SignedBeaconBlock.nim | 4 ++ tests/fuzzing/ssz_decode_VoluntaryExit.nim | 4 ++ tests/fuzzing/ssz_fuzzing.nim | 31 +++++++++++++ vendor/nim-testutils | 2 +- 11 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 scripts/run_ssz_fuzzing_test.nims create mode 100644 tests/fuzzing/.gitignore create mode 100644 tests/fuzzing/ssz_decode_Attestation.nim create mode 100644 tests/fuzzing/ssz_decode_AttesterSlashing.nim create mode 100644 tests/fuzzing/ssz_decode_BeaconState.nim create mode 100644 tests/fuzzing/ssz_decode_ProposerSlashing.nim create mode 100644 tests/fuzzing/ssz_decode_SignedAggregateAndProof.nim create mode 100644 tests/fuzzing/ssz_decode_SignedBeaconBlock.nim create mode 100644 tests/fuzzing/ssz_decode_VoluntaryExit.nim create mode 100644 tests/fuzzing/ssz_fuzzing.nim diff --git a/scripts/run_ssz_fuzzing_test.nims b/scripts/run_ssz_fuzzing_test.nims new file mode 100644 index 000000000..ae7ea9900 --- /dev/null +++ b/scripts/run_ssz_fuzzing_test.nims @@ -0,0 +1,46 @@ +import os except dirExists +import strformat, confutils + +const + gitRoot = thisDir() / ".." + fixturesDir = gitRoot / "vendor" / "nim-eth2-scenarios" / "tests-v0.11.2" / "mainnet" / "phase0" / "ssz_static" + + fuzzingTestsDir = gitRoot / "tests" / "fuzzing" + fuzzingCorpusesDir = fuzzingTestsDir / "corpus" + + fuzzNims = gitRoot / "vendor" / "nim-testutils" / "testutils" / "fuzzing" / "fuzz.nims" + +type + FuzzerKind = enum + libFuzzer + afl + +cli do (testname {.argument.}: string, + fuzzer = libFuzzer): + + if not dirExists(fixturesDir): + echo "Please run `make test` first in order to download the official ETH2 test vectors" + quit 1 + + if not dirExists(fixturesDir / testname): + echo testname, " is not a recognized SSZ type name (type names are case-sensitive)" + quit 1 + + let corpusDir = fuzzingCorpusesDir / testname + + rmDir corpusDir + mkDir corpusDir + + var inputIdx = 0 + template nextInputName: string = + inc inputIdx + "input" & $inputIdx + + for file in walkDirRec(fixturesDir / testname): + if splitFile(file).ext == ".ssz": + # TODO Can we create hard links here? + cpFile file, corpusDir / nextInputName() + + let testProgram = fuzzingTestsDir / &"ssz_decode_{testname}.nim" + + exec &"""nim "{fuzzNims}" "{fuzzer}" "{testProgram}" "{corpusDir}" """ diff --git a/tests/fuzzing/.gitignore b/tests/fuzzing/.gitignore new file mode 100644 index 000000000..ff2dcff2a --- /dev/null +++ b/tests/fuzzing/.gitignore @@ -0,0 +1,2 @@ +corpus/ + diff --git a/tests/fuzzing/ssz_decode_Attestation.nim b/tests/fuzzing/ssz_decode_Attestation.nim new file mode 100644 index 000000000..eaf2b98ae --- /dev/null +++ b/tests/fuzzing/ssz_decode_Attestation.nim @@ -0,0 +1,4 @@ +import ssz_fuzzing + +sszFuzzingTest Attestation + diff --git a/tests/fuzzing/ssz_decode_AttesterSlashing.nim b/tests/fuzzing/ssz_decode_AttesterSlashing.nim new file mode 100644 index 000000000..1f4376e85 --- /dev/null +++ b/tests/fuzzing/ssz_decode_AttesterSlashing.nim @@ -0,0 +1,4 @@ +import ssz_fuzzing + +sszFuzzingTest AttesterSlashing + diff --git a/tests/fuzzing/ssz_decode_BeaconState.nim b/tests/fuzzing/ssz_decode_BeaconState.nim new file mode 100644 index 000000000..f78120be4 --- /dev/null +++ b/tests/fuzzing/ssz_decode_BeaconState.nim @@ -0,0 +1,4 @@ +import ssz_fuzzing + +sszFuzzingTest BeaconState + diff --git a/tests/fuzzing/ssz_decode_ProposerSlashing.nim b/tests/fuzzing/ssz_decode_ProposerSlashing.nim new file mode 100644 index 000000000..ae3bb09fb --- /dev/null +++ b/tests/fuzzing/ssz_decode_ProposerSlashing.nim @@ -0,0 +1,4 @@ +import ssz_fuzzing + +sszFuzzingTest ProposerSlashing + diff --git a/tests/fuzzing/ssz_decode_SignedAggregateAndProof.nim b/tests/fuzzing/ssz_decode_SignedAggregateAndProof.nim new file mode 100644 index 000000000..25c1b28d3 --- /dev/null +++ b/tests/fuzzing/ssz_decode_SignedAggregateAndProof.nim @@ -0,0 +1,4 @@ +import ssz_fuzzing + +sszFuzzingTest SignedAggregateAndProof + diff --git a/tests/fuzzing/ssz_decode_SignedBeaconBlock.nim b/tests/fuzzing/ssz_decode_SignedBeaconBlock.nim new file mode 100644 index 000000000..484d6b799 --- /dev/null +++ b/tests/fuzzing/ssz_decode_SignedBeaconBlock.nim @@ -0,0 +1,4 @@ +import ssz_fuzzing + +sszFuzzingTest SignedBeaconBlock + diff --git a/tests/fuzzing/ssz_decode_VoluntaryExit.nim b/tests/fuzzing/ssz_decode_VoluntaryExit.nim new file mode 100644 index 000000000..1671c4cdc --- /dev/null +++ b/tests/fuzzing/ssz_decode_VoluntaryExit.nim @@ -0,0 +1,4 @@ +import ssz_fuzzing + +sszFuzzingTest SignedVoluntaryExit + diff --git a/tests/fuzzing/ssz_fuzzing.nim b/tests/fuzzing/ssz_fuzzing.nim new file mode 100644 index 000000000..c2b016a70 --- /dev/null +++ b/tests/fuzzing/ssz_fuzzing.nim @@ -0,0 +1,31 @@ +import + testutils/fuzzing, faststreams/inputs, + ../../beacon_chain/ssz, + ../../beacon_chain/spec/[datatypes, crypto, digest, datatypes] + +export + ssz, datatypes, crypto, digest, fuzzing + +template sszFuzzingTest*(T: type) = + test: + block: + let input = unsafeMemoryInput(payload) + let decoded = try: input.readValue(SSZ, T) + except SSZError: break + + if input.len.get > 0: + # Some unconsumed input remained, this is not a valid test case + break + + let reEncoded = SSZ.encode(decoded) + + if payload != reEncoded: + echo "Payload with len = ", payload.len + echo payload + echo "Re-encoided payload with len = ", reEncoded.len + echo reEncoded + + echo repr(decoded) + + doAssert false + diff --git a/vendor/nim-testutils b/vendor/nim-testutils index 4edb4c9ae..e508aea59 160000 --- a/vendor/nim-testutils +++ b/vendor/nim-testutils @@ -1 +1 @@ -Subproject commit 4edb4c9ae41f8f6fc7489dca63d1d9f5a48e37cd +Subproject commit e508aea59f6d4699c6e237a6935a5ff785c8c50d