From 7df01feb588c9da53fb55ceab950321497325155 Mon Sep 17 00:00:00 2001 From: Preston Van Loon Date: Wed, 19 Jan 2022 22:51:02 -0600 Subject: [PATCH] Remove libfuzzer / afl based builds in favor of go 1.18 fuzz testing (#10065) * Remove libfuzzer / afl based builds in favor of go 1.18 fuzz testing * rm beacon-fuzz archive Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> --- .bazelrc | 15 +- .buildkite-bazelrc | 3 - .gitignore | 4 - BUILD.bazel | 9 - WORKSPACE | 10 - beacon-chain/blockchain/BUILD.bazel | 1 - beacon-chain/blockchain/testing/BUILD.bazel | 1 - beacon-chain/cache/BUILD.bazel | 26 +- beacon-chain/cache/active_balance.go | 2 +- beacon-chain/cache/active_balance_disabled.go | 2 +- beacon-chain/cache/committee.go | 2 +- beacon-chain/cache/committee_disabled.go | 2 +- beacon-chain/cache/proposer_indices.go | 2 +- .../cache/proposer_indices_disabled.go | 2 +- beacon-chain/cache/sync_committee.go | 2 +- beacon-chain/cache/sync_committee_disabled.go | 2 +- beacon-chain/core/blocks/BUILD.bazel | 1 - beacon-chain/core/helpers/BUILD.bazel | 2 - beacon-chain/core/transition/BUILD.bazel | 1 - beacon-chain/db/BUILD.bazel | 1 - beacon-chain/db/kv/BUILD.bazel | 1 - .../forkchoice/protoarray/BUILD.bazel | 1 - .../operations/attestations/BUILD.bazel | 1 - beacon-chain/operations/slashings/BUILD.bazel | 1 - .../operations/voluntaryexits/BUILD.bazel | 1 - beacon-chain/p2p/BUILD.bazel | 1 - beacon-chain/p2p/encoder/BUILD.bazel | 1 - beacon-chain/p2p/testing/BUILD.bazel | 1 - beacon-chain/powchain/testing/BUILD.bazel | 1 - beacon-chain/state/BUILD.bazel | 1 - beacon-chain/state/stategen/BUILD.bazel | 1 - beacon-chain/state/stateutil/BUILD.bazel | 1 - beacon-chain/state/v1/BUILD.bazel | 1 - beacon-chain/sync/fuzz_exports.go | 4 +- .../sync/initial-sync/testing/BUILD.bazel | 1 - crypto/bls/blst/stub.go | 2 +- deps.bzl | 4 - fuzzbuzz.yaml | 2 +- hack/update-go-ssz.sh | 2 +- hack/upload_fuzzers.sh | 15 - testing/fuzz/BUILD.bazel | 219 - testing/fuzz/README.md | 102 - testing/fuzz/block_fuzz.go | 204 - testing/fuzz/common.go | 20 - testing/fuzz/generated.ssz.go | 136 - testing/fuzz/inputs.go | 11 - testing/fuzz/rpc_status_corpus/.gitkeep | 0 testing/fuzz/rpc_status_fuzz.go | 85 - testing/fuzz/ssz_encoder_attestations_fuzz.go | 27 - testing/fuzz/state_fuzz.go | 65 - testing/fuzz/testing/BUILD.bazel | 25 - testing/fuzz/testing/beacon_fuzz_states.go | 39 - .../fuzz/testing/beacon_fuzz_states_test.go | 12 - third_party/afl/BUILD.bazel | 80 - third_party/afl/afl-fuzz | Bin 794688 -> 0 bytes third_party/afl/afl-fuzz.c | 8099 ----------------- third_party/afl/afl-showmap.c | 780 -- third_party/afl/afl_driver.cpp | 277 - third_party/afl/alloc-inl.h | 570 -- third_party/afl/config.h | 350 - third_party/afl/debug.h | 251 - third_party/afl/hash.h | 104 - third_party/afl/llvm_mode/afl-llvm-rt.o.c | 306 - third_party/afl/types.h | 86 - third_party/beacon-fuzz/corpora.BUILD | 60 - third_party/herumi/bls_eth_go_binary.BUILD | 1 - tools/BUILD.bazel | 6 - tools/fuzz_wrapper.sh | 8 - tools/go/BUILD.bazel | 6 - tools/go/def.bzl | 22 +- tools/go/fuzz.bzl | 233 - 71 files changed, 25 insertions(+), 12292 deletions(-) delete mode 100755 hack/upload_fuzzers.sh delete mode 100644 testing/fuzz/BUILD.bazel delete mode 100644 testing/fuzz/README.md delete mode 100644 testing/fuzz/block_fuzz.go delete mode 100644 testing/fuzz/common.go delete mode 100644 testing/fuzz/generated.ssz.go delete mode 100644 testing/fuzz/inputs.go delete mode 100644 testing/fuzz/rpc_status_corpus/.gitkeep delete mode 100644 testing/fuzz/rpc_status_fuzz.go delete mode 100644 testing/fuzz/ssz_encoder_attestations_fuzz.go delete mode 100644 testing/fuzz/state_fuzz.go delete mode 100644 testing/fuzz/testing/BUILD.bazel delete mode 100644 testing/fuzz/testing/beacon_fuzz_states.go delete mode 100644 testing/fuzz/testing/beacon_fuzz_states_test.go delete mode 100644 third_party/afl/BUILD.bazel delete mode 100755 third_party/afl/afl-fuzz delete mode 100644 third_party/afl/afl-fuzz.c delete mode 100644 third_party/afl/afl-showmap.c delete mode 100644 third_party/afl/afl_driver.cpp delete mode 100644 third_party/afl/alloc-inl.h delete mode 100644 third_party/afl/config.h delete mode 100644 third_party/afl/debug.h delete mode 100644 third_party/afl/hash.h delete mode 100644 third_party/afl/llvm_mode/afl-llvm-rt.o.c delete mode 100644 third_party/afl/types.h delete mode 100644 third_party/beacon-fuzz/corpora.BUILD delete mode 100755 tools/fuzz_wrapper.sh delete mode 100644 tools/go/fuzz.bzl diff --git a/.bazelrc b/.bazelrc index 65b4412f2..6a8f445b4 100644 --- a/.bazelrc +++ b/.bazelrc @@ -62,20 +62,7 @@ build:llvm-asan --config=llvm build:llvm-asan --config=asan build:llvm-asan --linkopt -fuse-ld=ld.lld -build:fuzz --define=gotags=libfuzzer -build:fuzz --config=llvm-asan -build:fuzz --copt=-fsanitize=fuzzer-no-link -build:fuzz --linkopt=-fsanitize=fuzzer -build:fuzz --copt=-fno-omit-frame-pointer -build:fuzz --define=FUZZING_ENGINE=libfuzzer -build:fuzz --copt=-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -build:fuzz --linkopt -Wl,--no-as-needed -build:fuzz --define=gc_goopts=-d=libfuzzer,checkptr -build:fuzz --run_under=//tools:fuzz_wrapper -build:fuzz --compilation_mode=opt -build:fuzz --define=blst_disabled=true - -test:fuzz --local_test_jobs="HOST_CPUS*.5" +build:fuzz --@io_bazel_rules_go//go/config:tags=fuzz # Build binary with cgo symbolizer for debugging / profiling. build:cgo_symbolizer --config=llvm diff --git a/.buildkite-bazelrc b/.buildkite-bazelrc index 5cd30b5d6..82505645a 100644 --- a/.buildkite-bazelrc +++ b/.buildkite-bazelrc @@ -41,9 +41,6 @@ build --flaky_test_attempts=5 # Disabled race detection due to unstable test results under constrained environment build kite # build --features=race -# Disable flaky test detection for fuzzing. -test:fuzz --flaky_test_attempts=1 - # Better caching build:nostamp --nostamp build:nostamp --workspace_status_command=./hack/workspace_status_ci.sh diff --git a/.gitignore b/.gitignore index 612f4e09b..eff3603cb 100644 --- a/.gitignore +++ b/.gitignore @@ -30,9 +30,5 @@ password.txt # Dist files dist -# libfuzzer -oom-* -crash-* - # deepsource cli bin diff --git a/BUILD.bazel b/BUILD.bazel index 4df3c1b78..4e4367179 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -144,15 +144,6 @@ common_files = { "//:README.md": "README.md", } -string_setting( - name = "gotags", - build_setting_default = "", - values = [ - "", - "libfuzzer", - ], -) - sh_binary( name = "prysm_sh", srcs = ["prysm.sh"], diff --git a/WORKSPACE b/WORKSPACE index 477f54f96..870c8d8d5 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -341,16 +341,6 @@ git_repository( # Group the sources of the library so that CMake rule have access to it all_content = """filegroup(name = "all", srcs = glob(["**"]), visibility = ["//visibility:public"])""" -http_archive( - name = "sigp_beacon_fuzz_corpora", - build_file = "//third_party:beacon-fuzz/corpora.BUILD", - sha256 = "42993d0901a316afda45b4ba6d53c7c21f30c551dcec290a4ca131c24453d1ef", - strip_prefix = "beacon-fuzz-corpora-bac24ad78d45cc3664c0172241feac969c1ac29b", - urls = [ - "https://github.com/sigp/beacon-fuzz-corpora/archive/bac24ad78d45cc3664c0172241feac969c1ac29b.tar.gz", - ], -) - # External dependencies http_archive( diff --git a/beacon-chain/blockchain/BUILD.bazel b/beacon-chain/blockchain/BUILD.bazel index 9e942c559..e10da6186 100644 --- a/beacon-chain/blockchain/BUILD.bazel +++ b/beacon-chain/blockchain/BUILD.bazel @@ -25,7 +25,6 @@ go_library( visibility = [ "//beacon-chain:__subpackages__", "//cmd/beacon-chain:__subpackages__", - "//testing/fuzz:__pkg__", "//testing/slasher/simulator:__pkg__", ], deps = [ diff --git a/beacon-chain/blockchain/testing/BUILD.bazel b/beacon-chain/blockchain/testing/BUILD.bazel index d16619edd..80ff591b9 100644 --- a/beacon-chain/blockchain/testing/BUILD.bazel +++ b/beacon-chain/blockchain/testing/BUILD.bazel @@ -8,7 +8,6 @@ go_library( visibility = [ "//beacon-chain:__subpackages__", "//testing:__subpackages__", - "//testing/fuzz:__pkg__", ], deps = [ "//async/event:go_default_library", diff --git a/beacon-chain/cache/BUILD.bazel b/beacon-chain/cache/BUILD.bazel index 392dd4daa..8494ca1aa 100644 --- a/beacon-chain/cache/BUILD.bazel +++ b/beacon-chain/cache/BUILD.bazel @@ -1,39 +1,31 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") -# gazelle:exclude committee_disabled.go -# gazelle:exclude proposer_indices_disabled.go go_library( name = "go_default_library", srcs = [ + "active_balance.go", + "active_balance_disabled.go", # keep "attestation_data.go", "checkpoint_state.go", + "committee.go", + "committee_disabled.go", # keep "committees.go", "common.go", "doc.go", "error.go", + "proposer_indices.go", + "proposer_indices_disabled.go", # keep "proposer_indices_type.go", "skip_slot_cache.go", "subnet_ids.go", + "sync_committee.go", + "sync_committee_disabled.go", # keep "sync_committee_head_state.go", "sync_subnet_ids.go", - ] + select({ - "//testing/fuzz:fuzzing_enabled": [ - "active_balance_disabled.go", - "committee_disabled.go", - "proposer_indices_disabled.go", - "sync_committee_disabled.go", - ], - "//conditions:default": [ - "active_balance.go", - "committee.go", - "proposer_indices.go", - "sync_committee.go", - ], - }), + ], importpath = "github.com/prysmaticlabs/prysm/beacon-chain/cache", visibility = [ "//beacon-chain:__subpackages__", - "//testing/fuzz:__pkg__", "//tools:__subpackages__", ], deps = [ diff --git a/beacon-chain/cache/active_balance.go b/beacon-chain/cache/active_balance.go index e20e384ed..053a7514f 100644 --- a/beacon-chain/cache/active_balance.go +++ b/beacon-chain/cache/active_balance.go @@ -1,4 +1,4 @@ -// +build !libfuzzer +// +build !fuzz package cache diff --git a/beacon-chain/cache/active_balance_disabled.go b/beacon-chain/cache/active_balance_disabled.go index 2796a285d..1014080bc 100644 --- a/beacon-chain/cache/active_balance_disabled.go +++ b/beacon-chain/cache/active_balance_disabled.go @@ -1,4 +1,4 @@ -// +build libfuzzer +// +build fuzz package cache diff --git a/beacon-chain/cache/committee.go b/beacon-chain/cache/committee.go index 063cf7e05..3babe2656 100644 --- a/beacon-chain/cache/committee.go +++ b/beacon-chain/cache/committee.go @@ -1,4 +1,4 @@ -// +build !libfuzzer +// +build !fuzz package cache diff --git a/beacon-chain/cache/committee_disabled.go b/beacon-chain/cache/committee_disabled.go index 62190dda2..a003d3455 100644 --- a/beacon-chain/cache/committee_disabled.go +++ b/beacon-chain/cache/committee_disabled.go @@ -1,4 +1,4 @@ -// +build libfuzzer +// +build fuzz // This file is used in fuzzer builds to bypass global committee caches. package cache diff --git a/beacon-chain/cache/proposer_indices.go b/beacon-chain/cache/proposer_indices.go index 78583b209..44089b76a 100644 --- a/beacon-chain/cache/proposer_indices.go +++ b/beacon-chain/cache/proposer_indices.go @@ -1,4 +1,4 @@ -// +build !libfuzzer +// +build !fuzz package cache diff --git a/beacon-chain/cache/proposer_indices_disabled.go b/beacon-chain/cache/proposer_indices_disabled.go index 5e4ede689..2ae1418e5 100644 --- a/beacon-chain/cache/proposer_indices_disabled.go +++ b/beacon-chain/cache/proposer_indices_disabled.go @@ -1,4 +1,4 @@ -// +build libfuzzer +// +build fuzz // This file is used in fuzzer builds to bypass proposer indices caches. package cache diff --git a/beacon-chain/cache/sync_committee.go b/beacon-chain/cache/sync_committee.go index baf15c11d..e00f29fa6 100644 --- a/beacon-chain/cache/sync_committee.go +++ b/beacon-chain/cache/sync_committee.go @@ -1,4 +1,4 @@ -// +build !libfuzzer +// +build !fuzz package cache diff --git a/beacon-chain/cache/sync_committee_disabled.go b/beacon-chain/cache/sync_committee_disabled.go index 68da51f3c..2632e057e 100644 --- a/beacon-chain/cache/sync_committee_disabled.go +++ b/beacon-chain/cache/sync_committee_disabled.go @@ -1,4 +1,4 @@ -// +build libfuzzer +// +build fuzz package cache diff --git a/beacon-chain/core/blocks/BUILD.bazel b/beacon-chain/core/blocks/BUILD.bazel index ee1eea392..8611cbf27 100644 --- a/beacon-chain/core/blocks/BUILD.bazel +++ b/beacon-chain/core/blocks/BUILD.bazel @@ -19,7 +19,6 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks", visibility = [ "//beacon-chain:__subpackages__", - "//testing/fuzz:__pkg__", "//testing/spectest:__subpackages__", "//testing/util:__pkg__", "//validator:__subpackages__", diff --git a/beacon-chain/core/helpers/BUILD.bazel b/beacon-chain/core/helpers/BUILD.bazel index 017422430..44176f61a 100644 --- a/beacon-chain/core/helpers/BUILD.bazel +++ b/beacon-chain/core/helpers/BUILD.bazel @@ -20,7 +20,6 @@ go_library( "//cmd/beacon-chain:__subpackages__", "//contracts/deposit:__pkg__", "//crypto/keystore:__pkg__", - "//fuzz:__pkg__", "//network/forks:__pkg__", "//proto/prysm/v1alpha1:__subpackages__", "//proto/prysm/v1alpha1/attestation:__pkg__", @@ -29,7 +28,6 @@ go_library( "//testing/altair:__pkg__", "//testing/benchmark/benchmark_files:__subpackages__", "//testing/endtoend/evaluators:__pkg__", - "//testing/fuzz:__pkg__", "//testing/slasher/simulator:__pkg__", "//testing/spectest:__subpackages__", "//testing/util:__pkg__", diff --git a/beacon-chain/core/transition/BUILD.bazel b/beacon-chain/core/transition/BUILD.bazel index c17724722..4dfe8c82a 100644 --- a/beacon-chain/core/transition/BUILD.bazel +++ b/beacon-chain/core/transition/BUILD.bazel @@ -15,7 +15,6 @@ go_library( "//beacon-chain:__subpackages__", "//runtime/interop:__pkg__", "//testing/endtoend:__pkg__", - "//testing/fuzz:__pkg__", "//testing/spectest:__subpackages__", "//testing/util:__pkg__", "//tools/benchmark-files-gen:__pkg__", diff --git a/beacon-chain/db/BUILD.bazel b/beacon-chain/db/BUILD.bazel index f7977529a..b14a389b7 100644 --- a/beacon-chain/db/BUILD.bazel +++ b/beacon-chain/db/BUILD.bazel @@ -13,7 +13,6 @@ go_library( visibility = [ "//beacon-chain:__subpackages__", "//cmd/beacon-chain:__subpackages__", - "//testing/fuzz:__pkg__", "//testing/slasher/simulator:__pkg__", "//tools:__subpackages__", ], diff --git a/beacon-chain/db/kv/BUILD.bazel b/beacon-chain/db/kv/BUILD.bazel index 924a4815a..47306c8dc 100644 --- a/beacon-chain/db/kv/BUILD.bazel +++ b/beacon-chain/db/kv/BUILD.bazel @@ -30,7 +30,6 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/db/kv", visibility = [ "//beacon-chain:__subpackages__", - "//testing/fuzz:__pkg__", "//tools:__subpackages__", ], deps = [ diff --git a/beacon-chain/forkchoice/protoarray/BUILD.bazel b/beacon-chain/forkchoice/protoarray/BUILD.bazel index a197780d7..1614b0084 100644 --- a/beacon-chain/forkchoice/protoarray/BUILD.bazel +++ b/beacon-chain/forkchoice/protoarray/BUILD.bazel @@ -14,7 +14,6 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray", visibility = [ "//beacon-chain:__subpackages__", - "//testing/fuzz:__pkg__", ], deps = [ "//config/params:go_default_library", diff --git a/beacon-chain/operations/attestations/BUILD.bazel b/beacon-chain/operations/attestations/BUILD.bazel index 7d8f277fd..26fa214f4 100644 --- a/beacon-chain/operations/attestations/BUILD.bazel +++ b/beacon-chain/operations/attestations/BUILD.bazel @@ -14,7 +14,6 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations", visibility = [ "//beacon-chain:__subpackages__", - "//testing/fuzz:__pkg__", ], deps = [ "//beacon-chain/operations/attestations/kv:go_default_library", diff --git a/beacon-chain/operations/slashings/BUILD.bazel b/beacon-chain/operations/slashings/BUILD.bazel index 0ebc25b11..7f004a1d4 100644 --- a/beacon-chain/operations/slashings/BUILD.bazel +++ b/beacon-chain/operations/slashings/BUILD.bazel @@ -14,7 +14,6 @@ go_library( visibility = [ "//beacon-chain:__subpackages__", "//testing/endtoend:__subpackages__", - "//testing/fuzz:__pkg__", "//testing/slasher/simulator:__pkg__", ], deps = [ diff --git a/beacon-chain/operations/voluntaryexits/BUILD.bazel b/beacon-chain/operations/voluntaryexits/BUILD.bazel index ad3dde9f5..169f60bfb 100644 --- a/beacon-chain/operations/voluntaryexits/BUILD.bazel +++ b/beacon-chain/operations/voluntaryexits/BUILD.bazel @@ -10,7 +10,6 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits", visibility = [ "//beacon-chain:__subpackages__", - "//testing/fuzz:__pkg__", ], deps = [ "//beacon-chain/state:go_default_library", diff --git a/beacon-chain/p2p/BUILD.bazel b/beacon-chain/p2p/BUILD.bazel index b4d86513f..9ecddb939 100644 --- a/beacon-chain/p2p/BUILD.bazel +++ b/beacon-chain/p2p/BUILD.bazel @@ -36,7 +36,6 @@ go_library( visibility = [ "//beacon-chain:__subpackages__", "//testing/endtoend/evaluators:__pkg__", - "//testing/fuzz:__pkg__", "//tools:__subpackages__", ], deps = [ diff --git a/beacon-chain/p2p/encoder/BUILD.bazel b/beacon-chain/p2p/encoder/BUILD.bazel index a62343ae9..130714c9c 100644 --- a/beacon-chain/p2p/encoder/BUILD.bazel +++ b/beacon-chain/p2p/encoder/BUILD.bazel @@ -11,7 +11,6 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder", visibility = [ "//beacon-chain:__subpackages__", - "//testing/fuzz:__pkg__", ], deps = [ "//config/params:go_default_library", diff --git a/beacon-chain/p2p/testing/BUILD.bazel b/beacon-chain/p2p/testing/BUILD.bazel index 225d32423..4610da074 100644 --- a/beacon-chain/p2p/testing/BUILD.bazel +++ b/beacon-chain/p2p/testing/BUILD.bazel @@ -15,7 +15,6 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing", visibility = [ "//beacon-chain:__subpackages__", - "//testing/fuzz:__pkg__", ], deps = [ "//beacon-chain/p2p/encoder:go_default_library", diff --git a/beacon-chain/powchain/testing/BUILD.bazel b/beacon-chain/powchain/testing/BUILD.bazel index 9c79e0a95..27ed25ee9 100644 --- a/beacon-chain/powchain/testing/BUILD.bazel +++ b/beacon-chain/powchain/testing/BUILD.bazel @@ -10,7 +10,6 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing", visibility = [ "//beacon-chain:__subpackages__", - "//testing/fuzz:__pkg__", ], deps = [ "//async/event:go_default_library", diff --git a/beacon-chain/state/BUILD.bazel b/beacon-chain/state/BUILD.bazel index e303a754a..0f8afeed2 100644 --- a/beacon-chain/state/BUILD.bazel +++ b/beacon-chain/state/BUILD.bazel @@ -16,7 +16,6 @@ go_library( "//proto/testing:__subpackages__", "//slasher/rpc:__subpackages__", "//testing/benchmark:__pkg__", - "//testing/fuzz:__pkg__", "//testing/slasher/simulator:__pkg__", "//testing/spectest:__subpackages__", "//testing/util:__pkg__", diff --git a/beacon-chain/state/stategen/BUILD.bazel b/beacon-chain/state/stategen/BUILD.bazel index 65b356d5a..27246a9fd 100644 --- a/beacon-chain/state/stategen/BUILD.bazel +++ b/beacon-chain/state/stategen/BUILD.bazel @@ -19,7 +19,6 @@ go_library( visibility = [ "//beacon-chain:__subpackages__", "//testing/endtoend:__subpackages__", - "//testing/fuzz:__pkg__", "//testing/slasher/simulator:__pkg__", ], deps = [ diff --git a/beacon-chain/state/stateutil/BUILD.bazel b/beacon-chain/state/stateutil/BUILD.bazel index d12d063e1..f5840471d 100644 --- a/beacon-chain/state/stateutil/BUILD.bazel +++ b/beacon-chain/state/stateutil/BUILD.bazel @@ -26,7 +26,6 @@ go_library( "//proto/testing:__subpackages__", "//slasher:__subpackages__", "//testing:__subpackages__", - "//testing/fuzz:__pkg__", "//tools/blocktree:__pkg__", "//tools/pcli:__pkg__", "//validator/client:__pkg__", diff --git a/beacon-chain/state/v1/BUILD.bazel b/beacon-chain/state/v1/BUILD.bazel index 55b7b5759..a1763a074 100644 --- a/beacon-chain/state/v1/BUILD.bazel +++ b/beacon-chain/state/v1/BUILD.bazel @@ -38,7 +38,6 @@ go_library( "//runtime/interop:__subpackages__", "//slasher/rpc:__subpackages__", "//testing/benchmark:__pkg__", - "//testing/fuzz:__pkg__", "//testing/spectest:__subpackages__", "//testing/util:__pkg__", "//tools/benchmark-files-gen:__pkg__", diff --git a/beacon-chain/sync/fuzz_exports.go b/beacon-chain/sync/fuzz_exports.go index 9576d2641..28de03e17 100644 --- a/beacon-chain/sync/fuzz_exports.go +++ b/beacon-chain/sync/fuzz_exports.go @@ -1,5 +1,5 @@ -//go:build libfuzzer -// +build libfuzzer +//go:build fuzz +// +build fuzz package sync diff --git a/beacon-chain/sync/initial-sync/testing/BUILD.bazel b/beacon-chain/sync/initial-sync/testing/BUILD.bazel index c1db6c915..da5fc4379 100644 --- a/beacon-chain/sync/initial-sync/testing/BUILD.bazel +++ b/beacon-chain/sync/initial-sync/testing/BUILD.bazel @@ -7,6 +7,5 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing", visibility = [ "//beacon-chain:__subpackages__", - "//testing/fuzz:__pkg__", ], ) diff --git a/crypto/bls/blst/stub.go b/crypto/bls/blst/stub.go index c9b346b4f..69336bf62 100644 --- a/crypto/bls/blst/stub.go +++ b/crypto/bls/blst/stub.go @@ -1,4 +1,4 @@ -// +build blst_disabled libfuzzer +// +build blst_disabled fuzz package blst diff --git a/deps.bzl b/deps.bzl index e4a8a389b..6ce3c9a32 100644 --- a/deps.bzl +++ b/deps.bzl @@ -845,7 +845,6 @@ def prysm_deps(): go_repository( name = "com_github_ferranbt_fastssz", importpath = "github.com/ferranbt/fastssz", - nofuzz = True, replace = "github.com/prysmaticlabs/fastssz", sum = "h1:BC9nIbhpQMyFlmLUJsVv8/+UewAVIjJegtvgaP9bV/M=", version = "v0.0.0-20211123050228-97d96f38caae", @@ -938,7 +937,6 @@ def prysm_deps(): go_repository( name = "com_github_ghodss_yaml", importpath = "github.com/ghodss/yaml", - nofuzz = True, sum = "h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=", version = "v1.0.0", ) @@ -1123,7 +1121,6 @@ def prysm_deps(): go_repository( name = "com_github_golang_glog", importpath = "github.com/golang/glog", - nofuzz = True, sum = "h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=", version = "v0.0.0-20160126235308-23def4e6c14b", ) @@ -3995,7 +3992,6 @@ def prysm_deps(): go_repository( name = "in_gopkg_yaml_v2", importpath = "gopkg.in/yaml.v2", - nofuzz = True, sum = "h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=", version = "v2.4.0", ) diff --git a/fuzzbuzz.yaml b/fuzzbuzz.yaml index 85778da50..8236b8e3f 100644 --- a/fuzzbuzz.yaml +++ b/fuzzbuzz.yaml @@ -2,5 +2,5 @@ base: language: go docker_image: golang:latest build_tags: - - libfuzzer + - fuzz - blst_disabled diff --git a/hack/update-go-ssz.sh b/hack/update-go-ssz.sh index 8ec5141ba..dcfa6776d 100755 --- a/hack/update-go-ssz.sh +++ b/hack/update-go-ssz.sh @@ -4,7 +4,7 @@ # Script to copy ssz.go files from bazel build folder to appropriate location. # Bazel builds to bazel-bin/... folder, script copies them back to original folder where target is. -bazel query 'kind(ssz_gen_marshal, //proto/...) union kind(ssz_gen_marshal, //testing/fuzz/...)' | xargs bazel build +bazel query 'kind(ssz_gen_marshal, //proto/...)' | xargs bazel build # Get locations of proto ssz.go files. file_list=() diff --git a/hack/upload_fuzzers.sh b/hack/upload_fuzzers.sh deleted file mode 100755 index 46d555c13..000000000 --- a/hack/upload_fuzzers.sh +++ /dev/null @@ -1,15 +0,0 @@ -# Fuzzer bundle uploads -# -# This script builds the appropriate fuzzing bundles and uploads them to the google cloud bucket. -# Clusterfuzz will pick up the new fuzz bundles as fuzzing jobs are run. - -# Build targets. -bazel build --config=fuzz --config=nostamp \ - //testing/fuzz:block_fuzz_test_libfuzzer_bundle \ - //testing/fuzz:state_fuzz_test_libfuzzer_bundle \ - //testing/fuzz:ssz_encoder_attestations_test_libfuzzer_bundle - -# Upload bundles with date timestamps in the filename. -gsutil cp bazel-bin/fuzz/block_fuzz_test_libfuzzer_bundle.zip gs://builds.prysmaticlabs.appspot.com/libfuzzer_asan_blocks/fuzzer-build-"$(date +%Y%m%d%H%M)".zip -gsutil cp bazel-bin/fuzz/state_fuzz_test_libfuzzer_bundle.zip gs://builds.prysmaticlabs.appspot.com/libfuzzer_asan_state/fuzzer-build-"$(date +%Y%m%d%H%M)".zip -gsutil cp bazel-bin/fuzz/ssz_encoder_attestations_test_libfuzzer_bundle.zip gs://builds.prysmaticlabs.appspot.com/libfuzzer_asan_ssz_encoder_attestations/fuzzer-build-"$(date +%Y%m%d%H%M)".zip diff --git a/testing/fuzz/BUILD.bazel b/testing/fuzz/BUILD.bazel deleted file mode 100644 index 4c7c5efa7..000000000 --- a/testing/fuzz/BUILD.bazel +++ /dev/null @@ -1,219 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library") -load("//tools/go:fuzz.bzl", "go_fuzz_test") -load("//tools:ssz.bzl", "SSZ_DEPS", "ssz_gen_marshal") -load("@io_bazel_rules_docker//container:container.bzl", "container_image", "container_push") -load("@io_bazel_rules_go//go:def.bzl", "go_test") - -# gazelle:ignore - -config_setting( - name = "fuzzing_enabled", - values = {"define": "gotags=libfuzzer"}, -) - -ssz_gen_marshal( - name = "ssz_generated_files", - srcs = ["inputs.go"], - includes = [ - "//proto/prysm/v1alpha1:go_default_library", - "@com_github_prysmaticlabs_eth2_types//:go_default_library", - ], - objs = [ - "InputBlockWithPrestate", - ], -) - -IMPORT_PATH = "github.com/prysmaticlabs/prysm/fuzz" - -COMMON_DEPS = [ - "//beacon-chain/state/v1:go_default_library", - "//config/features:go_default_library", -] + SSZ_DEPS - -COMMON_SRCS = [ - "common.go", - "inputs.go", - ":ssz_generated_files", -] - -SRCS = COMMON_SRCS + glob(["*_fuzz.go"]) - -test_suite( - name = "fuzz_tests", - tags = ["manual"], - tests = [ - ":block_fuzz_test_with_libfuzzer", - ":rpc_status_fuzz_test_with_libfuzzer", - ":state_fuzz_test_with_libfuzzer", - ], -) - -go_fuzz_test( - name = "block_fuzz_test", - srcs = [ - "block_fuzz.go", - ] + COMMON_SRCS, - corpus = "@sigp_beacon_fuzz_corpora//:current_mainnet_block_header", - corpus_path = "external/sigp_beacon_fuzz_corpora/0-11-0/mainnet/block_header", - func = "BeaconFuzzBlock", - importpath = IMPORT_PATH, - max_len = 30000000, - deps = [ - "//beacon-chain/core/blocks:go_default_library", - "//beacon-chain/core/transition:go_default_library", - "//testing/fuzz/testing:go_default_library", - "//config/params:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - "//proto/prysm/v1alpha1/block:go_default_library", - "//proto/prysm/v1alpha1/wrapper:go_default_library", - "//beacon-chain/operations/attestations:go_default_library", - "//beacon-chain/p2p/testing:go_default_library", - "//beacon-chain/sync:go_default_library", - "//beacon-chain/db:go_default_library", - "//beacon-chain/db/kv:go_default_library", - "//beacon-chain/operations/voluntaryexits:go_default_library", - "//beacon-chain/blockchain:go_default_library", - "//beacon-chain/operations/slashings:go_default_library", - "//beacon-chain/forkchoice/protoarray:go_default_library", - "//beacon-chain/powchain/testing:go_default_library", - "//testing/util:go_default_library", - "@com_github_libp2p_go_libp2p_core//peer:go_default_library", - "@com_github_libp2p_go_libp2p_pubsub//:go_default_library", - "@com_github_libp2p_go_libp2p_pubsub//pb:go_default_library", - "@com_github_sirupsen_logrus//:go_default_library", - "//beacon-chain/p2p:go_default_library", - "//beacon-chain/blockchain/testing:go_default_library", - "//beacon-chain/cache:go_default_library", - "//beacon-chain/state/stategen:go_default_library", - "//crypto/rand:go_default_library", - ] + COMMON_DEPS, -) - -go_fuzz_test( - name = "rpc_status_fuzz_test", - srcs = [ - "rpc_status_fuzz.go", - ] + COMMON_SRCS, - corpus = "rpc_status_corpus", - corpus_path = "fuzz/rpc_status_corpus", - func = "BeaconFuzzP2PRPCStatus", - importpath = IMPORT_PATH, - deps = [ - "//beacon-chain/p2p:go_default_library", - "//beacon-chain/sync:go_default_library", - "//beacon-chain/blockchain/testing:go_default_library", - "//beacon-chain/sync/initial-sync/testing:go_default_library", - "//beacon-chain/cache:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - "//encoding/bytesutil:go_default_library", - "@com_github_pkg_errors//:go_default_library", - "@com_github_libp2p_go_libp2p//:go_default_library", - "@com_github_libp2p_go_libp2p_core//host:go_default_library", - "@com_github_libp2p_go_libp2p_core//peer:go_default_library", - "@com_github_libp2p_go_libp2p_core//network:go_default_library", - "@com_github_libp2p_go_libp2p_core//mux:go_default_library", - "@com_github_sirupsen_logrus//:go_default_library", - ] + COMMON_DEPS, -) - -go_fuzz_test( - name = "ssz_encoder_attestations_test", - srcs = [ - "ssz_encoder_attestations_fuzz.go", - ] + COMMON_SRCS, - corpus = "@sigp_beacon_fuzz_corpora//:current_mainnet_block_header", - corpus_path = "external/sigp_beacon_fuzz_corpora/0-11-0/mainnet/block_header", - func = "SszEncoderAttestationFuzz", - importpath = IMPORT_PATH, - deps = [ - "//beacon-chain/p2p/encoder:go_default_library", - "//config/params:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - ] + COMMON_DEPS, -) - -go_fuzz_test( - name = "state_fuzz_test", - srcs = [ - "state_fuzz.go", - ] + COMMON_SRCS, - corpus = "@sigp_beacon_fuzz_corpora//:0_11_0_mainnet_beaconstate", - corpus_path = "external/sigp_beacon_fuzz_corpora/0-11-0/mainnet/beaconstate", - func = "BeaconStateFuzz", - importpath = IMPORT_PATH, - max_len = 30000000, - deps = [ - "//proto/prysm/v1alpha1:go_default_library", - "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/core/time:go_default_library", - "//time/slots:go_default_library", - "//config/params:go_default_library", - ] + COMMON_DEPS, -) - -go_library( - name = "go_default_library", - testonly = 1, - srcs = [ - "common.go", - "inputs.go", - "rpc_status_fuzz.go", - "ssz_encoder_attestations_fuzz.go", - "state_fuzz.go", - ":ssz_generated_files", # keep - ], - importpath = "github.com/prysmaticlabs/prysm/fuzz", - visibility = ["//visibility:public"], - deps = [ - "//beacon-chain/blockchain:go_default_library", - "//beacon-chain/blockchain/testing:go_default_library", - "//beacon-chain/cache:go_default_library", - "//beacon-chain/core/time:go_default_library", - "//beacon-chain/core/blocks:go_default_library", - "//time/slots:go_default_library", - "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/db:go_default_library", - "//beacon-chain/db/kv:go_default_library", - "//beacon-chain/forkchoice/protoarray:go_default_library", - "//beacon-chain/operations/attestations:go_default_library", - "//beacon-chain/operations/slashings:go_default_library", - "//beacon-chain/operations/voluntaryexits:go_default_library", - "//beacon-chain/p2p:go_default_library", - "//beacon-chain/p2p/encoder:go_default_library", - "//beacon-chain/p2p/testing:go_default_library", - "//beacon-chain/state/v1:go_default_library", - "//beacon-chain/state/stategen:go_default_library", - "//beacon-chain/sync:go_default_library", - "//beacon-chain/sync/initial-sync/testing:go_default_library", - "//testing/fuzz/testing:go_default_library", - "//encoding/bytesutil:go_default_library", - "//config/features:go_default_library", - "//config/params:go_default_library", - "//crypto/rand:go_default_library", - "//testing/util:go_default_library", - "@com_github_libp2p_go_libp2p_core//host:go_default_library", - "@com_github_libp2p_go_libp2p_core//network:go_default_library", - "@com_github_libp2p_go_libp2p_core//peer:go_default_library", - "@com_github_libp2p_go_libp2p_pubsub//:go_default_library", - "@com_github_libp2p_go_libp2p_pubsub//pb:go_default_library", - "@com_github_libp2p_go_libp2p//:go_default_library", - "@com_github_pkg_errors//:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - "@com_github_sirupsen_logrus//:go_default_library", - ] + SSZ_DEPS, # keep -) - -go_library( - name = "inputs", - srcs = [ - "inputs.go", - ":ssz_generated_files", # keep - ], - importpath = "github.com/prysmaticlabs/prysm/fuzz", - visibility = ["//visibility:public"], - deps = [ - "//proto/prysm/v1alpha1:go_default_library", - ] + SSZ_DEPS, # keep -) diff --git a/testing/fuzz/README.md b/testing/fuzz/README.md deleted file mode 100644 index 8ae6350e0..000000000 --- a/testing/fuzz/README.md +++ /dev/null @@ -1,102 +0,0 @@ -# Prysm Fuzz Testing - -[![fuzzit](https://app.fuzzit.dev/badge?org_id=prysmaticlabs-gh)](https://app.fuzzit.dev/orgs/prysmaticlabs-gh/dashboard) - -## Adding a fuzz test - -Fuzz testing attempts to find crash level bugs within the tested code paths, but could also be used -as a sanity check certain logic. - -### 1) Determining an ideal target - -A fuzz test inputs pseudo-random data to a given method and attempts to find input data that tests -as many code branches as possible. When choosing a target to test, consider that the method under -test should be as stateless as possible. While stateful methods (i.e. methods that use a cache), -can be tested, they are often hard to reproduce in a regression test. Consider disabling any caches -or persistence layers if possible. - -### 2) Writing a fuzz test - -First, you need to determine in your input data. The current test suite uses SSZ encoded bytes to -deserialize to input objects. - -_Example: Block header input data_ - -```go -type InputBlockWithPrestate struct { - StateID uint16 - Block *ethpb.BeaconBlock -} -``` - -You'll also want to add that struct to `//testing/fuzz:ssz_generated_files` to generate the custom fast SSZ -methods for serialization to improve test performance. - -Your fuzz test must accept a single argument of type `[]byte`. The return types are ignored by -libfuzzer, but might be useful for other applications such as -[beacon-fuzz](https://github.com/sigp/beacon-fuzz). Be sure to name your test file with the -`_fuzz.go` suffix for consistency. - -```go -func MyExampleFuzz(b []byte) { - input := &MyFuzzInputData{} - if err := ssz.Unmarshal(b, input); err != nil { - return // Input bytes doesn't serialize to input object. - } - - result, err := somePackage.MethodUnderTest(input) - if err != nil { - // Input was invalid for processing, but the method didn't panic so that's OK. - return - } - // Optional: sanity check the resulting data. - if result < 0 { - panic("MethodUnderTest should never return a negative number") // Fail! - } -} -``` - -### 3) Add your fuzz target to fuzz/BUILD.bazel - -Since we are using some custom rules to generate the fuzz test instrumentation and appropriate -libfuzz testing suite, we cannot rely on gazelle to generate these targets for us. - -```starlark -go_fuzz_test( - name = "example_fuzz_test", - srcs = [ - "example_fuzz.go", - ] + COMMON_SRCS, # common and input type files. - corpus = "example_corpus", - corpus_path = "fuzz/example_corpus", # Path from root of project - func = "MyExampleFuzz", - importpath = IMPORT_PATH, - deps = [ - # Deps used in your fuzz test. - ] + COMMON_DEPS, -) -``` - -Be sure to add your target to the test suite at `//testing/fuzz:fuzz_tests`. - -### 4) Run your fuzz test - -To run your fuzz test you must manually target it with bazel test and run with the config flag -`--config=fuzz`. - -``` -bazel test //testing/fuzz:example_fuzz_test --config=fuzz -``` - -## Running fuzzit regression tests - -To run fuzzit regression tests, you can run the fuzz test suite with the 1--config=fuzzit` -configuration flag. Note: This requires docker installed on your machine. See -[fuzzitdev/fuzzit#58](https://github.com/fuzzitdev/fuzzit/issues/58). - -``` -bazel test //testing/fuzz:fuzz_tests --config=fuzzit -``` - -If the same command above is run with the FUZZIT_API_KEY environment variable set, then the fuzzit -test targets will be uploaded and restarted at https://app.fuzzit.dev. diff --git a/testing/fuzz/block_fuzz.go b/testing/fuzz/block_fuzz.go deleted file mode 100644 index 0af7c1d0e..000000000 --- a/testing/fuzz/block_fuzz.go +++ /dev/null @@ -1,204 +0,0 @@ -//go:build libfuzzer -// +build libfuzzer - -package fuzz - -import ( - "bytes" - "context" - "encoding/hex" - "io/ioutil" - "os" - "path" - - "github.com/libp2p/go-libp2p-core/peer" - pubsub "github.com/libp2p/go-libp2p-pubsub" - pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb" - "github.com/prysmaticlabs/prysm/beacon-chain/blockchain" - "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/beacon-chain/db" - beaconkv "github.com/prysmaticlabs/prysm/beacon-chain/db/kv" - "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" - "github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations" - "github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings" - "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits" - "github.com/prysmaticlabs/prysm/beacon-chain/p2p" - p2pt "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" - powt "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" - "github.com/prysmaticlabs/prysm/beacon-chain/sync" - "github.com/prysmaticlabs/prysm/config/params" - "github.com/prysmaticlabs/prysm/crypto/rand" - "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" - "github.com/prysmaticlabs/prysm/testing/util" - "github.com/sirupsen/logrus" -) - -const topic = p2p.BlockSubnetTopicFormat - -var db1 db.Database -var dbPath = path.Join(os.TempDir(), "fuzz_beacondb", randomHex(6)) - -func randomHex(n int) string { - bytes := make([]byte, n) - if _, err := rand.NewGenerator().Read(bytes); err != nil { - panic(err) - } - return hex.EncodeToString(bytes) -} - -func init() { - logrus.SetLevel(logrus.PanicLevel) - logrus.SetOutput(ioutil.Discard) - - var err error - - db1, err = db.NewDB(context.Background(), dbPath, &beaconkv.Config{}) - if err != nil { - panic(err) - } -} - -func setupDB() { - if err := db1.ClearDB(); err != nil { - _ = err - } - - ctx := context.Background() - s, err := util.NewBeaconState() - if err != nil { - panic(err) - } - b := util.NewBeaconBlock() - if err := db1.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)); err != nil { - panic(err) - } - br, err := b.HashTreeRoot() - if err != nil { - panic(err) - } - if err := db1.SaveState(ctx, s, br); err != nil { - panic(err) - } - if err := db1.SaveGenesisBlockRoot(ctx, br); err != nil { - panic(err) - } -} - -type fakeChecker struct{} - -func (fakeChecker) Syncing() bool { - return false -} -func (fakeChecker) Initialized() bool { - return false -} -func (fakeChecker) Status() error { - return nil -} -func (fakeChecker) Resync() error { - return nil -} -func (fakeChecker) Synced() bool { - return false -} - -// FuzzBlock wraps BeaconFuzzBlock in a go-fuzz compatible interface -func FuzzBlock(b []byte) int { - BeaconFuzzBlock(b) - return 0 -} - -// BeaconFuzzBlock runs full processing of beacon block against a given state. -func BeaconFuzzBlock(b []byte) { - params.UseMainnetConfig() - input := &InputBlockWithPrestate{} - if err := input.UnmarshalSSZ(b); err != nil { - return - } - st, err := v1.InitializeFromProtoUnsafe(input.State) - if err != nil { - return - } - - setupDB() - - p2p := p2pt.NewFuzzTestP2P() - sgen := stategen.New(db1) - sn := &testing.MockStateNotifier{} - bn := &testing.MockBlockNotifier{} - an := &testing.MockOperationNotifier{} - ap := attestations.NewPool() - ep := voluntaryexits.NewPool() - sp := slashings.NewPool() - ops, err := attestations.NewService(context.Background(), &attestations.Config{Pool: ap}) - if err != nil { - panic(err) - } - - chain, err := blockchain.NewService( - context.Background(), - blockchain.WithChainStartFetcher(powt.NewPOWChain()), - blockchain.WithDatabase(db1), - blockchain.WithAttestationPool(ap), - blockchain.WithExitPool(ep), - blockchain.WithSlashingPool(sp), - blockchain.WithP2PBroadcaster(p2p), - blockchain.WithStateNotifier(sn), - blockchain.WithForkChoiceStore(protoarray.New(0, 0, [32]byte{})), - blockchain.WithAttestationService(ops), - blockchain.WithStateGen(sgen), - ) - if err != nil { - panic(err) - } - chain.Start() - - s := sync.NewRegularSyncFuzz( - sync.WithDatabase(db1), - sync.WithP2P(p2p), - sync.WithChainService(chain), - sync.WithInitialSync(fakeChecker{}), - sync.WithStateNotifier(sn), - sync.WithBlockNotifier(bn), - sync.WithOperationNotifier(an), - sync.WithAttestationPool(ap), - sync.WithExitPool(ep), - sync.WithSlashingPool(sp), - sync.WithStateGen(sgen), - ) - - s.InitCaches() - - buf := new(bytes.Buffer) - _, err = p2p.Encoding().EncodeGossip(buf, input.Block) - if err != nil { - panic(err) - } - - ctx := context.Background() - pid := peer.ID("fuzz") - msg := &pubsub.Message{ - Message: &pubsub_pb.Message{ - Data: buf.Bytes(), - Topic: func() *string { - tpc := topic - return &tpc - }(), - }, - } - - if res := s.FuzzValidateBeaconBlockPubSub(ctx, pid, msg); res != pubsub.ValidationAccept { - return - } - - if err := s.FuzzBeaconBlockSubscriber(ctx, input.Block); err != nil { - _ = err - } - - if _, _, err := transition.ProcessBlockNoVerifyAnySig(ctx, st, wrapper.WrappedPhase0SignedBeaconBlock(input.Block)); err != nil { - _ = err - } -} diff --git a/testing/fuzz/common.go b/testing/fuzz/common.go deleted file mode 100644 index 43bb76c06..000000000 --- a/testing/fuzz/common.go +++ /dev/null @@ -1,20 +0,0 @@ -package fuzz - -import ( - "os" - - "github.com/prysmaticlabs/prysm/config/features" -) - -// EnvBls defines an environment variable name to check whether BLS is enabled or not. -const EnvBls = "BLS_ENABLED" - -func init() { - var blsEnabled bool - if value, exists := os.LookupEnv(EnvBls); exists { - blsEnabled = value == "1" - } - features.Init(&features.Flags{ - SkipBLSVerify: !blsEnabled, - }) -} diff --git a/testing/fuzz/generated.ssz.go b/testing/fuzz/generated.ssz.go deleted file mode 100644 index f42153d83..000000000 --- a/testing/fuzz/generated.ssz.go +++ /dev/null @@ -1,136 +0,0 @@ -// Code generated by fastssz. DO NOT EDIT. -// Hash: d706f5f311b0f23294fc4b788d2f6a7ccd6fe644291047b6c6c08d115d07c680 -package fuzz - -import ( - ssz "github.com/ferranbt/fastssz" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// MarshalSSZ ssz marshals the InputBlockWithPrestate object -func (i *InputBlockWithPrestate) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(i) -} - -// MarshalSSZTo ssz marshals the InputBlockWithPrestate object to a target array -func (i *InputBlockWithPrestate) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(8) - - // Offset (0) 'State' - dst = ssz.WriteOffset(dst, offset) - if i.State == nil { - i.State = new(ethpb.BeaconState) - } - offset += i.State.SizeSSZ() - - // Offset (1) 'Block' - dst = ssz.WriteOffset(dst, offset) - if i.Block == nil { - i.Block = new(ethpb.SignedBeaconBlock) - } - offset += i.Block.SizeSSZ() - - // Field (0) 'State' - if dst, err = i.State.MarshalSSZTo(dst); err != nil { - return - } - - // Field (1) 'Block' - if dst, err = i.Block.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the InputBlockWithPrestate object -func (i *InputBlockWithPrestate) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 8 { - return ssz.ErrSize - } - - tail := buf - var o0, o1 uint64 - - // Offset (0) 'State' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 < 8 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (1) 'Block' - if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { - return ssz.ErrOffset - } - - // Field (0) 'State' - { - buf = tail[o0:o1] - if i.State == nil { - i.State = new(ethpb.BeaconState) - } - if err = i.State.UnmarshalSSZ(buf); err != nil { - return err - } - } - - // Field (1) 'Block' - { - buf = tail[o1:] - if i.Block == nil { - i.Block = new(ethpb.SignedBeaconBlock) - } - if err = i.Block.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the InputBlockWithPrestate object -func (i *InputBlockWithPrestate) SizeSSZ() (size int) { - size = 8 - - // Field (0) 'State' - if i.State == nil { - i.State = new(ethpb.BeaconState) - } - size += i.State.SizeSSZ() - - // Field (1) 'Block' - if i.Block == nil { - i.Block = new(ethpb.SignedBeaconBlock) - } - size += i.Block.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the InputBlockWithPrestate object -func (i *InputBlockWithPrestate) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(i) -} - -// HashTreeRootWith ssz hashes the InputBlockWithPrestate object with a hasher -func (i *InputBlockWithPrestate) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'State' - if err = i.State.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Block' - if err = i.Block.HashTreeRootWith(hh); err != nil { - return - } - - hh.Merkleize(indx) - return -} diff --git a/testing/fuzz/inputs.go b/testing/fuzz/inputs.go deleted file mode 100644 index ee6da7d9d..000000000 --- a/testing/fuzz/inputs.go +++ /dev/null @@ -1,11 +0,0 @@ -package fuzz - -import ( - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// InputBlockWithPrestate for fuzz testing beacon blocks. -type InputBlockWithPrestate struct { - State *ethpb.BeaconState - Block *ethpb.SignedBeaconBlock -} diff --git a/testing/fuzz/rpc_status_corpus/.gitkeep b/testing/fuzz/rpc_status_corpus/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/testing/fuzz/rpc_status_fuzz.go b/testing/fuzz/rpc_status_fuzz.go deleted file mode 100644 index 022bf7a51..000000000 --- a/testing/fuzz/rpc_status_fuzz.go +++ /dev/null @@ -1,85 +0,0 @@ -package fuzz - -import ( - "context" - "strings" - - "github.com/libp2p/go-libp2p" - "github.com/libp2p/go-libp2p-core/host" - "github.com/libp2p/go-libp2p-core/peer" - "github.com/pkg/errors" - mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" - "github.com/prysmaticlabs/prysm/beacon-chain/p2p" - regularsync "github.com/prysmaticlabs/prysm/beacon-chain/sync" - mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/sirupsen/logrus" -) - -var p *p2p.Service -var h host.Host - -func init() { - logrus.SetLevel(logrus.PanicLevel) - - var err error - p, err = p2p.NewService(context.Background(), &p2p.Config{ - NoDiscovery: true, - }) - if err != nil { - panic(errors.Wrap(err, "could not create new p2p service")) - } - - h, err = libp2p.New() - if err != nil { - panic(errors.Wrap(err, "could not create new libp2p host")) - } - - info := peer.AddrInfo{ - ID: h.ID(), - Addrs: h.Addrs(), - } - if err := p.Connect(info); err != nil { - panic(errors.Wrap(err, "could not connect to peer")) - } - regularsync.NewService(context.Background(), - regularsync.WithP2P(p), - regularsync.WithChainService( - &mock.ChainService{ - Root: bytesutil.PadTo([]byte("root"), 32), - FinalizedCheckPoint: ðpb.Checkpoint{Epoch: 4, Root: make([]byte, 32)}, - Fork: ðpb.Fork{CurrentVersion: []byte("foo")}, - }), - regularsync.WithStateNotifier((&mock.ChainService{}).StateNotifier()), - regularsync.WithOperationNotifier((&mock.ChainService{}).OperationNotifier()), - regularsync.WithInitialSync(&mockSync.Sync{IsSyncing: false}), - ) -} - -// FuzzP2PRPCStatus wraps BeaconFuzzP2PRPCStatus in a go-fuzz compatible interface -func FuzzP2PRPCStatus(b []byte) int { - BeaconFuzzP2PRPCStatus(b) - return 0 -} - -// BeaconFuzzP2PRPCStatus implements libfuzzer and beacon fuzz interface. -func BeaconFuzzP2PRPCStatus(b []byte) { - s, err := h.NewStream(context.Background(), p.PeerID(), "/eth2/beacon_chain/req/status/1/ssz_snappy") - if err != nil { - // libp2p ¯\_(ツ)_/¯ - if strings.Contains(err.Error(), "stream reset") || strings.Contains(err.Error(), "connection reset by peer") || strings.Contains(err.Error(), "max dial attempts exceeded") { - return - } - panic(errors.Wrap(err, "failed to open stream")) - } - if s == nil { - panic("nil stream") - } - defer func() { - err := s.Close() - _ = err - }() - _, err = s.Write(b) - _ = err -} diff --git a/testing/fuzz/ssz_encoder_attestations_fuzz.go b/testing/fuzz/ssz_encoder_attestations_fuzz.go deleted file mode 100644 index 727d78f56..000000000 --- a/testing/fuzz/ssz_encoder_attestations_fuzz.go +++ /dev/null @@ -1,27 +0,0 @@ -package fuzz - -import ( - "bytes" - - "github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder" - "github.com/prysmaticlabs/prysm/config/params" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -var buf = new(bytes.Buffer) - -// SszEncoderAttestationFuzz runs network encode/decode for attestations. -func SszEncoderAttestationFuzz(b []byte) { - params.UseMainnetConfig() - buf.Reset() - input := ðpb.Attestation{} - e := encoder.SszNetworkEncoder{} - if err := e.DecodeGossip(b, input); err != nil { - _ = err - return - } - if _, err := e.EncodeGossip(buf, input); err != nil { - _ = err - return - } -} diff --git a/testing/fuzz/state_fuzz.go b/testing/fuzz/state_fuzz.go deleted file mode 100644 index 991a09bbc..000000000 --- a/testing/fuzz/state_fuzz.go +++ /dev/null @@ -1,65 +0,0 @@ -package fuzz - -import ( - "context" - "fmt" - - stateutil "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" - "github.com/prysmaticlabs/prysm/config/features" - "github.com/prysmaticlabs/prysm/config/params" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/time/slots" -) - -func init() { - features.Init(&features.Flags{ - EnableSSZCache: false, - }) -} - -// BeaconStateFuzz -- -func BeaconStateFuzz(input []byte) { - params.UseMainnetConfig() - st := ðpb.BeaconState{} - if err := st.UnmarshalSSZ(input); err != nil { - return - } - s, err := v1.InitializeFromProtoUnsafe(st) - if err != nil { - panic(err) - } - validateStateHTR(s) - nextEpoch := slots.ToEpoch(s.Slot()) + 1 - slot, err := slots.EpochStart(nextEpoch) - if err != nil { - return - } - if _, err := stateutil.ProcessSlots(context.Background(), s, slot); err != nil { - _ = err - return - } - validateStateHTR(s) -} - -func validateStateHTR(s *v1.BeaconState) { - rawState, ok := s.InnerStateUnsafe().(*ethpb.BeaconState) - if !ok { - panic("non valid type assertion") - } - rt, err := s.HashTreeRoot(context.Background()) - nxtRt, err2 := rawState.HashTreeRoot() - - if err == nil && err2 != nil { - panic("HTR from state had only and error from cached state HTR method") - } - if err != nil && err2 == nil { - panic("HTR from state had only and error from fast-ssz HTR method") - } - if err != nil && err2 != nil { - return - } - if rt != nxtRt { - panic(fmt.Sprintf("cached HTR gave a root of %#x while fast-ssz gave a root of %#x", rt, nxtRt)) - } -} diff --git a/testing/fuzz/testing/BUILD.bazel b/testing/fuzz/testing/BUILD.bazel deleted file mode 100644 index 0c62efeff..000000000 --- a/testing/fuzz/testing/BUILD.bazel +++ /dev/null @@ -1,25 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - testonly = 1, - srcs = ["beacon_fuzz_states.go"], - data = [ - "@sigp_beacon_fuzz_corpora//:current_mainnet_beaconstate", - ], - importpath = "github.com/prysmaticlabs/prysm/testing/fuzz/testing", - visibility = [ - "//testing/fuzz:__pkg__", - ], - deps = [ - "//proto/prysm/v1alpha1:go_default_library", - "//testing/util:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["beacon_fuzz_states_test.go"], - embed = [":go_default_library"], - deps = ["//testing/require:go_default_library"], -) diff --git a/testing/fuzz/testing/beacon_fuzz_states.go b/testing/fuzz/testing/beacon_fuzz_states.go deleted file mode 100644 index be5a85411..000000000 --- a/testing/fuzz/testing/beacon_fuzz_states.go +++ /dev/null @@ -1,39 +0,0 @@ -package testing - -import ( - "fmt" - "os" - "strconv" - - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/testing/util" -) - -const fileBase = "0-11-0/mainnet/beaconstate" -const fileBaseENV = "BEACONSTATES_PATH" - -// BeaconFuzzState returns a beacon state by ID using the beacon-fuzz corpora. -func BeaconFuzzState(ID uint64) (*ethpb.BeaconState, error) { - base := fileBase - // Using an environment variable allows a host image to specify the path when only the binary - // executable was uploaded (without the runfiles). i.e. fuzzit's platform. - if p, ok := os.LookupEnv(fileBaseENV); ok { - base = p - } - ok, err := util.BazelDirectoryNonEmpty(base) - if err != nil { - panic(err) - } - if !ok { - panic(fmt.Sprintf("Beacon states directory (%s) does not exist or has no files.", base)) - } - b, err := util.BazelFileBytes(base, strconv.Itoa(int(ID))) - if err != nil { - return nil, err - } - st := ðpb.BeaconState{} - if err := st.UnmarshalSSZ(b); err != nil { - return nil, err - } - return st, nil -} diff --git a/testing/fuzz/testing/beacon_fuzz_states_test.go b/testing/fuzz/testing/beacon_fuzz_states_test.go deleted file mode 100644 index a34142609..000000000 --- a/testing/fuzz/testing/beacon_fuzz_states_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package testing - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestGetBeaconFuzzState(t *testing.T) { - _, err := BeaconFuzzState(1) - require.NoError(t, err) -} diff --git a/third_party/afl/BUILD.bazel b/third_party/afl/BUILD.bazel deleted file mode 100644 index 41c71994f..000000000 --- a/third_party/afl/BUILD.bazel +++ /dev/null @@ -1,80 +0,0 @@ -package( - default_testonly = True, - default_visibility = ["//visibility:public"], -) -# Note: these libraries only compile with llvm. - -cc_library( - name = "comm_hdr", - hdrs = [ - "alloc-inl.h", - "config.h", - "debug.h", - "hash.h", - "types.h", - ], - visibility = ["//visibility:private"], -) - -CFLAGS = [ - "-O3 -funroll-loops", - "-Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign", - "-DAFL_PATH=\\\"/usr/local/lib/afl\\\"", - "-DDOC_PATH=\\\"/usr/local/share/doc/afl\\\"", - "-DBIN_PATH=\\\"/usr/local/bin\\\"", -] - -LDFLAGS = ["-ldl"] - -cc_library( - name = "lib-afl-fuzz", - srcs = ["afl-fuzz.c"], - copts = CFLAGS, - linkopts = LDFLAGS, - visibility = ["//visibility:private"], - deps = [":comm_hdr"], -) - -cc_library( - name = "lib-afl-showmap", - srcs = ["afl-showmap.c"], - copts = CFLAGS, - linkopts = LDFLAGS, - visibility = ["//visibility:private"], - deps = [":comm_hdr"], -) - -cc_library( - name = "afl-llvm-rt", - srcs = ["llvm_mode/afl-llvm-rt.o.c"], - copts = ["-Wno-pointer-sign -O3"], - visibility = ["//visibility:private"], - deps = [":comm_hdr"], -) - -cc_library( - name = "fuzzing_engine", - srcs = ["afl_driver.cpp"], - copts = ["-fsanitize=address -O3"], - linkopts = ["-fsanitize=address"], - tags = ["manual"], - deps = [":afl-llvm-rt"], -) - -genrule( - name = "libs", - srcs = [ - ":lib-afl-fuzz", - ":lib-afl-showmap", - ], - outs = [ - "afl-fuzz", - "afl-showmap", - ], - cmd = """ -cp $(locations :lib-afl-fuzz) . -cp $(locations :lib-afl-showmap) . -mv liblib-afl-fuzz.a $(location afl-fuzz) -mv liblib-afl-showmap.a $(location afl-showmap) -""", -) diff --git a/third_party/afl/afl-fuzz b/third_party/afl/afl-fuzz deleted file mode 100755 index 380285ead6ae70d6b57712246b55beebebf71e4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 794688 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 o-C4dV2c182^*w@m4x5nHqP@KpW5-x1Whx(2nss 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�W8WPcR$gkFc(76E?V2)PsH=i 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�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 diff --git a/third_party/afl/afl-fuzz.c b/third_party/afl/afl-fuzz.c deleted file mode 100644 index 0280f1e41..000000000 --- a/third_party/afl/afl-fuzz.c +++ /dev/null @@ -1,8099 +0,0 @@ -/* - american fuzzy lop - fuzzer code - -------------------------------- - - Written and maintained by Michal Zalewski - - Forkserver design by Jann Horn - - Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This is the real deal: the program takes an instrumented binary and - attempts a variety of basic fuzzing tricks, paying close attention to - how they affect the execution path. - - */ - -#define AFL_MAIN -#define MESSAGES_TO_STDOUT - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#define _FILE_OFFSET_BITS 64 - -#include "config.h" -#include "types.h" -#include "debug.h" -#include "alloc-inl.h" -#include "hash.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) -# include -#endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */ - -/* For systems that have sched_setaffinity; right now just Linux, but one - can hope... */ - -#ifdef __linux__ -# define HAVE_AFFINITY 1 -#endif /* __linux__ */ - -/* A toggle to export some variables when building as a library. Not very - useful for the general public. */ - -#ifdef AFL_LIB -# define EXP_ST -#else -# define EXP_ST static -#endif /* ^AFL_LIB */ - -/* Lots of globals, but mostly for the status UI and other things where it - really makes no sense to haul them around as function parameters. */ - - -EXP_ST u8 *in_dir, /* Input directory with test cases */ - *out_file, /* File to fuzz, if any */ - *out_dir, /* Working & output directory */ - *sync_dir, /* Synchronization directory */ - *sync_id, /* Fuzzer ID */ - *use_banner, /* Display banner */ - *in_bitmap, /* Input bitmap */ - *doc_path, /* Path to documentation dir */ - *target_path, /* Path to target binary */ - *orig_cmdline; /* Original command line */ - -EXP_ST u32 exec_tmout = EXEC_TIMEOUT; /* Configurable exec timeout (ms) */ -static u32 hang_tmout = EXEC_TIMEOUT; /* Timeout used for hang det (ms) */ - -EXP_ST u64 mem_limit = MEM_LIMIT; /* Memory cap for child (MB) */ - -static u32 stats_update_freq = 1; /* Stats update frequency (execs) */ - -EXP_ST u8 skip_deterministic, /* Skip deterministic stages? */ - force_deterministic, /* Force deterministic stages? */ - use_splicing, /* Recombine input files? */ - dumb_mode, /* Run in non-instrumented mode? */ - score_changed, /* Scoring for favorites changed? */ - kill_signal, /* Signal that killed the child */ - resuming_fuzz, /* Resuming an older fuzzing job? */ - timeout_given, /* Specific timeout given? */ - not_on_tty, /* stdout is not a tty */ - term_too_small, /* terminal dimensions too small */ - uses_asan, /* Target uses ASAN? */ - no_forkserver, /* Disable forkserver? */ - crash_mode, /* Crash mode! Yeah! */ - in_place_resume, /* Attempt in-place resume? */ - auto_changed, /* Auto-generated tokens changed? */ - no_cpu_meter_red, /* Feng shui on the status screen */ - no_arith, /* Skip most arithmetic ops */ - shuffle_queue, /* Shuffle input queue? */ - bitmap_changed = 1, /* Time to update bitmap? */ - qemu_mode, /* Running in QEMU mode? */ - skip_requested, /* Skip request, via SIGUSR1 */ - run_over10m, /* Run time over 10 minutes? */ - persistent_mode, /* Running in persistent mode? */ - deferred_mode, /* Deferred forkserver mode? */ - fast_cal; /* Try to calibrate faster? */ - -static s32 out_fd, /* Persistent fd for out_file */ - dev_urandom_fd = -1, /* Persistent fd for /dev/urandom */ - dev_null_fd = -1, /* Persistent fd for /dev/null */ - fsrv_ctl_fd, /* Fork server control pipe (write) */ - fsrv_st_fd; /* Fork server status pipe (read) */ - -static s32 forksrv_pid, /* PID of the fork server */ - child_pid = -1, /* PID of the fuzzed program */ - out_dir_fd = -1; /* FD of the lock file */ - -EXP_ST u8* trace_bits; /* SHM with instrumentation bitmap */ - -EXP_ST u8 virgin_bits[MAP_SIZE], /* Regions yet untouched by fuzzing */ - virgin_tmout[MAP_SIZE], /* Bits we haven't seen in tmouts */ - virgin_crash[MAP_SIZE]; /* Bits we haven't seen in crashes */ - -static u8 var_bytes[MAP_SIZE]; /* Bytes that appear to be variable */ - -static s32 shm_id; /* ID of the SHM region */ - -static volatile u8 stop_soon, /* Ctrl-C pressed? */ - clear_screen = 1, /* Window resized? */ - child_timed_out; /* Traced process timed out? */ - -EXP_ST u32 queued_paths, /* Total number of queued testcases */ - queued_variable, /* Testcases with variable behavior */ - queued_at_start, /* Total number of initial inputs */ - queued_discovered, /* Items discovered during this run */ - queued_imported, /* Items imported via -S */ - queued_favored, /* Paths deemed favorable */ - queued_with_cov, /* Paths with new coverage bytes */ - pending_not_fuzzed, /* Queued but not done yet */ - pending_favored, /* Pending favored paths */ - cur_skipped_paths, /* Abandoned inputs in cur cycle */ - cur_depth, /* Current path depth */ - max_depth, /* Max path depth */ - useless_at_start, /* Number of useless starting paths */ - var_byte_count, /* Bitmap bytes with var behavior */ - current_entry, /* Current queue entry ID */ - havoc_div = 1; /* Cycle count divisor for havoc */ - -EXP_ST u64 total_crashes, /* Total number of crashes */ - unique_crashes, /* Crashes with unique signatures */ - total_tmouts, /* Total number of timeouts */ - unique_tmouts, /* Timeouts with unique signatures */ - unique_hangs, /* Hangs with unique signatures */ - total_execs, /* Total execve() calls */ - start_time, /* Unix start time (ms) */ - last_path_time, /* Time for most recent path (ms) */ - last_crash_time, /* Time for most recent crash (ms) */ - last_hang_time, /* Time for most recent hang (ms) */ - last_crash_execs, /* Exec counter at last crash */ - queue_cycle, /* Queue round counter */ - cycles_wo_finds, /* Cycles without any new paths */ - trim_execs, /* Execs done to trim input files */ - bytes_trim_in, /* Bytes coming into the trimmer */ - bytes_trim_out, /* Bytes coming outa the trimmer */ - blocks_eff_total, /* Blocks subject to effector maps */ - blocks_eff_select; /* Blocks selected as fuzzable */ - -static u32 subseq_tmouts; /* Number of timeouts in a row */ - -static u8 *stage_name = "init", /* Name of the current fuzz stage */ - *stage_short, /* Short stage name */ - *syncing_party; /* Currently syncing with... */ - -static s32 stage_cur, stage_max; /* Stage progression */ -static s32 splicing_with = -1; /* Splicing with which test case? */ - -static u32 master_id, master_max; /* Master instance job splitting */ - -static u32 syncing_case; /* Syncing with case #... */ - -static s32 stage_cur_byte, /* Byte offset of current stage op */ - stage_cur_val; /* Value used for stage op */ - -static u8 stage_val_type; /* Value type (STAGE_VAL_*) */ - -static u64 stage_finds[32], /* Patterns found per fuzz stage */ - stage_cycles[32]; /* Execs per fuzz stage */ - -static u32 rand_cnt; /* Random number counter */ - -static u64 total_cal_us, /* Total calibration time (us) */ - total_cal_cycles; /* Total calibration cycles */ - -static u64 total_bitmap_size, /* Total bit count for all bitmaps */ - total_bitmap_entries; /* Number of bitmaps counted */ - -static s32 cpu_core_count; /* CPU core count */ - -#ifdef HAVE_AFFINITY - -static s32 cpu_aff = -1; /* Selected CPU core */ - -#endif /* HAVE_AFFINITY */ - -static FILE* plot_file; /* Gnuplot output file */ - -struct queue_entry { - - u8* fname; /* File name for the test case */ - u32 len; /* Input length */ - - u8 cal_failed, /* Calibration failed? */ - trim_done, /* Trimmed? */ - was_fuzzed, /* Had any fuzzing done yet? */ - passed_det, /* Deterministic stages passed? */ - has_new_cov, /* Triggers new coverage? */ - var_behavior, /* Variable behavior? */ - favored, /* Currently favored? */ - fs_redundant; /* Marked as redundant in the fs? */ - - u32 bitmap_size, /* Number of bits set in bitmap */ - exec_cksum; /* Checksum of the execution trace */ - - u64 exec_us, /* Execution time (us) */ - handicap, /* Number of queue cycles behind */ - depth; /* Path depth */ - - u8* trace_mini; /* Trace bytes, if kept */ - u32 tc_ref; /* Trace bytes ref count */ - - struct queue_entry *next, /* Next element, if any */ - *next_100; /* 100 elements ahead */ - -}; - -static struct queue_entry *queue, /* Fuzzing queue (linked list) */ - *queue_cur, /* Current offset within the queue */ - *queue_top, /* Top of the list */ - *q_prev100; /* Previous 100 marker */ - -static struct queue_entry* - top_rated[MAP_SIZE]; /* Top entries for bitmap bytes */ - -struct extra_data { - u8* data; /* Dictionary token data */ - u32 len; /* Dictionary token length */ - u32 hit_cnt; /* Use count in the corpus */ -}; - -static struct extra_data* extras; /* Extra tokens to fuzz with */ -static u32 extras_cnt; /* Total number of tokens read */ - -static struct extra_data* a_extras; /* Automatically selected extras */ -static u32 a_extras_cnt; /* Total number of tokens available */ - -static u8* (*post_handler)(u8* buf, u32* len); - -/* Interesting values, as per config.h */ - -static s8 interesting_8[] = { INTERESTING_8 }; -static s16 interesting_16[] = { INTERESTING_8, INTERESTING_16 }; -static s32 interesting_32[] = { INTERESTING_8, INTERESTING_16, INTERESTING_32 }; - -/* Fuzzing stages */ - -enum { - /* 00 */ STAGE_FLIP1, - /* 01 */ STAGE_FLIP2, - /* 02 */ STAGE_FLIP4, - /* 03 */ STAGE_FLIP8, - /* 04 */ STAGE_FLIP16, - /* 05 */ STAGE_FLIP32, - /* 06 */ STAGE_ARITH8, - /* 07 */ STAGE_ARITH16, - /* 08 */ STAGE_ARITH32, - /* 09 */ STAGE_INTEREST8, - /* 10 */ STAGE_INTEREST16, - /* 11 */ STAGE_INTEREST32, - /* 12 */ STAGE_EXTRAS_UO, - /* 13 */ STAGE_EXTRAS_UI, - /* 14 */ STAGE_EXTRAS_AO, - /* 15 */ STAGE_HAVOC, - /* 16 */ STAGE_SPLICE -}; - -/* Stage value types */ - -enum { - /* 00 */ STAGE_VAL_NONE, - /* 01 */ STAGE_VAL_LE, - /* 02 */ STAGE_VAL_BE -}; - -/* Execution status fault codes */ - -enum { - /* 00 */ FAULT_NONE, - /* 01 */ FAULT_TMOUT, - /* 02 */ FAULT_CRASH, - /* 03 */ FAULT_ERROR, - /* 04 */ FAULT_NOINST, - /* 05 */ FAULT_NOBITS -}; - - -/* Get unix time in milliseconds */ - -static u64 get_cur_time(void) { - - struct timeval tv; - struct timezone tz; - - gettimeofday(&tv, &tz); - - return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); - -} - - -/* Get unix time in microseconds */ - -static u64 get_cur_time_us(void) { - - struct timeval tv; - struct timezone tz; - - gettimeofday(&tv, &tz); - - return (tv.tv_sec * 1000000ULL) + tv.tv_usec; - -} - - -/* Generate a random number (from 0 to limit - 1). This may - have slight bias. */ - -static inline u32 UR(u32 limit) { - - if (unlikely(!rand_cnt--)) { - - u32 seed[2]; - - ck_read(dev_urandom_fd, &seed, sizeof(seed), "/dev/urandom"); - - srandom(seed[0]); - rand_cnt = (RESEED_RNG / 2) + (seed[1] % RESEED_RNG); - - } - - return random() % limit; - -} - - -/* Shuffle an array of pointers. Might be slightly biased. */ - -static void shuffle_ptrs(void** ptrs, u32 cnt) { - - u32 i; - - for (i = 0; i < cnt - 2; i++) { - - u32 j = i + UR(cnt - i); - void *s = ptrs[i]; - ptrs[i] = ptrs[j]; - ptrs[j] = s; - - } - -} - - -#ifdef HAVE_AFFINITY - -/* Build a list of processes bound to specific cores. Returns -1 if nothing - can be found. Assumes an upper bound of 4k CPUs. */ - -static void bind_to_free_cpu(void) { - - DIR* d; - struct dirent* de; - cpu_set_t c; - - u8 cpu_used[4096] = { 0 }; - u32 i; - - if (cpu_core_count < 2) return; - - if (getenv("AFL_NO_AFFINITY")) { - - WARNF("Not binding to a CPU core (AFL_NO_AFFINITY set)."); - return; - - } - - d = opendir("/proc"); - - if (!d) { - - WARNF("Unable to access /proc - can't scan for free CPU cores."); - return; - - } - - ACTF("Checking CPU core loadout..."); - - /* Introduce some jitter, in case multiple AFL tasks are doing the same - thing at the same time... */ - - usleep(R(1000) * 250); - - /* Scan all /proc//status entries, checking for Cpus_allowed_list. - Flag all processes bound to a specific CPU using cpu_used[]. This will - fail for some exotic binding setups, but is likely good enough in almost - all real-world use cases. */ - - while ((de = readdir(d))) { - - u8* fn; - FILE* f; - u8 tmp[MAX_LINE]; - u8 has_vmsize = 0; - - if (!isdigit(de->d_name[0])) continue; - - fn = alloc_printf("/proc/%s/status", de->d_name); - - if (!(f = fopen(fn, "r"))) { - ck_free(fn); - continue; - } - - while (fgets(tmp, MAX_LINE, f)) { - - u32 hval; - - /* Processes without VmSize are probably kernel tasks. */ - - if (!strncmp(tmp, "VmSize:\t", 8)) has_vmsize = 1; - - if (!strncmp(tmp, "Cpus_allowed_list:\t", 19) && - !strchr(tmp, '-') && !strchr(tmp, ',') && - sscanf(tmp + 19, "%u", &hval) == 1 && hval < sizeof(cpu_used) && - has_vmsize) { - - cpu_used[hval] = 1; - break; - - } - - } - - ck_free(fn); - fclose(f); - - } - - closedir(d); - - for (i = 0; i < cpu_core_count; i++) if (!cpu_used[i]) break; - - if (i == cpu_core_count) { - - SAYF("\n" cLRD "[-] " cRST - "Uh-oh, looks like all %u CPU cores on your system are allocated to\n" - " other instances of afl-fuzz (or similar CPU-locked tasks). Starting\n" - " another fuzzer on this machine is probably a bad plan, but if you are\n" - " absolutely sure, you can set AFL_NO_AFFINITY and try again.\n", - cpu_core_count); - - FATAL("No more free CPU cores"); - - } - - OKF("Found a free CPU core, binding to #%u.", i); - - cpu_aff = i; - - CPU_ZERO(&c); - CPU_SET(i, &c); - - if (sched_setaffinity(0, sizeof(c), &c)) - PFATAL("sched_setaffinity failed"); - -} - -#endif /* HAVE_AFFINITY */ - -#ifndef IGNORE_FINDS - -/* Helper function to compare buffers; returns first and last differing offset. We - use this to find reasonable locations for splicing two files. */ - -static void locate_diffs(u8* ptr1, u8* ptr2, u32 len, s32* first, s32* last) { - - s32 f_loc = -1; - s32 l_loc = -1; - u32 pos; - - for (pos = 0; pos < len; pos++) { - - if (*(ptr1++) != *(ptr2++)) { - - if (f_loc == -1) f_loc = pos; - l_loc = pos; - - } - - } - - *first = f_loc; - *last = l_loc; - - return; - -} - -#endif /* !IGNORE_FINDS */ - - -/* Describe integer. Uses 12 cyclic static buffers for return values. The value - returned should be five characters or less for all the integers we reasonably - expect to see. */ - -static u8* DI(u64 val) { - - static u8 tmp[12][16]; - static u8 cur; - - cur = (cur + 1) % 12; - -#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) do { \ - if (val < (_divisor) * (_limit_mult)) { \ - sprintf(tmp[cur], _fmt, ((_cast)val) / (_divisor)); \ - return tmp[cur]; \ - } \ - } while (0) - - /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu", u64); - - /* 10.0k - 99.9k */ - CHK_FORMAT(1000, 99.95, "%0.01fk", double); - - /* 100k - 999k */ - CHK_FORMAT(1000, 1000, "%lluk", u64); - - /* 1.00M - 9.99M */ - CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); - - /* 10.0M - 99.9M */ - CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); - - /* 100M - 999M */ - CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); - - /* 1.00G - 9.99G */ - CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); - - /* 10.0G - 99.9G */ - CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double); - - /* 100G - 999G */ - CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64); - - /* 1.00T - 9.99G */ - CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double); - - /* 10.0T - 99.9T */ - CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double); - - /* 100T+ */ - strcpy(tmp[cur], "infty"); - return tmp[cur]; - -} - - -/* Describe float. Similar to the above, except with a single - static buffer. */ - -static u8* DF(double val) { - - static u8 tmp[16]; - - if (val < 99.995) { - sprintf(tmp, "%0.02f", val); - return tmp; - } - - if (val < 999.95) { - sprintf(tmp, "%0.01f", val); - return tmp; - } - - return DI((u64)val); - -} - - -/* Describe integer as memory size. */ - -static u8* DMS(u64 val) { - - static u8 tmp[12][16]; - static u8 cur; - - cur = (cur + 1) % 12; - - /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu B", u64); - - /* 10.0k - 99.9k */ - CHK_FORMAT(1024, 99.95, "%0.01f kB", double); - - /* 100k - 999k */ - CHK_FORMAT(1024, 1000, "%llu kB", u64); - - /* 1.00M - 9.99M */ - CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); - - /* 10.0M - 99.9M */ - CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); - - /* 100M - 999M */ - CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); - - /* 1.00G - 9.99G */ - CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); - - /* 10.0G - 99.9G */ - CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double); - - /* 100G - 999G */ - CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64); - - /* 1.00T - 9.99G */ - CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double); - - /* 10.0T - 99.9T */ - CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double); - -#undef CHK_FORMAT - - /* 100T+ */ - strcpy(tmp[cur], "infty"); - return tmp[cur]; - -} - - -/* Describe time delta. Returns one static buffer, 34 chars of less. */ - -static u8* DTD(u64 cur_ms, u64 event_ms) { - - static u8 tmp[64]; - u64 delta; - s32 t_d, t_h, t_m, t_s; - - if (!event_ms) return "none seen yet"; - - delta = cur_ms - event_ms; - - t_d = delta / 1000 / 60 / 60 / 24; - t_h = (delta / 1000 / 60 / 60) % 24; - t_m = (delta / 1000 / 60) % 60; - t_s = (delta / 1000) % 60; - - sprintf(tmp, "%s days, %u hrs, %u min, %u sec", DI(t_d), t_h, t_m, t_s); - return tmp; - -} - - -/* Mark deterministic checks as done for a particular queue entry. We use the - .state file to avoid repeating deterministic fuzzing when resuming aborted - scans. */ - -static void mark_as_det_done(struct queue_entry* q) { - - u8* fn = strrchr(q->fname, '/'); - s32 fd; - - fn = alloc_printf("%s/queue/.state/deterministic_done/%s", out_dir, fn + 1); - - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); - close(fd); - - ck_free(fn); - - q->passed_det = 1; - -} - - -/* Mark as variable. Create symlinks if possible to make it easier to examine - the files. */ - -static void mark_as_variable(struct queue_entry* q) { - - u8 *fn = strrchr(q->fname, '/') + 1, *ldest; - - ldest = alloc_printf("../../%s", fn); - fn = alloc_printf("%s/queue/.state/variable_behavior/%s", out_dir, fn); - - if (symlink(ldest, fn)) { - - s32 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); - close(fd); - - } - - ck_free(ldest); - ck_free(fn); - - q->var_behavior = 1; - -} - - -/* Mark / unmark as redundant (edge-only). This is not used for restoring state, - but may be useful for post-processing datasets. */ - -static void mark_as_redundant(struct queue_entry* q, u8 state) { - - u8* fn; - s32 fd; - - if (state == q->fs_redundant) return; - - q->fs_redundant = state; - - fn = strrchr(q->fname, '/'); - fn = alloc_printf("%s/queue/.state/redundant_edges/%s", out_dir, fn + 1); - - if (state) { - - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); - close(fd); - - } else { - - if (unlink(fn)) PFATAL("Unable to remove '%s'", fn); - - } - - ck_free(fn); - -} - - -/* Append new test case to the queue. */ - -static void add_to_queue(u8* fname, u32 len, u8 passed_det) { - - struct queue_entry* q = ck_alloc(sizeof(struct queue_entry)); - - q->fname = fname; - q->len = len; - q->depth = cur_depth + 1; - q->passed_det = passed_det; - - if (q->depth > max_depth) max_depth = q->depth; - - if (queue_top) { - - queue_top->next = q; - queue_top = q; - - } else q_prev100 = queue = queue_top = q; - - queued_paths++; - pending_not_fuzzed++; - - cycles_wo_finds = 0; - - if (!(queued_paths % 100)) { - - q_prev100->next_100 = q; - q_prev100 = q; - - } - - last_path_time = get_cur_time(); - -} - - -/* Destroy the entire queue. */ - -EXP_ST void destroy_queue(void) { - - struct queue_entry *q = queue, *n; - - while (q) { - - n = q->next; - ck_free(q->fname); - ck_free(q->trace_mini); - ck_free(q); - q = n; - - } - -} - - -/* Write bitmap to file. The bitmap is useful mostly for the secret - -B option, to focus a separate fuzzing session on a particular - interesting input without rediscovering all the others. */ - -EXP_ST void write_bitmap(void) { - - u8* fname; - s32 fd; - - if (!bitmap_changed) return; - bitmap_changed = 0; - - fname = alloc_printf("%s/fuzz_bitmap", out_dir); - fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); - - if (fd < 0) PFATAL("Unable to open '%s'", fname); - - ck_write(fd, virgin_bits, MAP_SIZE, fname); - - close(fd); - ck_free(fname); - -} - - -/* Read bitmap from file. This is for the -B option again. */ - -EXP_ST void read_bitmap(u8* fname) { - - s32 fd = open(fname, O_RDONLY); - - if (fd < 0) PFATAL("Unable to open '%s'", fname); - - ck_read(fd, virgin_bits, MAP_SIZE, fname); - - close(fd); - -} - - -/* Check if the current execution path brings anything new to the table. - Update virgin bits to reflect the finds. Returns 1 if the only change is - the hit-count for a particular tuple; 2 if there are new tuples seen. - Updates the map, so subsequent calls will always return 0. - - This function is called after every exec() on a fairly large buffer, so - it needs to be fast. We do this in 32-bit and 64-bit flavors. */ - -static inline u8 has_new_bits(u8* virgin_map) { - -#ifdef __x86_64__ - - u64* current = (u64*)trace_bits; - u64* virgin = (u64*)virgin_map; - - u32 i = (MAP_SIZE >> 3); - -#else - - u32* current = (u32*)trace_bits; - u32* virgin = (u32*)virgin_map; - - u32 i = (MAP_SIZE >> 2); - -#endif /* ^__x86_64__ */ - - u8 ret = 0; - - while (i--) { - - /* Optimize for (*current & *virgin) == 0 - i.e., no bits in current bitmap - that have not been already cleared from the virgin map - since this will - almost always be the case. */ - - if (unlikely(*current) && unlikely(*current & *virgin)) { - - if (likely(ret < 2)) { - - u8* cur = (u8*)current; - u8* vir = (u8*)virgin; - - /* Looks like we have not found any new bytes yet; see if any non-zero - bytes in current[] are pristine in virgin[]. */ - -#ifdef __x86_64__ - - if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || - (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff) || - (cur[4] && vir[4] == 0xff) || (cur[5] && vir[5] == 0xff) || - (cur[6] && vir[6] == 0xff) || (cur[7] && vir[7] == 0xff)) ret = 2; - else ret = 1; - -#else - - if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || - (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff)) ret = 2; - else ret = 1; - -#endif /* ^__x86_64__ */ - - } - - *virgin &= ~*current; - - } - - current++; - virgin++; - - } - - if (ret && virgin_map == virgin_bits) bitmap_changed = 1; - - return ret; - -} - - -/* Count the number of bits set in the provided bitmap. Used for the status - screen several times every second, does not have to be fast. */ - -static u32 count_bits(u8* mem) { - - u32* ptr = (u32*)mem; - u32 i = (MAP_SIZE >> 2); - u32 ret = 0; - - while (i--) { - - u32 v = *(ptr++); - - /* This gets called on the inverse, virgin bitmap; optimize for sparse - data. */ - - if (v == 0xffffffff) { - ret += 32; - continue; - } - - v -= ((v >> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >> 2) & 0x33333333); - ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24; - - } - - return ret; - -} - - -#define FF(_b) (0xff << ((_b) << 3)) - -/* Count the number of bytes set in the bitmap. Called fairly sporadically, - mostly to update the status screen or calibrate and examine confirmed - new paths. */ - -static u32 count_bytes(u8* mem) { - - u32* ptr = (u32*)mem; - u32 i = (MAP_SIZE >> 2); - u32 ret = 0; - - while (i--) { - - u32 v = *(ptr++); - - if (!v) continue; - if (v & FF(0)) ret++; - if (v & FF(1)) ret++; - if (v & FF(2)) ret++; - if (v & FF(3)) ret++; - - } - - return ret; - -} - - -/* Count the number of non-255 bytes set in the bitmap. Used strictly for the - status screen, several calls per second or so. */ - -static u32 count_non_255_bytes(u8* mem) { - - u32* ptr = (u32*)mem; - u32 i = (MAP_SIZE >> 2); - u32 ret = 0; - - while (i--) { - - u32 v = *(ptr++); - - /* This is called on the virgin bitmap, so optimize for the most likely - case. */ - - if (v == 0xffffffff) continue; - if ((v & FF(0)) != FF(0)) ret++; - if ((v & FF(1)) != FF(1)) ret++; - if ((v & FF(2)) != FF(2)) ret++; - if ((v & FF(3)) != FF(3)) ret++; - - } - - return ret; - -} - - -/* Destructively simplify trace by eliminating hit count information - and replacing it with 0x80 or 0x01 depending on whether the tuple - is hit or not. Called on every new crash or timeout, should be - reasonably fast. */ - -static const u8 simplify_lookup[256] = { - - [0] = 1, - [1 ... 255] = 128 - -}; - -#ifdef __x86_64__ - -static void simplify_trace(u64* mem) { - - u32 i = MAP_SIZE >> 3; - - while (i--) { - - /* Optimize for sparse bitmaps. */ - - if (unlikely(*mem)) { - - u8* mem8 = (u8*)mem; - - mem8[0] = simplify_lookup[mem8[0]]; - mem8[1] = simplify_lookup[mem8[1]]; - mem8[2] = simplify_lookup[mem8[2]]; - mem8[3] = simplify_lookup[mem8[3]]; - mem8[4] = simplify_lookup[mem8[4]]; - mem8[5] = simplify_lookup[mem8[5]]; - mem8[6] = simplify_lookup[mem8[6]]; - mem8[7] = simplify_lookup[mem8[7]]; - - } else *mem = 0x0101010101010101ULL; - - mem++; - - } - -} - -#else - -static void simplify_trace(u32* mem) { - - u32 i = MAP_SIZE >> 2; - - while (i--) { - - /* Optimize for sparse bitmaps. */ - - if (unlikely(*mem)) { - - u8* mem8 = (u8*)mem; - - mem8[0] = simplify_lookup[mem8[0]]; - mem8[1] = simplify_lookup[mem8[1]]; - mem8[2] = simplify_lookup[mem8[2]]; - mem8[3] = simplify_lookup[mem8[3]]; - - } else *mem = 0x01010101; - - mem++; - } - -} - -#endif /* ^__x86_64__ */ - - -/* Destructively classify execution counts in a trace. This is used as a - preprocessing step for any newly acquired traces. Called on every exec, - must be fast. */ - -static const u8 count_class_lookup8[256] = { - - [0] = 0, - [1] = 1, - [2] = 2, - [3] = 4, - [4 ... 7] = 8, - [8 ... 15] = 16, - [16 ... 31] = 32, - [32 ... 127] = 64, - [128 ... 255] = 128 - -}; - -static u16 count_class_lookup16[65536]; - - -EXP_ST void init_count_class16(void) { - - u32 b1, b2; - - for (b1 = 0; b1 < 256; b1++) - for (b2 = 0; b2 < 256; b2++) - count_class_lookup16[(b1 << 8) + b2] = - (count_class_lookup8[b1] << 8) | - count_class_lookup8[b2]; - -} - - -#ifdef __x86_64__ - -static inline void classify_counts(u64* mem) { - - u32 i = MAP_SIZE >> 3; - - while (i--) { - - /* Optimize for sparse bitmaps. */ - - if (unlikely(*mem)) { - - u16* mem16 = (u16*)mem; - - mem16[0] = count_class_lookup16[mem16[0]]; - mem16[1] = count_class_lookup16[mem16[1]]; - mem16[2] = count_class_lookup16[mem16[2]]; - mem16[3] = count_class_lookup16[mem16[3]]; - - } - - mem++; - - } - -} - -#else - -static inline void classify_counts(u32* mem) { - - u32 i = MAP_SIZE >> 2; - - while (i--) { - - /* Optimize for sparse bitmaps. */ - - if (unlikely(*mem)) { - - u16* mem16 = (u16*)mem; - - mem16[0] = count_class_lookup16[mem16[0]]; - mem16[1] = count_class_lookup16[mem16[1]]; - - } - - mem++; - - } - -} - -#endif /* ^__x86_64__ */ - - -/* Get rid of shared memory (atexit handler). */ - -static void remove_shm(void) { - - shmctl(shm_id, IPC_RMID, NULL); - -} - - -/* Compact trace bytes into a smaller bitmap. We effectively just drop the - count information here. This is called only sporadically, for some - new paths. */ - -static void minimize_bits(u8* dst, u8* src) { - - u32 i = 0; - - while (i < MAP_SIZE) { - - if (*(src++)) dst[i >> 3] |= 1 << (i & 7); - i++; - - } - -} - - -/* When we bump into a new path, we call this to see if the path appears - more "favorable" than any of the existing ones. The purpose of the - "favorables" is to have a minimal set of paths that trigger all the bits - seen in the bitmap so far, and focus on fuzzing them at the expense of - the rest. - - The first step of the process is to maintain a list of top_rated[] entries - for every byte in the bitmap. We win that slot if there is no previous - contender, or if the contender has a more favorable speed x size factor. */ - -static void update_bitmap_score(struct queue_entry* q) { - - u32 i; - u64 fav_factor = q->exec_us * q->len; - - /* For every byte set in trace_bits[], see if there is a previous winner, - and how it compares to us. */ - - for (i = 0; i < MAP_SIZE; i++) - - if (trace_bits[i]) { - - if (top_rated[i]) { - - /* Faster-executing or smaller test cases are favored. */ - - if (fav_factor > top_rated[i]->exec_us * top_rated[i]->len) continue; - - /* Looks like we're going to win. Decrease ref count for the - previous winner, discard its trace_bits[] if necessary. */ - - if (!--top_rated[i]->tc_ref) { - ck_free(top_rated[i]->trace_mini); - top_rated[i]->trace_mini = 0; - } - - } - - /* Insert ourselves as the new winner. */ - - top_rated[i] = q; - q->tc_ref++; - - if (!q->trace_mini) { - q->trace_mini = ck_alloc(MAP_SIZE >> 3); - minimize_bits(q->trace_mini, trace_bits); - } - - score_changed = 1; - - } - -} - - -/* The second part of the mechanism discussed above is a routine that - goes over top_rated[] entries, and then sequentially grabs winners for - previously-unseen bytes (temp_v) and marks them as favored, at least - until the next run. The favored entries are given more air time during - all fuzzing steps. */ - -static void cull_queue(void) { - - struct queue_entry* q; - static u8 temp_v[MAP_SIZE >> 3]; - u32 i; - - if (dumb_mode || !score_changed) return; - - score_changed = 0; - - memset(temp_v, 255, MAP_SIZE >> 3); - - queued_favored = 0; - pending_favored = 0; - - q = queue; - - while (q) { - q->favored = 0; - q = q->next; - } - - /* Let's see if anything in the bitmap isn't captured in temp_v. - If yes, and if it has a top_rated[] contender, let's use it. */ - - for (i = 0; i < MAP_SIZE; i++) - if (top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) { - - u32 j = MAP_SIZE >> 3; - - /* Remove all bits belonging to the current entry from temp_v. */ - - while (j--) - if (top_rated[i]->trace_mini[j]) - temp_v[j] &= ~top_rated[i]->trace_mini[j]; - - top_rated[i]->favored = 1; - queued_favored++; - - if (!top_rated[i]->was_fuzzed) pending_favored++; - - } - - q = queue; - - while (q) { - mark_as_redundant(q, !q->favored); - q = q->next; - } - -} - - -/* Configure shared memory and virgin_bits. This is called at startup. */ - -EXP_ST void setup_shm(void) { - - u8* shm_str; - - if (!in_bitmap) memset(virgin_bits, 255, MAP_SIZE); - - memset(virgin_tmout, 255, MAP_SIZE); - memset(virgin_crash, 255, MAP_SIZE); - - shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); - - if (shm_id < 0) PFATAL("shmget() failed"); - - atexit(remove_shm); - - shm_str = alloc_printf("%d", shm_id); - - /* If somebody is asking us to fuzz instrumented binaries in dumb mode, - we don't want them to detect instrumentation, since we won't be sending - fork server commands. This should be replaced with better auto-detection - later on, perhaps? */ - - if (!dumb_mode) setenv(SHM_ENV_VAR, shm_str, 1); - - ck_free(shm_str); - - trace_bits = shmat(shm_id, NULL, 0); - - if (!trace_bits) PFATAL("shmat() failed"); - -} - - -/* Load postprocessor, if available. */ - -static void setup_post(void) { - - void* dh; - u8* fn = getenv("AFL_POST_LIBRARY"); - u32 tlen = 6; - - if (!fn) return; - - ACTF("Loading postprocessor from '%s'...", fn); - - dh = dlopen(fn, RTLD_NOW); - if (!dh) FATAL("%s", dlerror()); - - post_handler = dlsym(dh, "afl_postprocess"); - if (!post_handler) FATAL("Symbol 'afl_postprocess' not found."); - - /* Do a quick test. It's better to segfault now than later =) */ - - post_handler("hello", &tlen); - - OKF("Postprocessor installed successfully."); - -} - - -/* Read all testcases from the input directory, then queue them for testing. - Called at startup. */ - -static void read_testcases(void) { - - struct dirent **nl; - s32 nl_cnt; - u32 i; - u8* fn; - - /* Auto-detect non-in-place resumption attempts. */ - - fn = alloc_printf("%s/queue", in_dir); - if (!access(fn, F_OK)) in_dir = fn; else ck_free(fn); - - ACTF("Scanning '%s'...", in_dir); - - /* We use scandir() + alphasort() rather than readdir() because otherwise, - the ordering of test cases would vary somewhat randomly and would be - difficult to control. */ - - nl_cnt = scandir(in_dir, &nl, NULL, alphasort); - - if (nl_cnt < 0) { - - if (errno == ENOENT || errno == ENOTDIR) - - SAYF("\n" cLRD "[-] " cRST - "The input directory does not seem to be valid - try again. The fuzzer needs\n" - " one or more test case to start with - ideally, a small file under 1 kB\n" - " or so. The cases must be stored as regular files directly in the input\n" - " directory.\n"); - - PFATAL("Unable to open '%s'", in_dir); - - } - - if (shuffle_queue && nl_cnt > 1) { - - ACTF("Shuffling queue..."); - shuffle_ptrs((void**)nl, nl_cnt); - - } - - for (i = 0; i < nl_cnt; i++) { - - struct stat st; - - u8* fn = alloc_printf("%s/%s", in_dir, nl[i]->d_name); - u8* dfn = alloc_printf("%s/.state/deterministic_done/%s", in_dir, nl[i]->d_name); - - u8 passed_det = 0; - - free(nl[i]); /* not tracked */ - - if (lstat(fn, &st) || access(fn, R_OK)) - PFATAL("Unable to access '%s'", fn); - - /* This also takes care of . and .. */ - - if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn, "/README.txt")) { - - ck_free(fn); - ck_free(dfn); - continue; - - } - - if (st.st_size > MAX_FILE) - FATAL("Test case '%s' is too big (%s, limit is %s)", fn, - DMS(st.st_size), DMS(MAX_FILE)); - - /* Check for metadata that indicates that deterministic fuzzing - is complete for this entry. We don't want to repeat deterministic - fuzzing when resuming aborted scans, because it would be pointless - and probably very time-consuming. */ - - if (!access(dfn, F_OK)) passed_det = 1; - ck_free(dfn); - - add_to_queue(fn, st.st_size, passed_det); - - } - - free(nl); /* not tracked */ - - if (!queued_paths) { - - SAYF("\n" cLRD "[-] " cRST - "Looks like there are no valid test cases in the input directory! The fuzzer\n" - " needs one or more test case to start with - ideally, a small file under\n" - " 1 kB or so. The cases must be stored as regular files directly in the\n" - " input directory.\n"); - - FATAL("No usable test cases in '%s'", in_dir); - - } - - last_path_time = 0; - queued_at_start = queued_paths; - -} - - -/* Helper function for load_extras. */ - -static int compare_extras_len(const void* p1, const void* p2) { - struct extra_data *e1 = (struct extra_data*)p1, - *e2 = (struct extra_data*)p2; - - return e1->len - e2->len; -} - -static int compare_extras_use_d(const void* p1, const void* p2) { - struct extra_data *e1 = (struct extra_data*)p1, - *e2 = (struct extra_data*)p2; - - return e2->hit_cnt - e1->hit_cnt; -} - - -/* Read extras from a file, sort by size. */ - -static void load_extras_file(u8* fname, u32* min_len, u32* max_len, - u32 dict_level) { - - FILE* f; - u8 buf[MAX_LINE]; - u8 *lptr; - u32 cur_line = 0; - - f = fopen(fname, "r"); - - if (!f) PFATAL("Unable to open '%s'", fname); - - while ((lptr = fgets(buf, MAX_LINE, f))) { - - u8 *rptr, *wptr; - u32 klen = 0; - - cur_line++; - - /* Trim on left and right. */ - - while (isspace(*lptr)) lptr++; - - rptr = lptr + strlen(lptr) - 1; - while (rptr >= lptr && isspace(*rptr)) rptr--; - rptr++; - *rptr = 0; - - /* Skip empty lines and comments. */ - - if (!*lptr || *lptr == '#') continue; - - /* All other lines must end with '"', which we can consume. */ - - rptr--; - - if (rptr < lptr || *rptr != '"') - FATAL("Malformed name=\"value\" pair in line %u.", cur_line); - - *rptr = 0; - - /* Skip alphanumerics and dashes (label). */ - - while (isalnum(*lptr) || *lptr == '_') lptr++; - - /* If @number follows, parse that. */ - - if (*lptr == '@') { - - lptr++; - if (atoi(lptr) > dict_level) continue; - while (isdigit(*lptr)) lptr++; - - } - - /* Skip whitespace and = signs. */ - - while (isspace(*lptr) || *lptr == '=') lptr++; - - /* Consume opening '"'. */ - - if (*lptr != '"') - FATAL("Malformed name=\"keyword\" pair in line %u.", cur_line); - - lptr++; - - if (!*lptr) FATAL("Empty keyword in line %u.", cur_line); - - /* Okay, let's allocate memory and copy data between "...", handling - \xNN escaping, \\, and \". */ - - extras = ck_realloc_block(extras, (extras_cnt + 1) * - sizeof(struct extra_data)); - - wptr = extras[extras_cnt].data = ck_alloc(rptr - lptr); - - while (*lptr) { - - char* hexdigits = "0123456789abcdef"; - - switch (*lptr) { - - case 1 ... 31: - case 128 ... 255: - FATAL("Non-printable characters in line %u.", cur_line); - - case '\\': - - lptr++; - - if (*lptr == '\\' || *lptr == '"') { - *(wptr++) = *(lptr++); - klen++; - break; - } - - if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2])) - FATAL("Invalid escaping (not \\xNN) in line %u.", cur_line); - - *(wptr++) = - ((strchr(hexdigits, tolower(lptr[1])) - hexdigits) << 4) | - (strchr(hexdigits, tolower(lptr[2])) - hexdigits); - - lptr += 3; - klen++; - - break; - - default: - - *(wptr++) = *(lptr++); - klen++; - - } - - } - - extras[extras_cnt].len = klen; - - if (extras[extras_cnt].len > MAX_DICT_FILE) - FATAL("Keyword too big in line %u (%s, limit is %s)", cur_line, - DMS(klen), DMS(MAX_DICT_FILE)); - - if (*min_len > klen) *min_len = klen; - if (*max_len < klen) *max_len = klen; - - extras_cnt++; - - } - - fclose(f); - -} - - -/* Read extras from the extras directory and sort them by size. */ - -static void load_extras(u8* dir) { - - DIR* d; - struct dirent* de; - u32 min_len = MAX_DICT_FILE, max_len = 0, dict_level = 0; - u8* x; - - /* If the name ends with @, extract level and continue. */ - - if ((x = strchr(dir, '@'))) { - - *x = 0; - dict_level = atoi(x + 1); - - } - - ACTF("Loading extra dictionary from '%s' (level %u)...", dir, dict_level); - - d = opendir(dir); - - if (!d) { - - if (errno == ENOTDIR) { - load_extras_file(dir, &min_len, &max_len, dict_level); - goto check_and_sort; - } - - PFATAL("Unable to open '%s'", dir); - - } - - if (x) FATAL("Dictionary levels not supported for directories."); - - while ((de = readdir(d))) { - - struct stat st; - u8* fn = alloc_printf("%s/%s", dir, de->d_name); - s32 fd; - - if (lstat(fn, &st) || access(fn, R_OK)) - PFATAL("Unable to access '%s'", fn); - - /* This also takes care of . and .. */ - if (!S_ISREG(st.st_mode) || !st.st_size) { - - ck_free(fn); - continue; - - } - - if (st.st_size > MAX_DICT_FILE) - FATAL("Extra '%s' is too big (%s, limit is %s)", fn, - DMS(st.st_size), DMS(MAX_DICT_FILE)); - - if (min_len > st.st_size) min_len = st.st_size; - if (max_len < st.st_size) max_len = st.st_size; - - extras = ck_realloc_block(extras, (extras_cnt + 1) * - sizeof(struct extra_data)); - - extras[extras_cnt].data = ck_alloc(st.st_size); - extras[extras_cnt].len = st.st_size; - - fd = open(fn, O_RDONLY); - - if (fd < 0) PFATAL("Unable to open '%s'", fn); - - ck_read(fd, extras[extras_cnt].data, st.st_size, fn); - - close(fd); - ck_free(fn); - - extras_cnt++; - - } - - closedir(d); - -check_and_sort: - - if (!extras_cnt) FATAL("No usable files in '%s'", dir); - - qsort(extras, extras_cnt, sizeof(struct extra_data), compare_extras_len); - - OKF("Loaded %u extra tokens, size range %s to %s.", extras_cnt, - DMS(min_len), DMS(max_len)); - - if (max_len > 32) - WARNF("Some tokens are relatively large (%s) - consider trimming.", - DMS(max_len)); - - if (extras_cnt > MAX_DET_EXTRAS) - WARNF("More than %u tokens - will use them probabilistically.", - MAX_DET_EXTRAS); - -} - - - - -/* Helper function for maybe_add_auto() */ - -static inline u8 memcmp_nocase(u8* m1, u8* m2, u32 len) { - - while (len--) if (tolower(*(m1++)) ^ tolower(*(m2++))) return 1; - return 0; - -} - - -/* Maybe add automatic extra. */ - -static void maybe_add_auto(u8* mem, u32 len) { - - u32 i; - - /* Allow users to specify that they don't want auto dictionaries. */ - - if (!MAX_AUTO_EXTRAS || !USE_AUTO_EXTRAS) return; - - /* Skip runs of identical bytes. */ - - for (i = 1; i < len; i++) - if (mem[0] ^ mem[i]) break; - - if (i == len) return; - - /* Reject builtin interesting values. */ - - if (len == 2) { - - i = sizeof(interesting_16) >> 1; - - while (i--) - if (*((u16*)mem) == interesting_16[i] || - *((u16*)mem) == SWAP16(interesting_16[i])) return; - - } - - if (len == 4) { - - i = sizeof(interesting_32) >> 2; - - while (i--) - if (*((u32*)mem) == interesting_32[i] || - *((u32*)mem) == SWAP32(interesting_32[i])) return; - - } - - /* Reject anything that matches existing extras. Do a case-insensitive - match. We optimize by exploiting the fact that extras[] are sorted - by size. */ - - for (i = 0; i < extras_cnt; i++) - if (extras[i].len >= len) break; - - for (; i < extras_cnt && extras[i].len == len; i++) - if (!memcmp_nocase(extras[i].data, mem, len)) return; - - /* Last but not least, check a_extras[] for matches. There are no - guarantees of a particular sort order. */ - - auto_changed = 1; - - for (i = 0; i < a_extras_cnt; i++) { - - if (a_extras[i].len == len && !memcmp_nocase(a_extras[i].data, mem, len)) { - - a_extras[i].hit_cnt++; - goto sort_a_extras; - - } - - } - - /* At this point, looks like we're dealing with a new entry. So, let's - append it if we have room. Otherwise, let's randomly evict some other - entry from the bottom half of the list. */ - - if (a_extras_cnt < MAX_AUTO_EXTRAS) { - - a_extras = ck_realloc_block(a_extras, (a_extras_cnt + 1) * - sizeof(struct extra_data)); - - a_extras[a_extras_cnt].data = ck_memdup(mem, len); - a_extras[a_extras_cnt].len = len; - a_extras_cnt++; - - } else { - - i = MAX_AUTO_EXTRAS / 2 + - UR((MAX_AUTO_EXTRAS + 1) / 2); - - ck_free(a_extras[i].data); - - a_extras[i].data = ck_memdup(mem, len); - a_extras[i].len = len; - a_extras[i].hit_cnt = 0; - - } - -sort_a_extras: - - /* First, sort all auto extras by use count, descending order. */ - - qsort(a_extras, a_extras_cnt, sizeof(struct extra_data), - compare_extras_use_d); - - /* Then, sort the top USE_AUTO_EXTRAS entries by size. */ - - qsort(a_extras, MIN(USE_AUTO_EXTRAS, a_extras_cnt), - sizeof(struct extra_data), compare_extras_len); - -} - - -/* Save automatically generated extras. */ - -static void save_auto(void) { - - u32 i; - - if (!auto_changed) return; - auto_changed = 0; - - for (i = 0; i < MIN(USE_AUTO_EXTRAS, a_extras_cnt); i++) { - - u8* fn = alloc_printf("%s/queue/.state/auto_extras/auto_%06u", out_dir, i); - s32 fd; - - fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); - - if (fd < 0) PFATAL("Unable to create '%s'", fn); - - ck_write(fd, a_extras[i].data, a_extras[i].len, fn); - - close(fd); - ck_free(fn); - - } - -} - - -/* Load automatically generated extras. */ - -static void load_auto(void) { - - u32 i; - - for (i = 0; i < USE_AUTO_EXTRAS; i++) { - - u8 tmp[MAX_AUTO_EXTRA + 1]; - u8* fn = alloc_printf("%s/.state/auto_extras/auto_%06u", in_dir, i); - s32 fd, len; - - fd = open(fn, O_RDONLY, 0600); - - if (fd < 0) { - - if (errno != ENOENT) PFATAL("Unable to open '%s'", fn); - ck_free(fn); - break; - - } - - /* We read one byte more to cheaply detect tokens that are too - long (and skip them). */ - - len = read(fd, tmp, MAX_AUTO_EXTRA + 1); - - if (len < 0) PFATAL("Unable to read from '%s'", fn); - - if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA) - maybe_add_auto(tmp, len); - - close(fd); - ck_free(fn); - - } - - if (i) OKF("Loaded %u auto-discovered dictionary tokens.", i); - else OKF("No auto-generated dictionary tokens to reuse."); - -} - - -/* Destroy extras. */ - -static void destroy_extras(void) { - - u32 i; - - for (i = 0; i < extras_cnt; i++) - ck_free(extras[i].data); - - ck_free(extras); - - for (i = 0; i < a_extras_cnt; i++) - ck_free(a_extras[i].data); - - ck_free(a_extras); - -} - - -/* Spin up fork server (instrumented mode only). The idea is explained here: - - http://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html - - In essence, the instrumentation allows us to skip execve(), and just keep - cloning a stopped child. So, we just execute once, and then send commands - through a pipe. The other part of this logic is in afl-as.h. */ - -EXP_ST void init_forkserver(char** argv) { - - static struct itimerval it; - int st_pipe[2], ctl_pipe[2]; - int status; - s32 rlen; - - ACTF("Spinning up the fork server..."); - - if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed"); - - forksrv_pid = fork(); - - if (forksrv_pid < 0) PFATAL("fork() failed"); - - if (!forksrv_pid) { - - struct rlimit r; - - /* Umpf. On OpenBSD, the default fd limit for root users is set to - soft 128. Let's try to fix that... */ - - if (!getrlimit(RLIMIT_NOFILE, &r) && r.rlim_cur < FORKSRV_FD + 2) { - - r.rlim_cur = FORKSRV_FD + 2; - setrlimit(RLIMIT_NOFILE, &r); /* Ignore errors */ - - } - - if (mem_limit) { - - r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20; - -#ifdef RLIMIT_AS - - setrlimit(RLIMIT_AS, &r); /* Ignore errors */ - -#else - - /* This takes care of OpenBSD, which doesn't have RLIMIT_AS, but - according to reliable sources, RLIMIT_DATA covers anonymous - maps - so we should be getting good protection against OOM bugs. */ - - setrlimit(RLIMIT_DATA, &r); /* Ignore errors */ - -#endif /* ^RLIMIT_AS */ - - - } - - /* Dumping cores is slow and can lead to anomalies if SIGKILL is delivered - before the dump is complete. */ - - r.rlim_max = r.rlim_cur = 0; - - setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ - - /* Isolate the process and configure standard descriptors. If out_file is - specified, stdin is /dev/null; otherwise, out_fd is cloned instead. */ - - setsid(); - - dup2(dev_null_fd, 1); - dup2(dev_null_fd, 2); - - if (out_file) { - - dup2(dev_null_fd, 0); - - } else { - - dup2(out_fd, 0); - close(out_fd); - - } - - /* Set up control and status pipes, close the unneeded original fds. */ - - if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) PFATAL("dup2() failed"); - if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) PFATAL("dup2() failed"); - - close(ctl_pipe[0]); - close(ctl_pipe[1]); - close(st_pipe[0]); - close(st_pipe[1]); - - close(out_dir_fd); - close(dev_null_fd); - close(dev_urandom_fd); - close(fileno(plot_file)); - - /* This should improve performance a bit, since it stops the linker from - doing extra work post-fork(). */ - - if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0); - - /* Set sane defaults for ASAN if nothing else specified. */ - - setenv("ASAN_OPTIONS", "abort_on_error=1:" - "detect_leaks=0:" - "symbolize=0:" - "allocator_may_return_null=1", 0); - - /* MSAN is tricky, because it doesn't support abort_on_error=1 at this - point. So, we do this in a very hacky way. */ - - setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" - "symbolize=0:" - "abort_on_error=1:" - "allocator_may_return_null=1:" - "msan_track_origins=0", 0); - - execv(target_path, argv); - - /* Use a distinctive bitmap signature to tell the parent about execv() - falling through. */ - - *(u32*)trace_bits = EXEC_FAIL_SIG; - exit(0); - - } - - /* Close the unneeded endpoints. */ - - close(ctl_pipe[0]); - close(st_pipe[1]); - - fsrv_ctl_fd = ctl_pipe[1]; - fsrv_st_fd = st_pipe[0]; - - /* Wait for the fork server to come up, but don't wait too long. */ - - it.it_value.tv_sec = ((exec_tmout * FORK_WAIT_MULT) / 1000); - it.it_value.tv_usec = ((exec_tmout * FORK_WAIT_MULT) % 1000) * 1000; - - setitimer(ITIMER_REAL, &it, NULL); - - rlen = read(fsrv_st_fd, &status, 4); - - it.it_value.tv_sec = 0; - it.it_value.tv_usec = 0; - - setitimer(ITIMER_REAL, &it, NULL); - - /* If we have a four-byte "hello" message from the server, we're all set. - Otherwise, try to figure out what went wrong. */ - - if (rlen == 4) { - OKF("All right - fork server is up."); - return; - } - - if (child_timed_out) - FATAL("Timeout while initializing fork server (adjusting -t may help)"); - - if (waitpid(forksrv_pid, &status, 0) <= 0) - PFATAL("waitpid() failed"); - - if (WIFSIGNALED(status)) { - - if (mem_limit && mem_limit < 500 && uses_asan) { - - SAYF("\n" cLRD "[-] " cRST - "Whoops, the target binary crashed suddenly, before receiving any input\n" - " from the fuzzer! Since it seems to be built with ASAN and you have a\n" - " restrictive memory limit configured, this is expected; please read\n" - " %s/notes_for_asan.txt for help.\n", doc_path); - - } else if (!mem_limit) { - - SAYF("\n" cLRD "[-] " cRST - "Whoops, the target binary crashed suddenly, before receiving any input\n" - " from the fuzzer! There are several probable explanations:\n\n" - - " - The binary is just buggy and explodes entirely on its own. If so, you\n" - " need to fix the underlying problem or find a better replacement.\n\n" - -#ifdef __APPLE__ - - " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" - " break afl-fuzz performance optimizations when running platform-specific\n" - " targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n" - -#endif /* __APPLE__ */ - - " - Less likely, there is a horrible bug in the fuzzer. If other options\n" - " fail, poke for troubleshooting tips.\n"); - - } else { - - SAYF("\n" cLRD "[-] " cRST - "Whoops, the target binary crashed suddenly, before receiving any input\n" - " from the fuzzer! There are several probable explanations:\n\n" - - " - The current memory limit (%s) is too restrictive, causing the\n" - " target to hit an OOM condition in the dynamic linker. Try bumping up\n" - " the limit with the -m setting in the command line. A simple way confirm\n" - " this diagnosis would be:\n\n" - -#ifdef RLIMIT_AS - " ( ulimit -Sv $[%llu << 10]; /path/to/fuzzed_app )\n\n" -#else - " ( ulimit -Sd $[%llu << 10]; /path/to/fuzzed_app )\n\n" -#endif /* ^RLIMIT_AS */ - - " Tip: you can use http://jwilk.net/software/recidivm to quickly\n" - " estimate the required amount of virtual memory for the binary.\n\n" - - " - The binary is just buggy and explodes entirely on its own. If so, you\n" - " need to fix the underlying problem or find a better replacement.\n\n" - -#ifdef __APPLE__ - - " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" - " break afl-fuzz performance optimizations when running platform-specific\n" - " targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n" - -#endif /* __APPLE__ */ - - " - Less likely, there is a horrible bug in the fuzzer. If other options\n" - " fail, poke for troubleshooting tips.\n", - DMS(mem_limit << 20), mem_limit - 1); - - } - - FATAL("Fork server crashed with signal %d", WTERMSIG(status)); - - } - - if (*(u32*)trace_bits == EXEC_FAIL_SIG) - FATAL("Unable to execute target application ('%s')", argv[0]); - - if (mem_limit && mem_limit < 500 && uses_asan) { - - SAYF("\n" cLRD "[-] " cRST - "Hmm, looks like the target binary terminated before we could complete a\n" - " handshake with the injected code. Since it seems to be built with ASAN and\n" - " you have a restrictive memory limit configured, this is expected; please\n" - " read %s/notes_for_asan.txt for help.\n", doc_path); - - } else if (!mem_limit) { - - SAYF("\n" cLRD "[-] " cRST - "Hmm, looks like the target binary terminated before we could complete a\n" - " handshake with the injected code. Perhaps there is a horrible bug in the\n" - " fuzzer. Poke for troubleshooting tips.\n"); - - } else { - - SAYF("\n" cLRD "[-] " cRST - "Hmm, looks like the target binary terminated before we could complete a\n" - " handshake with the injected code. There are %s probable explanations:\n\n" - - "%s" - " - The current memory limit (%s) is too restrictive, causing an OOM\n" - " fault in the dynamic linker. This can be fixed with the -m option. A\n" - " simple way to confirm the diagnosis may be:\n\n" - -#ifdef RLIMIT_AS - " ( ulimit -Sv $[%llu << 10]; /path/to/fuzzed_app )\n\n" -#else - " ( ulimit -Sd $[%llu << 10]; /path/to/fuzzed_app )\n\n" -#endif /* ^RLIMIT_AS */ - - " Tip: you can use http://jwilk.net/software/recidivm to quickly\n" - " estimate the required amount of virtual memory for the binary.\n\n" - - " - Less likely, there is a horrible bug in the fuzzer. If other options\n" - " fail, poke for troubleshooting tips.\n", - getenv(DEFER_ENV_VAR) ? "three" : "two", - getenv(DEFER_ENV_VAR) ? - " - You are using deferred forkserver, but __AFL_INIT() is never\n" - " reached before the program terminates.\n\n" : "", - DMS(mem_limit << 20), mem_limit - 1); - - } - - FATAL("Fork server handshake failed"); - -} - - -/* Execute target application, monitoring for timeouts. Return status - information. The called program will update trace_bits[]. */ - -static u8 run_target(char** argv, u32 timeout) { - - static struct itimerval it; - static u32 prev_timed_out = 0; - - int status = 0; - u32 tb4; - - child_timed_out = 0; - - /* After this memset, trace_bits[] are effectively volatile, so we - must prevent any earlier operations from venturing into that - territory. */ - - memset(trace_bits, 0, MAP_SIZE); - MEM_BARRIER(); - - /* If we're running in "dumb" mode, we can't rely on the fork server - logic compiled into the target program, so we will just keep calling - execve(). There is a bit of code duplication between here and - init_forkserver(), but c'est la vie. */ - - if (dumb_mode == 1 || no_forkserver) { - - child_pid = fork(); - - if (child_pid < 0) PFATAL("fork() failed"); - - if (!child_pid) { - - struct rlimit r; - - if (mem_limit) { - - r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20; - -#ifdef RLIMIT_AS - - setrlimit(RLIMIT_AS, &r); /* Ignore errors */ - -#else - - setrlimit(RLIMIT_DATA, &r); /* Ignore errors */ - -#endif /* ^RLIMIT_AS */ - - } - - r.rlim_max = r.rlim_cur = 0; - - setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ - - /* Isolate the process and configure standard descriptors. If out_file is - specified, stdin is /dev/null; otherwise, out_fd is cloned instead. */ - - setsid(); - - dup2(dev_null_fd, 1); - dup2(dev_null_fd, 2); - - if (out_file) { - - dup2(dev_null_fd, 0); - - } else { - - dup2(out_fd, 0); - close(out_fd); - - } - - /* On Linux, would be faster to use O_CLOEXEC. Maybe TODO. */ - - close(dev_null_fd); - close(out_dir_fd); - close(dev_urandom_fd); - close(fileno(plot_file)); - - /* Set sane defaults for ASAN if nothing else specified. */ - - setenv("ASAN_OPTIONS", "abort_on_error=1:" - "detect_leaks=0:" - "symbolize=0:" - "allocator_may_return_null=1", 0); - - setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" - "symbolize=0:" - "msan_track_origins=0", 0); - - execv(target_path, argv); - - /* Use a distinctive bitmap value to tell the parent about execv() - falling through. */ - - *(u32*)trace_bits = EXEC_FAIL_SIG; - exit(0); - - } - - } else { - - s32 res; - - /* In non-dumb mode, we have the fork server up and running, so simply - tell it to have at it, and then read back PID. */ - - if ((res = write(fsrv_ctl_fd, &prev_timed_out, 4)) != 4) { - - if (stop_soon) return 0; - RPFATAL(res, "Unable to request new process from fork server (OOM?)"); - - } - - if ((res = read(fsrv_st_fd, &child_pid, 4)) != 4) { - - if (stop_soon) return 0; - RPFATAL(res, "Unable to request new process from fork server (OOM?)"); - - } - - if (child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); - - } - - /* Configure timeout, as requested by user, then wait for child to terminate. */ - - it.it_value.tv_sec = (timeout / 1000); - it.it_value.tv_usec = (timeout % 1000) * 1000; - - setitimer(ITIMER_REAL, &it, NULL); - - /* The SIGALRM handler simply kills the child_pid and sets child_timed_out. */ - - if (dumb_mode == 1 || no_forkserver) { - - if (waitpid(child_pid, &status, 0) <= 0) PFATAL("waitpid() failed"); - - } else { - - s32 res; - - if ((res = read(fsrv_st_fd, &status, 4)) != 4) { - - if (stop_soon) return 0; - RPFATAL(res, "Unable to communicate with fork server (OOM?)"); - - } - - } - - if (!WIFSTOPPED(status)) child_pid = 0; - - it.it_value.tv_sec = 0; - it.it_value.tv_usec = 0; - - setitimer(ITIMER_REAL, &it, NULL); - - total_execs++; - - /* Any subsequent operations on trace_bits must not be moved by the - compiler below this point. Past this location, trace_bits[] behave - very normally and do not have to be treated as volatile. */ - - MEM_BARRIER(); - - tb4 = *(u32*)trace_bits; - -#ifdef __x86_64__ - classify_counts((u64*)trace_bits); -#else - classify_counts((u32*)trace_bits); -#endif /* ^__x86_64__ */ - - prev_timed_out = child_timed_out; - - /* Report outcome to caller. */ - - if (WIFSIGNALED(status) && !stop_soon) { - - kill_signal = WTERMSIG(status); - - if (child_timed_out && kill_signal == SIGKILL) return FAULT_TMOUT; - - return FAULT_CRASH; - - } - - /* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and - must use a special exit code. */ - - if (uses_asan && WEXITSTATUS(status) == MSAN_ERROR) { - kill_signal = 0; - return FAULT_CRASH; - } - - if ((dumb_mode == 1 || no_forkserver) && tb4 == EXEC_FAIL_SIG) - return FAULT_ERROR; - - return FAULT_NONE; - -} - - -/* Write modified data to file for testing. If out_file is set, the old file - is unlinked and a new one is created. Otherwise, out_fd is rewound and - truncated. */ - -static void write_to_testcase(void* mem, u32 len) { - - s32 fd = out_fd; - - if (out_file) { - - unlink(out_file); /* Ignore errors. */ - - fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); - - if (fd < 0) PFATAL("Unable to create '%s'", out_file); - - } else lseek(fd, 0, SEEK_SET); - - ck_write(fd, mem, len, out_file); - - if (!out_file) { - - if (ftruncate(fd, len)) PFATAL("ftruncate() failed"); - lseek(fd, 0, SEEK_SET); - - } else close(fd); - -} - - -/* The same, but with an adjustable gap. Used for trimming. */ - -static void write_with_gap(void* mem, u32 len, u32 skip_at, u32 skip_len) { - - s32 fd = out_fd; - u32 tail_len = len - skip_at - skip_len; - - if (out_file) { - - unlink(out_file); /* Ignore errors. */ - - fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); - - if (fd < 0) PFATAL("Unable to create '%s'", out_file); - - } else lseek(fd, 0, SEEK_SET); - - if (skip_at) ck_write(fd, mem, skip_at, out_file); - - if (tail_len) ck_write(fd, mem + skip_at + skip_len, tail_len, out_file); - - if (!out_file) { - - if (ftruncate(fd, len - skip_len)) PFATAL("ftruncate() failed"); - lseek(fd, 0, SEEK_SET); - - } else close(fd); - -} - - -static void show_stats(void); - -/* Calibrate a new test case. This is done when processing the input directory - to warn about flaky or otherwise problematic test cases early on; and when - new paths are discovered to detect variable behavior and so on. */ - -static u8 calibrate_case(char** argv, struct queue_entry* q, u8* use_mem, - u32 handicap, u8 from_queue) { - - static u8 first_trace[MAP_SIZE]; - - u8 fault = 0, new_bits = 0, var_detected = 0, - first_run = (q->exec_cksum == 0); - - u64 start_us, stop_us; - - s32 old_sc = stage_cur, old_sm = stage_max; - u32 use_tmout = exec_tmout; - u8* old_sn = stage_name; - - /* Be a bit more generous about timeouts when resuming sessions, or when - trying to calibrate already-added finds. This helps avoid trouble due - to intermittent latency. */ - - if (!from_queue || resuming_fuzz) - use_tmout = MAX(exec_tmout + CAL_TMOUT_ADD, - exec_tmout * CAL_TMOUT_PERC / 100); - - q->cal_failed++; - - stage_name = "calibration"; - stage_max = fast_cal ? 3 : CAL_CYCLES; - - /* Make sure the forkserver is up before we do anything, and let's not - count its spin-up time toward binary calibration. */ - - if (dumb_mode != 1 && !no_forkserver && !forksrv_pid) - init_forkserver(argv); - - if (q->exec_cksum) memcpy(first_trace, trace_bits, MAP_SIZE); - - start_us = get_cur_time_us(); - - for (stage_cur = 0; stage_cur < stage_max; stage_cur++) { - - u32 cksum; - - if (!first_run && !(stage_cur % stats_update_freq)) show_stats(); - - write_to_testcase(use_mem, q->len); - - fault = run_target(argv, use_tmout); - - /* stop_soon is set by the handler for Ctrl+C. When it's pressed, - we want to bail out quickly. */ - - if (stop_soon || fault != crash_mode) goto abort_calibration; - - if (!dumb_mode && !stage_cur && !count_bytes(trace_bits)) { - fault = FAULT_NOINST; - goto abort_calibration; - } - - cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); - - if (q->exec_cksum != cksum) { - - u8 hnb = has_new_bits(virgin_bits); - if (hnb > new_bits) new_bits = hnb; - - if (q->exec_cksum) { - - u32 i; - - for (i = 0; i < MAP_SIZE; i++) { - - if (!var_bytes[i] && first_trace[i] != trace_bits[i]) { - - var_bytes[i] = 1; - stage_max = CAL_CYCLES_LONG; - - } - - } - - var_detected = 1; - - } else { - - q->exec_cksum = cksum; - memcpy(first_trace, trace_bits, MAP_SIZE); - - } - - } - - } - - stop_us = get_cur_time_us(); - - total_cal_us += stop_us - start_us; - total_cal_cycles += stage_max; - - /* OK, let's collect some stats about the performance of this test case. - This is used for fuzzing air time calculations in calculate_score(). */ - - q->exec_us = (stop_us - start_us) / stage_max; - q->bitmap_size = count_bytes(trace_bits); - q->handicap = handicap; - q->cal_failed = 0; - - total_bitmap_size += q->bitmap_size; - total_bitmap_entries++; - - update_bitmap_score(q); - - /* If this case didn't result in new output from the instrumentation, tell - parent. This is a non-critical problem, but something to warn the user - about. */ - - if (!dumb_mode && first_run && !fault && !new_bits) fault = FAULT_NOBITS; - -abort_calibration: - - if (new_bits == 2 && !q->has_new_cov) { - q->has_new_cov = 1; - queued_with_cov++; - } - - /* Mark variable paths. */ - - if (var_detected) { - - var_byte_count = count_bytes(var_bytes); - - if (!q->var_behavior) { - mark_as_variable(q); - queued_variable++; - } - - } - - stage_name = old_sn; - stage_cur = old_sc; - stage_max = old_sm; - - if (!first_run) show_stats(); - - return fault; - -} - - -/* Examine map coverage. Called once, for first test case. */ - -static void check_map_coverage(void) { - - u32 i; - - if (count_bytes(trace_bits) < 100) return; - - for (i = (1 << (MAP_SIZE_POW2 - 1)); i < MAP_SIZE; i++) - if (trace_bits[i]) return; - - WARNF("Recompile binary with newer version of afl to improve coverage!"); - -} - - -/* Perform dry run of all test cases to confirm that the app is working as - expected. This is done only for the initial inputs, and only once. */ - -static void perform_dry_run(char** argv) { - - struct queue_entry* q = queue; - u32 cal_failures = 0; - u8* skip_crashes = getenv("AFL_SKIP_CRASHES"); - - while (q) { - - u8* use_mem; - u8 res; - s32 fd; - - u8* fn = strrchr(q->fname, '/') + 1; - - ACTF("Attempting dry run with '%s'...", fn); - - fd = open(q->fname, O_RDONLY); - if (fd < 0) PFATAL("Unable to open '%s'", q->fname); - - use_mem = ck_alloc_nozero(q->len); - - if (read(fd, use_mem, q->len) != q->len) - FATAL("Short read from '%s'", q->fname); - - close(fd); - - res = calibrate_case(argv, q, use_mem, 0, 1); - ck_free(use_mem); - - if (stop_soon) return; - - if (res == crash_mode || res == FAULT_NOBITS) - SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST, - q->len, q->bitmap_size, q->exec_us); - - switch (res) { - - case FAULT_NONE: - - if (q == queue) check_map_coverage(); - - if (crash_mode) FATAL("Test case '%s' does *NOT* crash", fn); - - break; - - case FAULT_TMOUT: - - if (timeout_given) { - - /* The -t nn+ syntax in the command line sets timeout_given to '2' and - instructs afl-fuzz to tolerate but skip queue entries that time - out. */ - - if (timeout_given > 1) { - WARNF("Test case results in a timeout (skipping)"); - q->cal_failed = CAL_CHANCES; - cal_failures++; - break; - } - - SAYF("\n" cLRD "[-] " cRST - "The program took more than %u ms to process one of the initial test cases.\n" - " Usually, the right thing to do is to relax the -t option - or to delete it\n" - " altogether and allow the fuzzer to auto-calibrate. That said, if you know\n" - " what you are doing and want to simply skip the unruly test cases, append\n" - " '+' at the end of the value passed to -t ('-t %u+').\n", exec_tmout, - exec_tmout); - - FATAL("Test case '%s' results in a timeout", fn); - - } else { - - SAYF("\n" cLRD "[-] " cRST - "The program took more than %u ms to process one of the initial test cases.\n" - " This is bad news; raising the limit with the -t option is possible, but\n" - " will probably make the fuzzing process extremely slow.\n\n" - - " If this test case is just a fluke, the other option is to just avoid it\n" - " altogether, and find one that is less of a CPU hog.\n", exec_tmout); - - FATAL("Test case '%s' results in a timeout", fn); - - } - - case FAULT_CRASH: - - if (crash_mode) break; - - if (skip_crashes) { - WARNF("Test case results in a crash (skipping)"); - q->cal_failed = CAL_CHANCES; - cal_failures++; - break; - } - - if (mem_limit) { - - SAYF("\n" cLRD "[-] " cRST - "Oops, the program crashed with one of the test cases provided. There are\n" - " several possible explanations:\n\n" - - " - The test case causes known crashes under normal working conditions. If\n" - " so, please remove it. The fuzzer should be seeded with interesting\n" - " inputs - but not ones that cause an outright crash.\n\n" - - " - The current memory limit (%s) is too low for this program, causing\n" - " it to die due to OOM when parsing valid files. To fix this, try\n" - " bumping it up with the -m setting in the command line. If in doubt,\n" - " try something along the lines of:\n\n" - -#ifdef RLIMIT_AS - " ( ulimit -Sv $[%llu << 10]; /path/to/binary [...] for troubleshooting tips.\n", - DMS(mem_limit << 20), mem_limit - 1, doc_path); - - } else { - - SAYF("\n" cLRD "[-] " cRST - "Oops, the program crashed with one of the test cases provided. There are\n" - " several possible explanations:\n\n" - - " - The test case causes known crashes under normal working conditions. If\n" - " so, please remove it. The fuzzer should be seeded with interesting\n" - " inputs - but not ones that cause an outright crash.\n\n" - -#ifdef __APPLE__ - - " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" - " break afl-fuzz performance optimizations when running platform-specific\n" - " binaries. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n" - -#endif /* __APPLE__ */ - - " - Least likely, there is a horrible bug in the fuzzer. If other options\n" - " fail, poke for troubleshooting tips.\n"); - - } - - FATAL("Test case '%s' results in a crash", fn); - - case FAULT_ERROR: - - FATAL("Unable to execute target application ('%s')", argv[0]); - - case FAULT_NOINST: - - FATAL("No instrumentation detected"); - - case FAULT_NOBITS: - - useless_at_start++; - - if (!in_bitmap && !shuffle_queue) - WARNF("No new instrumentation output, test case may be useless."); - - break; - - } - - if (q->var_behavior) WARNF("Instrumentation output varies across runs."); - - q = q->next; - - } - - if (cal_failures) { - - if (cal_failures == queued_paths) - FATAL("All test cases time out%s, giving up!", - skip_crashes ? " or crash" : ""); - - WARNF("Skipped %u test cases (%0.02f%%) due to timeouts%s.", cal_failures, - ((double)cal_failures) * 100 / queued_paths, - skip_crashes ? " or crashes" : ""); - - if (cal_failures * 5 > queued_paths) - WARNF(cLRD "High percentage of rejected test cases, check settings!"); - - } - - OKF("All test cases processed."); - -} - - -/* Helper function: link() if possible, copy otherwise. */ - -static void link_or_copy(u8* old_path, u8* new_path) { - - s32 i = link(old_path, new_path); - s32 sfd, dfd; - u8* tmp; - - if (!i) return; - - sfd = open(old_path, O_RDONLY); - if (sfd < 0) PFATAL("Unable to open '%s'", old_path); - - dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (dfd < 0) PFATAL("Unable to create '%s'", new_path); - - tmp = ck_alloc(64 * 1024); - - while ((i = read(sfd, tmp, 64 * 1024)) > 0) - ck_write(dfd, tmp, i, new_path); - - if (i < 0) PFATAL("read() failed"); - - ck_free(tmp); - close(sfd); - close(dfd); - -} - - -static void nuke_resume_dir(void); - -/* Create hard links for input test cases in the output directory, choosing - good names and pivoting accordingly. */ - -static void pivot_inputs(void) { - - struct queue_entry* q = queue; - u32 id = 0; - - ACTF("Creating hard links for all input files..."); - - while (q) { - - u8 *nfn, *rsl = strrchr(q->fname, '/'); - u32 orig_id; - - if (!rsl) rsl = q->fname; else rsl++; - - /* If the original file name conforms to the syntax and the recorded - ID matches the one we'd assign, just use the original file name. - This is valuable for resuming fuzzing runs. */ - -#ifndef SIMPLE_FILES -# define CASE_PREFIX "id:" -#else -# define CASE_PREFIX "id_" -#endif /* ^!SIMPLE_FILES */ - - if (!strncmp(rsl, CASE_PREFIX, 3) && - sscanf(rsl + 3, "%06u", &orig_id) == 1 && orig_id == id) { - - u8* src_str; - u32 src_id; - - resuming_fuzz = 1; - nfn = alloc_printf("%s/queue/%s", out_dir, rsl); - - /* Since we're at it, let's also try to find parent and figure out the - appropriate depth for this entry. */ - - src_str = strchr(rsl + 3, ':'); - - if (src_str && sscanf(src_str + 1, "%06u", &src_id) == 1) { - - struct queue_entry* s = queue; - while (src_id-- && s) s = s->next; - if (s) q->depth = s->depth + 1; - - if (max_depth < q->depth) max_depth = q->depth; - - } - - } else { - - /* No dice - invent a new name, capturing the original one as a - substring. */ - -#ifndef SIMPLE_FILES - - u8* use_name = strstr(rsl, ",orig:"); - - if (use_name) use_name += 6; else use_name = rsl; - nfn = alloc_printf("%s/queue/id:%06u,orig:%s", out_dir, id, use_name); - -#else - - nfn = alloc_printf("%s/queue/id_%06u", out_dir, id); - -#endif /* ^!SIMPLE_FILES */ - - } - - /* Pivot to the new queue entry. */ - - link_or_copy(q->fname, nfn); - ck_free(q->fname); - q->fname = nfn; - - /* Make sure that the passed_det value carries over, too. */ - - if (q->passed_det) mark_as_det_done(q); - - q = q->next; - id++; - - } - - if (in_place_resume) nuke_resume_dir(); - -} - - -#ifndef SIMPLE_FILES - -/* Construct a file name for a new test case, capturing the operation - that led to its discovery. Uses a static buffer. */ - -static u8* describe_op(u8 hnb) { - - static u8 ret[256]; - - if (syncing_party) { - - sprintf(ret, "sync:%s,src:%06u", syncing_party, syncing_case); - - } else { - - sprintf(ret, "src:%06u", current_entry); - - if (splicing_with >= 0) - sprintf(ret + strlen(ret), "+%06u", splicing_with); - - sprintf(ret + strlen(ret), ",op:%s", stage_short); - - if (stage_cur_byte >= 0) { - - sprintf(ret + strlen(ret), ",pos:%u", stage_cur_byte); - - if (stage_val_type != STAGE_VAL_NONE) - sprintf(ret + strlen(ret), ",val:%s%+d", - (stage_val_type == STAGE_VAL_BE) ? "be:" : "", - stage_cur_val); - - } else sprintf(ret + strlen(ret), ",rep:%u", stage_cur_val); - - } - - if (hnb == 2) strcat(ret, ",+cov"); - - return ret; - -} - -#endif /* !SIMPLE_FILES */ - - -/* Write a message accompanying the crash directory :-) */ - -static void write_crash_readme(void) { - - u8* fn = alloc_printf("%s/crashes/README.txt", out_dir); - s32 fd; - FILE* f; - - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - ck_free(fn); - - /* Do not die on errors here - that would be impolite. */ - - if (fd < 0) return; - - f = fdopen(fd, "w"); - - if (!f) { - close(fd); - return; - } - - fprintf(f, "Command line used to find this crash:\n\n" - - "%s\n\n" - - "If you can't reproduce a bug outside of afl-fuzz, be sure to set the same\n" - "memory limit. The limit used for this fuzzing session was %s.\n\n" - - "Need a tool to minimize test cases before investigating the crashes or sending\n" - "them to a vendor? Check out the afl-tmin that comes with the fuzzer!\n\n" - - "Found any cool bugs in open-source tools using afl-fuzz? If yes, please drop\n" - "me a mail at once the issues are fixed - I'd love to\n" - "add your finds to the gallery at:\n\n" - - " http://lcamtuf.coredump.cx/afl/\n\n" - - "Thanks :-)\n", - - orig_cmdline, DMS(mem_limit << 20)); /* ignore errors */ - - fclose(f); - -} - - -/* Check if the result of an execve() during routine fuzzing is interesting, - save or queue the input test case for further analysis if so. Returns 1 if - entry is saved, 0 otherwise. */ - -static u8 save_if_interesting(char** argv, void* mem, u32 len, u8 fault) { - - u8 *fn = ""; - u8 hnb; - s32 fd; - u8 keeping = 0, res; - - if (fault == crash_mode) { - - /* Keep only if there are new bits in the map, add to queue for - future fuzzing, etc. */ - - if (!(hnb = has_new_bits(virgin_bits))) { - if (crash_mode) total_crashes++; - return 0; - } - -#ifndef SIMPLE_FILES - - fn = alloc_printf("%s/queue/id:%06u,%s", out_dir, queued_paths, - describe_op(hnb)); - -#else - - fn = alloc_printf("%s/queue/id_%06u", out_dir, queued_paths); - -#endif /* ^!SIMPLE_FILES */ - - add_to_queue(fn, len, 0); - - if (hnb == 2) { - queue_top->has_new_cov = 1; - queued_with_cov++; - } - - queue_top->exec_cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); - - /* Try to calibrate inline; this also calls update_bitmap_score() when - successful. */ - - res = calibrate_case(argv, queue_top, mem, queue_cycle - 1, 0); - - if (res == FAULT_ERROR) - FATAL("Unable to execute target application"); - - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); - ck_write(fd, mem, len, fn); - close(fd); - - keeping = 1; - - } - - switch (fault) { - - case FAULT_TMOUT: - - /* Timeouts are not very interesting, but we're still obliged to keep - a handful of samples. We use the presence of new bits in the - hang-specific bitmap as a signal of uniqueness. In "dumb" mode, we - just keep everything. */ - - total_tmouts++; - - if (unique_hangs >= KEEP_UNIQUE_HANG) return keeping; - - if (!dumb_mode) { - -#ifdef __x86_64__ - simplify_trace((u64*)trace_bits); -#else - simplify_trace((u32*)trace_bits); -#endif /* ^__x86_64__ */ - - if (!has_new_bits(virgin_tmout)) return keeping; - - } - - unique_tmouts++; - - /* Before saving, we make sure that it's a genuine hang by re-running - the target with a more generous timeout (unless the default timeout - is already generous). */ - - if (exec_tmout < hang_tmout) { - - u8 new_fault; - write_to_testcase(mem, len); - new_fault = run_target(argv, hang_tmout); - - /* A corner case that one user reported bumping into: increasing the - timeout actually uncovers a crash. Make sure we don't discard it if - so. */ - - if (!stop_soon && new_fault == FAULT_CRASH) goto keep_as_crash; - - if (stop_soon || new_fault != FAULT_TMOUT) return keeping; - - } - -#ifndef SIMPLE_FILES - - fn = alloc_printf("%s/hangs/id:%06llu,%s", out_dir, - unique_hangs, describe_op(0)); - -#else - - fn = alloc_printf("%s/hangs/id_%06llu", out_dir, - unique_hangs); - -#endif /* ^!SIMPLE_FILES */ - - unique_hangs++; - - last_hang_time = get_cur_time(); - - break; - - case FAULT_CRASH: - -keep_as_crash: - - /* This is handled in a manner roughly similar to timeouts, - except for slightly different limits and no need to re-run test - cases. */ - - total_crashes++; - - if (unique_crashes >= KEEP_UNIQUE_CRASH) return keeping; - - if (!dumb_mode) { - -#ifdef __x86_64__ - simplify_trace((u64*)trace_bits); -#else - simplify_trace((u32*)trace_bits); -#endif /* ^__x86_64__ */ - - if (!has_new_bits(virgin_crash)) return keeping; - - } - - if (!unique_crashes) write_crash_readme(); - -#ifndef SIMPLE_FILES - - fn = alloc_printf("%s/crashes/id:%06llu,sig:%02u,%s", out_dir, - unique_crashes, kill_signal, describe_op(0)); - -#else - - fn = alloc_printf("%s/crashes/id_%06llu_%02u", out_dir, unique_crashes, - kill_signal); - -#endif /* ^!SIMPLE_FILES */ - - unique_crashes++; - - last_crash_time = get_cur_time(); - last_crash_execs = total_execs; - - break; - - case FAULT_ERROR: FATAL("Unable to execute target application"); - - default: return keeping; - - } - - /* If we're here, we apparently want to save the crash or hang - test case, too. */ - - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); - ck_write(fd, mem, len, fn); - close(fd); - - ck_free(fn); - - return keeping; - -} - - -/* When resuming, try to find the queue position to start from. This makes sense - only when resuming, and when we can find the original fuzzer_stats. */ - -static u32 find_start_position(void) { - - static u8 tmp[4096]; /* Ought to be enough for anybody. */ - - u8 *fn, *off; - s32 fd, i; - u32 ret; - - if (!resuming_fuzz) return 0; - - if (in_place_resume) fn = alloc_printf("%s/fuzzer_stats", out_dir); - else fn = alloc_printf("%s/../fuzzer_stats", in_dir); - - fd = open(fn, O_RDONLY); - ck_free(fn); - - if (fd < 0) return 0; - - i = read(fd, tmp, sizeof(tmp) - 1); (void)i; /* Ignore errors */ - close(fd); - - off = strstr(tmp, "cur_path : "); - if (!off) return 0; - - ret = atoi(off + 20); - if (ret >= queued_paths) ret = 0; - return ret; - -} - - -/* The same, but for timeouts. The idea is that when resuming sessions without - -t given, we don't want to keep auto-scaling the timeout over and over - again to prevent it from growing due to random flukes. */ - -static void find_timeout(void) { - - static u8 tmp[4096]; /* Ought to be enough for anybody. */ - - u8 *fn, *off; - s32 fd, i; - u32 ret; - - if (!resuming_fuzz) return; - - if (in_place_resume) fn = alloc_printf("%s/fuzzer_stats", out_dir); - else fn = alloc_printf("%s/../fuzzer_stats", in_dir); - - fd = open(fn, O_RDONLY); - ck_free(fn); - - if (fd < 0) return; - - i = read(fd, tmp, sizeof(tmp) - 1); (void)i; /* Ignore errors */ - close(fd); - - off = strstr(tmp, "exec_timeout : "); - if (!off) return; - - ret = atoi(off + 17); - if (ret <= 4) return; - - exec_tmout = ret; - timeout_given = 3; - -} - - -/* Update stats file for unattended monitoring. */ - -static void write_stats_file(double bitmap_cvg, double stability, double eps) { - - static double last_bcvg, last_stab, last_eps; - - u8* fn = alloc_printf("%s/fuzzer_stats", out_dir); - s32 fd; - FILE* f; - - fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); - - if (fd < 0) PFATAL("Unable to create '%s'", fn); - - ck_free(fn); - - f = fdopen(fd, "w"); - - if (!f) PFATAL("fdopen() failed"); - - /* Keep last values in case we're called from another context - where exec/sec stats and such are not readily available. */ - - if (!bitmap_cvg && !stability && !eps) { - bitmap_cvg = last_bcvg; - stability = last_stab; - eps = last_eps; - } else { - last_bcvg = bitmap_cvg; - last_stab = stability; - last_eps = eps; - } - - fprintf(f, "start_time : %llu\n" - "last_update : %llu\n" - "fuzzer_pid : %u\n" - "cycles_done : %llu\n" - "execs_done : %llu\n" - "execs_per_sec : %0.02f\n" - "paths_total : %u\n" - "paths_favored : %u\n" - "paths_found : %u\n" - "paths_imported : %u\n" - "max_depth : %u\n" - "cur_path : %u\n" /* Must match find_start_position() */ - "pending_favs : %u\n" - "pending_total : %u\n" - "variable_paths : %u\n" - "stability : %0.02f%%\n" - "bitmap_cvg : %0.02f%%\n" - "unique_crashes : %llu\n" - "unique_hangs : %llu\n" - "last_path : %llu\n" - "last_crash : %llu\n" - "last_hang : %llu\n" - "execs_since_crash : %llu\n" - "exec_timeout : %u\n" - "afl_banner : %s\n" - "afl_version : " VERSION "\n" - "target_mode : %s%s%s%s%s%s%s\n" - "command_line : %s\n", - start_time / 1000, get_cur_time() / 1000, getpid(), - queue_cycle ? (queue_cycle - 1) : 0, total_execs, eps, - queued_paths, queued_favored, queued_discovered, queued_imported, - max_depth, current_entry, pending_favored, pending_not_fuzzed, - queued_variable, stability, bitmap_cvg, unique_crashes, - unique_hangs, last_path_time / 1000, last_crash_time / 1000, - last_hang_time / 1000, total_execs - last_crash_execs, - exec_tmout, use_banner, - qemu_mode ? "qemu " : "", dumb_mode ? " dumb " : "", - no_forkserver ? "no_forksrv " : "", crash_mode ? "crash " : "", - persistent_mode ? "persistent " : "", deferred_mode ? "deferred " : "", - (qemu_mode || dumb_mode || no_forkserver || crash_mode || - persistent_mode || deferred_mode) ? "" : "default", - orig_cmdline); - /* ignore errors */ - - fclose(f); - -} - - -/* Update the plot file if there is a reason to. */ - -static void maybe_update_plot_file(double bitmap_cvg, double eps) { - - static u32 prev_qp, prev_pf, prev_pnf, prev_ce, prev_md; - static u64 prev_qc, prev_uc, prev_uh; - - if (prev_qp == queued_paths && prev_pf == pending_favored && - prev_pnf == pending_not_fuzzed && prev_ce == current_entry && - prev_qc == queue_cycle && prev_uc == unique_crashes && - prev_uh == unique_hangs && prev_md == max_depth) return; - - prev_qp = queued_paths; - prev_pf = pending_favored; - prev_pnf = pending_not_fuzzed; - prev_ce = current_entry; - prev_qc = queue_cycle; - prev_uc = unique_crashes; - prev_uh = unique_hangs; - prev_md = max_depth; - - /* Fields in the file: - - unix_time, cycles_done, cur_path, paths_total, paths_not_fuzzed, - favored_not_fuzzed, unique_crashes, unique_hangs, max_depth, - execs_per_sec */ - - fprintf(plot_file, - "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f\n", - get_cur_time() / 1000, queue_cycle - 1, current_entry, queued_paths, - pending_not_fuzzed, pending_favored, bitmap_cvg, unique_crashes, - unique_hangs, max_depth, eps); /* ignore errors */ - - fflush(plot_file); - -} - - - -/* A helper function for maybe_delete_out_dir(), deleting all prefixed - files in a directory. */ - -static u8 delete_files(u8* path, u8* prefix) { - - DIR* d; - struct dirent* d_ent; - - d = opendir(path); - - if (!d) return 0; - - while ((d_ent = readdir(d))) { - - if (d_ent->d_name[0] != '.' && (!prefix || - !strncmp(d_ent->d_name, prefix, strlen(prefix)))) { - - u8* fname = alloc_printf("%s/%s", path, d_ent->d_name); - if (unlink(fname)) PFATAL("Unable to delete '%s'", fname); - ck_free(fname); - - } - - } - - closedir(d); - - return !!rmdir(path); - -} - - -/* Get the number of runnable processes, with some simple smoothing. */ - -static double get_runnable_processes(void) { - - static double res; - -#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) - - /* I don't see any portable sysctl or so that would quickly give us the - number of runnable processes; the 1-minute load average can be a - semi-decent approximation, though. */ - - if (getloadavg(&res, 1) != 1) return 0; - -#else - - /* On Linux, /proc/stat is probably the best way; load averages are - computed in funny ways and sometimes don't reflect extremely short-lived - processes well. */ - - FILE* f = fopen("/proc/stat", "r"); - u8 tmp[1024]; - u32 val = 0; - - if (!f) return 0; - - while (fgets(tmp, sizeof(tmp), f)) { - - if (!strncmp(tmp, "procs_running ", 14) || - !strncmp(tmp, "procs_blocked ", 14)) val += atoi(tmp + 14); - - } - - fclose(f); - - if (!res) { - - res = val; - - } else { - - res = res * (1.0 - 1.0 / AVG_SMOOTHING) + - ((double)val) * (1.0 / AVG_SMOOTHING); - - } - -#endif /* ^(__APPLE__ || __FreeBSD__ || __OpenBSD__) */ - - return res; - -} - - -/* Delete the temporary directory used for in-place session resume. */ - -static void nuke_resume_dir(void) { - - u8* fn; - - fn = alloc_printf("%s/_resume/.state/deterministic_done", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/_resume/.state/auto_extras", out_dir); - if (delete_files(fn, "auto_")) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/_resume/.state/redundant_edges", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/_resume/.state/variable_behavior", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/_resume/.state", out_dir); - if (rmdir(fn) && errno != ENOENT) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/_resume", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - return; - -dir_cleanup_failed: - - FATAL("_resume directory cleanup failed"); - -} - - -/* Delete fuzzer output directory if we recognize it as ours, if the fuzzer - is not currently running, and if the last run time isn't too great. */ - -static void maybe_delete_out_dir(void) { - - FILE* f; - u8 *fn = alloc_printf("%s/fuzzer_stats", out_dir); - - /* See if the output directory is locked. If yes, bail out. If not, - create a lock that will persist for the lifetime of the process - (this requires leaving the descriptor open).*/ - - out_dir_fd = open(out_dir, O_RDONLY); - if (out_dir_fd < 0) PFATAL("Unable to open '%s'", out_dir); - -#ifndef __sun - - if (flock(out_dir_fd, LOCK_EX | LOCK_NB) && errno == EWOULDBLOCK) { - - SAYF("\n" cLRD "[-] " cRST - "Looks like the job output directory is being actively used by another\n" - " instance of afl-fuzz. You will need to choose a different %s\n" - " or stop the other process first.\n", - sync_id ? "fuzzer ID" : "output location"); - - FATAL("Directory '%s' is in use", out_dir); - - } - -#endif /* !__sun */ - - f = fopen(fn, "r"); - - if (f) { - - u64 start_time, last_update; - - if (fscanf(f, "start_time : %llu\n" - "last_update : %llu\n", &start_time, &last_update) != 2) - FATAL("Malformed data in '%s'", fn); - - fclose(f); - - /* Let's see how much work is at stake. */ - - if (!in_place_resume && last_update - start_time > OUTPUT_GRACE * 60) { - - SAYF("\n" cLRD "[-] " cRST - "The job output directory already exists and contains the results of more\n" - " than %u minutes worth of fuzzing. To avoid data loss, afl-fuzz will *NOT*\n" - " automatically delete this data for you.\n\n" - - " If you wish to start a new session, remove or rename the directory manually,\n" - " or specify a different output location for this job. To resume the old\n" - " session, put '-' as the input directory in the command line ('-i -') and\n" - " try again.\n", OUTPUT_GRACE); - - FATAL("At-risk data found in '%s'", out_dir); - - } - - } - - ck_free(fn); - - /* The idea for in-place resume is pretty simple: we temporarily move the old - queue/ to a new location that gets deleted once import to the new queue/ - is finished. If _resume/ already exists, the current queue/ may be - incomplete due to an earlier abort, so we want to use the old _resume/ - dir instead, and we let rename() fail silently. */ - - if (in_place_resume) { - - u8* orig_q = alloc_printf("%s/queue", out_dir); - - in_dir = alloc_printf("%s/_resume", out_dir); - - rename(orig_q, in_dir); /* Ignore errors */ - - OKF("Output directory exists, will attempt session resume."); - - ck_free(orig_q); - - } else { - - OKF("Output directory exists but deemed OK to reuse."); - - } - - ACTF("Deleting old session data..."); - - /* Okay, let's get the ball rolling! First, we need to get rid of the entries - in /.synced/.../id:*, if any are present. */ - - if (!in_place_resume) { - - fn = alloc_printf("%s/.synced", out_dir); - if (delete_files(fn, NULL)) goto dir_cleanup_failed; - ck_free(fn); - - } - - /* Next, we need to clean up /queue/.state/ subdirectories: */ - - fn = alloc_printf("%s/queue/.state/deterministic_done", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/queue/.state/auto_extras", out_dir); - if (delete_files(fn, "auto_")) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/queue/.state/redundant_edges", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/queue/.state/variable_behavior", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - /* Then, get rid of the .state subdirectory itself (should be empty by now) - and everything matching /queue/id:*. */ - - fn = alloc_printf("%s/queue/.state", out_dir); - if (rmdir(fn) && errno != ENOENT) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/queue", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - /* All right, let's do /crashes/id:* and /hangs/id:*. */ - - if (!in_place_resume) { - - fn = alloc_printf("%s/crashes/README.txt", out_dir); - unlink(fn); /* Ignore errors */ - ck_free(fn); - - } - - fn = alloc_printf("%s/crashes", out_dir); - - /* Make backup of the crashes directory if it's not empty and if we're - doing in-place resume. */ - - if (in_place_resume && rmdir(fn)) { - - time_t cur_t = time(0); - struct tm* t = localtime(&cur_t); - -#ifndef SIMPLE_FILES - - u8* nfn = alloc_printf("%s.%04u-%02u-%02u-%02u:%02u:%02u", fn, - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); - -#else - - u8* nfn = alloc_printf("%s_%04u%02u%02u%02u%02u%02u", fn, - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); - -#endif /* ^!SIMPLE_FILES */ - - rename(fn, nfn); /* Ignore errors. */ - ck_free(nfn); - - } - - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/hangs", out_dir); - - /* Backup hangs, too. */ - - if (in_place_resume && rmdir(fn)) { - - time_t cur_t = time(0); - struct tm* t = localtime(&cur_t); - -#ifndef SIMPLE_FILES - - u8* nfn = alloc_printf("%s.%04u-%02u-%02u-%02u:%02u:%02u", fn, - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); - -#else - - u8* nfn = alloc_printf("%s_%04u%02u%02u%02u%02u%02u", fn, - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); - -#endif /* ^!SIMPLE_FILES */ - - rename(fn, nfn); /* Ignore errors. */ - ck_free(nfn); - - } - - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - /* And now, for some finishing touches. */ - - fn = alloc_printf("%s/.cur_input", out_dir); - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/fuzz_bitmap", out_dir); - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; - ck_free(fn); - - if (!in_place_resume) { - fn = alloc_printf("%s/fuzzer_stats", out_dir); - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; - ck_free(fn); - } - - fn = alloc_printf("%s/plot_data", out_dir); - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; - ck_free(fn); - - OKF("Output dir cleanup successful."); - - /* Wow... is that all? If yes, celebrate! */ - - return; - -dir_cleanup_failed: - - SAYF("\n" cLRD "[-] " cRST - "Whoops, the fuzzer tried to reuse your output directory, but bumped into\n" - " some files that shouldn't be there or that couldn't be removed - so it\n" - " decided to abort! This happened while processing this path:\n\n" - - " %s\n\n" - " Please examine and manually delete the files, or specify a different\n" - " output location for the tool.\n", fn); - - FATAL("Output directory cleanup failed"); - -} - - -static void check_term_size(void); - - -/* A spiffy retro stats screen! This is called every stats_update_freq - execve() calls, plus in several other circumstances. */ - -static void show_stats(void) { - - static u64 last_stats_ms, last_plot_ms, last_ms, last_execs; - static double avg_exec; - double t_byte_ratio, stab_ratio; - - u64 cur_ms; - u32 t_bytes, t_bits; - - u32 banner_len, banner_pad; - u8 tmp[256]; - - cur_ms = get_cur_time(); - - /* If not enough time has passed since last UI update, bail out. */ - - if (cur_ms - last_ms < 1000 / UI_TARGET_HZ) return; - - /* Check if we're past the 10 minute mark. */ - - if (cur_ms - start_time > 10 * 60 * 1000) run_over10m = 1; - - /* Calculate smoothed exec speed stats. */ - - if (!last_execs) { - - avg_exec = ((double)total_execs) * 1000 / (cur_ms - start_time); - - } else { - - double cur_avg = ((double)(total_execs - last_execs)) * 1000 / - (cur_ms - last_ms); - - /* If there is a dramatic (5x+) jump in speed, reset the indicator - more quickly. */ - - if (cur_avg * 5 < avg_exec || cur_avg / 5 > avg_exec) - avg_exec = cur_avg; - - avg_exec = avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) + - cur_avg * (1.0 / AVG_SMOOTHING); - - } - - last_ms = cur_ms; - last_execs = total_execs; - - /* Tell the callers when to contact us (as measured in execs). */ - - stats_update_freq = avg_exec / (UI_TARGET_HZ * 10); - if (!stats_update_freq) stats_update_freq = 1; - - /* Do some bitmap stats. */ - - t_bytes = count_non_255_bytes(virgin_bits); - t_byte_ratio = ((double)t_bytes * 100) / MAP_SIZE; - - if (t_bytes) - stab_ratio = 100 - ((double)var_byte_count) * 100 / t_bytes; - else - stab_ratio = 100; - - /* Roughly every minute, update fuzzer stats and save auto tokens. */ - - if (cur_ms - last_stats_ms > STATS_UPDATE_SEC * 1000) { - - last_stats_ms = cur_ms; - write_stats_file(t_byte_ratio, stab_ratio, avg_exec); - save_auto(); - write_bitmap(); - - } - - /* Every now and then, write plot data. */ - - if (cur_ms - last_plot_ms > PLOT_UPDATE_SEC * 1000) { - - last_plot_ms = cur_ms; - maybe_update_plot_file(t_byte_ratio, avg_exec); - - } - - /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */ - - if (!dumb_mode && cycles_wo_finds > 100 && !pending_not_fuzzed && - getenv("AFL_EXIT_WHEN_DONE")) stop_soon = 2; - - if (total_crashes && getenv("AFL_BENCH_UNTIL_CRASH")) stop_soon = 2; - - /* If we're not on TTY, bail out. */ - - if (not_on_tty) return; - - /* Compute some mildly useful bitmap stats. */ - - t_bits = (MAP_SIZE << 3) - count_bits(virgin_bits); - - /* Now, for the visuals... */ - - if (clear_screen) { - - SAYF(TERM_CLEAR CURSOR_HIDE); - clear_screen = 0; - - check_term_size(); - - } - - SAYF(TERM_HOME); - - if (term_too_small) { - - SAYF(cBRI "Your terminal is too small to display the UI.\n" - "Please resize terminal window to at least 80x25.\n" cRST); - - return; - - } - - /* Let's start by drawing a centered banner. */ - - banner_len = (crash_mode ? 24 : 22) + strlen(VERSION) + strlen(use_banner); - banner_pad = (80 - banner_len) / 2; - memset(tmp, ' ', banner_pad); - - sprintf(tmp + banner_pad, "%s " cLCY VERSION cLGN - " (%s)", crash_mode ? cPIN "peruvian were-rabbit" : - cYEL "american fuzzy lop", use_banner); - - SAYF("\n%s\n\n", tmp); - - /* "Handy" shortcuts for drawing boxes... */ - -#define bSTG bSTART cGRA -#define bH2 bH bH -#define bH5 bH2 bH2 bH -#define bH10 bH5 bH5 -#define bH20 bH10 bH10 -#define bH30 bH20 bH10 -#define SP5 " " -#define SP10 SP5 SP5 -#define SP20 SP10 SP10 - - /* Lord, forgive me this. */ - - SAYF(SET_G1 bSTG bLT bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH2 bHB - bH bSTOP cCYA " overall results " bSTG bH5 bRT "\n"); - - if (dumb_mode) { - - strcpy(tmp, cRST); - - } else { - - u64 min_wo_finds = (cur_ms - last_path_time) / 1000 / 60; - - /* First queue cycle: don't stop now! */ - if (queue_cycle == 1 || min_wo_finds < 15) strcpy(tmp, cMGN); else - - /* Subsequent cycles, but we're still making finds. */ - if (cycles_wo_finds < 25 || min_wo_finds < 30) strcpy(tmp, cYEL); else - - /* No finds for a long time and no test cases to try. */ - if (cycles_wo_finds > 100 && !pending_not_fuzzed && min_wo_finds > 120) - strcpy(tmp, cLGN); - - /* Default: cautiously OK to stop? */ - else strcpy(tmp, cLBL); - - } - - SAYF(bV bSTOP " run time : " cRST "%-34s " bSTG bV bSTOP - " cycles done : %s%-5s " bSTG bV "\n", - DTD(cur_ms, start_time), tmp, DI(queue_cycle - 1)); - - /* We want to warn people about not seeing new paths after a full cycle, - except when resuming fuzzing or running in non-instrumented mode. */ - - if (!dumb_mode && (last_path_time || resuming_fuzz || queue_cycle == 1 || - in_bitmap || crash_mode)) { - - SAYF(bV bSTOP " last new path : " cRST "%-34s ", - DTD(cur_ms, last_path_time)); - - } else { - - if (dumb_mode) - - SAYF(bV bSTOP " last new path : " cPIN "n/a" cRST - " (non-instrumented mode) "); - - else - - SAYF(bV bSTOP " last new path : " cRST "none yet " cLRD - "(odd, check syntax!) "); - - } - - SAYF(bSTG bV bSTOP " total paths : " cRST "%-5s " bSTG bV "\n", - DI(queued_paths)); - - /* Highlight crashes in red if found, denote going over the KEEP_UNIQUE_CRASH - limit with a '+' appended to the count. */ - - sprintf(tmp, "%s%s", DI(unique_crashes), - (unique_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); - - SAYF(bV bSTOP " last uniq crash : " cRST "%-34s " bSTG bV bSTOP - " uniq crashes : %s%-6s " bSTG bV "\n", - DTD(cur_ms, last_crash_time), unique_crashes ? cLRD : cRST, - tmp); - - sprintf(tmp, "%s%s", DI(unique_hangs), - (unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); - - SAYF(bV bSTOP " last uniq hang : " cRST "%-34s " bSTG bV bSTOP - " uniq hangs : " cRST "%-6s " bSTG bV "\n", - DTD(cur_ms, last_hang_time), tmp); - - SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH20 bHB bH bSTOP cCYA - " map coverage " bSTG bH bHT bH20 bH2 bH bVL "\n"); - - /* This gets funny because we want to print several variable-length variables - together, but then cram them into a fixed-width field - so we need to - put them in a temporary buffer first. */ - - sprintf(tmp, "%s%s (%0.02f%%)", DI(current_entry), - queue_cur->favored ? "" : "*", - ((double)current_entry * 100) / queued_paths); - - SAYF(bV bSTOP " now processing : " cRST "%-17s " bSTG bV bSTOP, tmp); - - sprintf(tmp, "%0.02f%% / %0.02f%%", ((double)queue_cur->bitmap_size) * - 100 / MAP_SIZE, t_byte_ratio); - - SAYF(" map density : %s%-21s " bSTG bV "\n", t_byte_ratio > 70 ? cLRD : - ((t_bytes < 200 && !dumb_mode) ? cPIN : cRST), tmp); - - sprintf(tmp, "%s (%0.02f%%)", DI(cur_skipped_paths), - ((double)cur_skipped_paths * 100) / queued_paths); - - SAYF(bV bSTOP " paths timed out : " cRST "%-17s " bSTG bV, tmp); - - sprintf(tmp, "%0.02f bits/tuple", - t_bytes ? (((double)t_bits) / t_bytes) : 0); - - SAYF(bSTOP " count coverage : " cRST "%-21s " bSTG bV "\n", tmp); - - SAYF(bVR bH bSTOP cCYA " stage progress " bSTG bH20 bX bH bSTOP cCYA - " findings in depth " bSTG bH20 bVL "\n"); - - sprintf(tmp, "%s (%0.02f%%)", DI(queued_favored), - ((double)queued_favored) * 100 / queued_paths); - - /* Yeah... it's still going on... halp? */ - - SAYF(bV bSTOP " now trying : " cRST "%-21s " bSTG bV bSTOP - " favored paths : " cRST "%-22s " bSTG bV "\n", stage_name, tmp); - - if (!stage_max) { - - sprintf(tmp, "%s/-", DI(stage_cur)); - - } else { - - sprintf(tmp, "%s/%s (%0.02f%%)", DI(stage_cur), DI(stage_max), - ((double)stage_cur) * 100 / stage_max); - - } - - SAYF(bV bSTOP " stage execs : " cRST "%-21s " bSTG bV bSTOP, tmp); - - sprintf(tmp, "%s (%0.02f%%)", DI(queued_with_cov), - ((double)queued_with_cov) * 100 / queued_paths); - - SAYF(" new edges on : " cRST "%-22s " bSTG bV "\n", tmp); - - sprintf(tmp, "%s (%s%s unique)", DI(total_crashes), DI(unique_crashes), - (unique_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); - - if (crash_mode) { - - SAYF(bV bSTOP " total execs : " cRST "%-21s " bSTG bV bSTOP - " new crashes : %s%-22s " bSTG bV "\n", DI(total_execs), - unique_crashes ? cLRD : cRST, tmp); - - } else { - - SAYF(bV bSTOP " total execs : " cRST "%-21s " bSTG bV bSTOP - " total crashes : %s%-22s " bSTG bV "\n", DI(total_execs), - unique_crashes ? cLRD : cRST, tmp); - - } - - /* Show a warning about slow execution. */ - - if (avg_exec < 100) { - - sprintf(tmp, "%s/sec (%s)", DF(avg_exec), avg_exec < 20 ? - "zzzz..." : "slow!"); - - SAYF(bV bSTOP " exec speed : " cLRD "%-21s ", tmp); - - } else { - - sprintf(tmp, "%s/sec", DF(avg_exec)); - SAYF(bV bSTOP " exec speed : " cRST "%-21s ", tmp); - - } - - sprintf(tmp, "%s (%s%s unique)", DI(total_tmouts), DI(unique_tmouts), - (unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); - - SAYF (bSTG bV bSTOP " total tmouts : " cRST "%-22s " bSTG bV "\n", tmp); - - /* Aaaalmost there... hold on! */ - - SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bH bHT bH10 - bH5 bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bH bVL "\n"); - - if (skip_deterministic) { - - strcpy(tmp, "n/a, n/a, n/a"); - - } else { - - sprintf(tmp, "%s/%s, %s/%s, %s/%s", - DI(stage_finds[STAGE_FLIP1]), DI(stage_cycles[STAGE_FLIP1]), - DI(stage_finds[STAGE_FLIP2]), DI(stage_cycles[STAGE_FLIP2]), - DI(stage_finds[STAGE_FLIP4]), DI(stage_cycles[STAGE_FLIP4])); - - } - - SAYF(bV bSTOP " bit flips : " cRST "%-37s " bSTG bV bSTOP " levels : " - cRST "%-10s " bSTG bV "\n", tmp, DI(max_depth)); - - if (!skip_deterministic) - sprintf(tmp, "%s/%s, %s/%s, %s/%s", - DI(stage_finds[STAGE_FLIP8]), DI(stage_cycles[STAGE_FLIP8]), - DI(stage_finds[STAGE_FLIP16]), DI(stage_cycles[STAGE_FLIP16]), - DI(stage_finds[STAGE_FLIP32]), DI(stage_cycles[STAGE_FLIP32])); - - SAYF(bV bSTOP " byte flips : " cRST "%-37s " bSTG bV bSTOP " pending : " - cRST "%-10s " bSTG bV "\n", tmp, DI(pending_not_fuzzed)); - - if (!skip_deterministic) - sprintf(tmp, "%s/%s, %s/%s, %s/%s", - DI(stage_finds[STAGE_ARITH8]), DI(stage_cycles[STAGE_ARITH8]), - DI(stage_finds[STAGE_ARITH16]), DI(stage_cycles[STAGE_ARITH16]), - DI(stage_finds[STAGE_ARITH32]), DI(stage_cycles[STAGE_ARITH32])); - - SAYF(bV bSTOP " arithmetics : " cRST "%-37s " bSTG bV bSTOP " pend fav : " - cRST "%-10s " bSTG bV "\n", tmp, DI(pending_favored)); - - if (!skip_deterministic) - sprintf(tmp, "%s/%s, %s/%s, %s/%s", - DI(stage_finds[STAGE_INTEREST8]), DI(stage_cycles[STAGE_INTEREST8]), - DI(stage_finds[STAGE_INTEREST16]), DI(stage_cycles[STAGE_INTEREST16]), - DI(stage_finds[STAGE_INTEREST32]), DI(stage_cycles[STAGE_INTEREST32])); - - SAYF(bV bSTOP " known ints : " cRST "%-37s " bSTG bV bSTOP " own finds : " - cRST "%-10s " bSTG bV "\n", tmp, DI(queued_discovered)); - - if (!skip_deterministic) - sprintf(tmp, "%s/%s, %s/%s, %s/%s", - DI(stage_finds[STAGE_EXTRAS_UO]), DI(stage_cycles[STAGE_EXTRAS_UO]), - DI(stage_finds[STAGE_EXTRAS_UI]), DI(stage_cycles[STAGE_EXTRAS_UI]), - DI(stage_finds[STAGE_EXTRAS_AO]), DI(stage_cycles[STAGE_EXTRAS_AO])); - - SAYF(bV bSTOP " dictionary : " cRST "%-37s " bSTG bV bSTOP - " imported : " cRST "%-10s " bSTG bV "\n", tmp, - sync_id ? DI(queued_imported) : (u8*)"n/a"); - - sprintf(tmp, "%s/%s, %s/%s", - DI(stage_finds[STAGE_HAVOC]), DI(stage_cycles[STAGE_HAVOC]), - DI(stage_finds[STAGE_SPLICE]), DI(stage_cycles[STAGE_SPLICE])); - - SAYF(bV bSTOP " havoc : " cRST "%-37s " bSTG bV bSTOP, tmp); - - if (t_bytes) sprintf(tmp, "%0.02f%%", stab_ratio); - else strcpy(tmp, "n/a"); - - SAYF(" stability : %s%-10s " bSTG bV "\n", (stab_ratio < 85 && var_byte_count > 40) - ? cLRD : ((queued_variable && (!persistent_mode || var_byte_count > 20)) - ? cMGN : cRST), tmp); - - if (!bytes_trim_out) { - - sprintf(tmp, "n/a, "); - - } else { - - sprintf(tmp, "%0.02f%%/%s, ", - ((double)(bytes_trim_in - bytes_trim_out)) * 100 / bytes_trim_in, - DI(trim_execs)); - - } - - if (!blocks_eff_total) { - - u8 tmp2[128]; - - sprintf(tmp2, "n/a"); - strcat(tmp, tmp2); - - } else { - - u8 tmp2[128]; - - sprintf(tmp2, "%0.02f%%", - ((double)(blocks_eff_total - blocks_eff_select)) * 100 / - blocks_eff_total); - - strcat(tmp, tmp2); - - } - - SAYF(bV bSTOP " trim : " cRST "%-37s " bSTG bVR bH20 bH2 bH2 bRB "\n" - bLB bH30 bH20 bH2 bH bRB bSTOP cRST RESET_G1, tmp); - - /* Provide some CPU utilization stats. */ - - if (cpu_core_count) { - - double cur_runnable = get_runnable_processes(); - u32 cur_utilization = cur_runnable * 100 / cpu_core_count; - - u8* cpu_color = cCYA; - - /* If we could still run one or more processes, use green. */ - - if (cpu_core_count > 1 && cur_runnable + 1 <= cpu_core_count) - cpu_color = cLGN; - - /* If we're clearly oversubscribed, use red. */ - - if (!no_cpu_meter_red && cur_utilization >= 150) cpu_color = cLRD; - -#ifdef HAVE_AFFINITY - - if (cpu_aff >= 0) { - - SAYF(SP10 cGRA "[cpu%03u:%s%3u%%" cGRA "]\r" cRST, - MIN(cpu_aff, 999), cpu_color, - MIN(cur_utilization, 999)); - - } else { - - SAYF(SP10 cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, - cpu_color, MIN(cur_utilization, 999)); - - } - -#else - - SAYF(SP10 cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, - cpu_color, MIN(cur_utilization, 999)); - -#endif /* ^HAVE_AFFINITY */ - - } else SAYF("\r"); - - /* Hallelujah! */ - - fflush(0); - -} - - -/* Display quick statistics at the end of processing the input directory, - plus a bunch of warnings. Some calibration stuff also ended up here, - along with several hardcoded constants. Maybe clean up eventually. */ - -static void show_init_stats(void) { - - struct queue_entry* q = queue; - u32 min_bits = 0, max_bits = 0; - u64 min_us = 0, max_us = 0; - u64 avg_us = 0; - u32 max_len = 0; - - if (total_cal_cycles) avg_us = total_cal_us / total_cal_cycles; - - while (q) { - - if (!min_us || q->exec_us < min_us) min_us = q->exec_us; - if (q->exec_us > max_us) max_us = q->exec_us; - - if (!min_bits || q->bitmap_size < min_bits) min_bits = q->bitmap_size; - if (q->bitmap_size > max_bits) max_bits = q->bitmap_size; - - if (q->len > max_len) max_len = q->len; - - q = q->next; - - } - - SAYF("\n"); - - if (avg_us > (qemu_mode ? 50000 : 10000)) - WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.txt.", - doc_path); - - /* Let's keep things moving with slow binaries. */ - - if (avg_us > 50000) havoc_div = 10; /* 0-19 execs/sec */ - else if (avg_us > 20000) havoc_div = 5; /* 20-49 execs/sec */ - else if (avg_us > 10000) havoc_div = 2; /* 50-100 execs/sec */ - - if (!resuming_fuzz) { - - if (max_len > 50 * 1024) - WARNF(cLRD "Some test cases are huge (%s) - see %s/perf_tips.txt!", - DMS(max_len), doc_path); - else if (max_len > 10 * 1024) - WARNF("Some test cases are big (%s) - see %s/perf_tips.txt.", - DMS(max_len), doc_path); - - if (useless_at_start && !in_bitmap) - WARNF(cLRD "Some test cases look useless. Consider using a smaller set."); - - if (queued_paths > 100) - WARNF(cLRD "You probably have far too many input files! Consider trimming down."); - else if (queued_paths > 20) - WARNF("You have lots of input files; try starting small."); - - } - - OKF("Here are some useful stats:\n\n" - - cGRA " Test case count : " cRST "%u favored, %u variable, %u total\n" - cGRA " Bitmap range : " cRST "%u to %u bits (average: %0.02f bits)\n" - cGRA " Exec timing : " cRST "%s to %s us (average: %s us)\n", - queued_favored, queued_variable, queued_paths, min_bits, max_bits, - ((double)total_bitmap_size) / (total_bitmap_entries ? total_bitmap_entries : 1), - DI(min_us), DI(max_us), DI(avg_us)); - - if (!timeout_given) { - - /* Figure out the appropriate timeout. The basic idea is: 5x average or - 1x max, rounded up to EXEC_TM_ROUND ms and capped at 1 second. - - If the program is slow, the multiplier is lowered to 2x or 3x, because - random scheduler jitter is less likely to have any impact, and because - our patience is wearing thin =) */ - - if (avg_us > 50000) exec_tmout = avg_us * 2 / 1000; - else if (avg_us > 10000) exec_tmout = avg_us * 3 / 1000; - else exec_tmout = avg_us * 5 / 1000; - - exec_tmout = MAX(exec_tmout, max_us / 1000); - exec_tmout = (exec_tmout + EXEC_TM_ROUND) / EXEC_TM_ROUND * EXEC_TM_ROUND; - - if (exec_tmout > EXEC_TIMEOUT) exec_tmout = EXEC_TIMEOUT; - - ACTF("No -t option specified, so I'll use exec timeout of %u ms.", - exec_tmout); - - timeout_given = 1; - - } else if (timeout_given == 3) { - - ACTF("Applying timeout settings from resumed session (%u ms).", exec_tmout); - - } - - /* In dumb mode, re-running every timing out test case with a generous time - limit is very expensive, so let's select a more conservative default. */ - - if (dumb_mode && !getenv("AFL_HANG_TMOUT")) - hang_tmout = MIN(EXEC_TIMEOUT, exec_tmout * 2 + 100); - - OKF("All set and ready to roll!"); - -} - - -/* Find first power of two greater or equal to val (assuming val under - 2^31). */ - -static u32 next_p2(u32 val) { - - u32 ret = 1; - while (val > ret) ret <<= 1; - return ret; - -} - - -/* Trim all new test cases to save cycles when doing deterministic checks. The - trimmer uses power-of-two increments somewhere between 1/16 and 1/1024 of - file size, to keep the stage short and sweet. */ - -static u8 trim_case(char** argv, struct queue_entry* q, u8* in_buf) { - - static u8 tmp[64]; - static u8 clean_trace[MAP_SIZE]; - - u8 needs_write = 0, fault = 0; - u32 trim_exec = 0; - u32 remove_len; - u32 len_p2; - - /* Although the trimmer will be less useful when variable behavior is - detected, it will still work to some extent, so we don't check for - this. */ - - if (q->len < 5) return 0; - - stage_name = tmp; - bytes_trim_in += q->len; - - /* Select initial chunk len, starting with large steps. */ - - len_p2 = next_p2(q->len); - - remove_len = MAX(len_p2 / TRIM_START_STEPS, TRIM_MIN_BYTES); - - /* Continue until the number of steps gets too high or the stepover - gets too small. */ - - while (remove_len >= MAX(len_p2 / TRIM_END_STEPS, TRIM_MIN_BYTES)) { - - u32 remove_pos = remove_len; - - sprintf(tmp, "trim %s/%s", DI(remove_len), DI(remove_len)); - - stage_cur = 0; - stage_max = q->len / remove_len; - - while (remove_pos < q->len) { - - u32 trim_avail = MIN(remove_len, q->len - remove_pos); - u32 cksum; - - write_with_gap(in_buf, q->len, remove_pos, trim_avail); - - fault = run_target(argv, exec_tmout); - trim_execs++; - - if (stop_soon || fault == FAULT_ERROR) goto abort_trimming; - - /* Note that we don't keep track of crashes or hangs here; maybe TODO? */ - - cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); - - /* If the deletion had no impact on the trace, make it permanent. This - isn't perfect for variable-path inputs, but we're just making a - best-effort pass, so it's not a big deal if we end up with false - negatives every now and then. */ - - if (cksum == q->exec_cksum) { - - u32 move_tail = q->len - remove_pos - trim_avail; - - q->len -= trim_avail; - len_p2 = next_p2(q->len); - - memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail, - move_tail); - - /* Let's save a clean trace, which will be needed by - update_bitmap_score once we're done with the trimming stuff. */ - - if (!needs_write) { - - needs_write = 1; - memcpy(clean_trace, trace_bits, MAP_SIZE); - - } - - } else remove_pos += remove_len; - - /* Since this can be slow, update the screen every now and then. */ - - if (!(trim_exec++ % stats_update_freq)) show_stats(); - stage_cur++; - - } - - remove_len >>= 1; - - } - - /* If we have made changes to in_buf, we also need to update the on-disk - version of the test case. */ - - if (needs_write) { - - s32 fd; - - unlink(q->fname); /* ignore errors */ - - fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600); - - if (fd < 0) PFATAL("Unable to create '%s'", q->fname); - - ck_write(fd, in_buf, q->len, q->fname); - close(fd); - - memcpy(trace_bits, clean_trace, MAP_SIZE); - update_bitmap_score(q); - - } - -abort_trimming: - - bytes_trim_out += q->len; - return fault; - -} - - -/* Write a modified test case, run program, process results. Handle - error conditions, returning 1 if it's time to bail out. This is - a helper function for fuzz_one(). */ - -EXP_ST u8 common_fuzz_stuff(char** argv, u8* out_buf, u32 len) { - - u8 fault; - - if (post_handler) { - - out_buf = post_handler(out_buf, &len); - if (!out_buf || !len) return 0; - - } - - write_to_testcase(out_buf, len); - - fault = run_target(argv, exec_tmout); - - if (stop_soon) return 1; - - if (fault == FAULT_TMOUT) { - - if (subseq_tmouts++ > TMOUT_LIMIT) { - cur_skipped_paths++; - return 1; - } - - } else subseq_tmouts = 0; - - /* Users can hit us with SIGUSR1 to request the current input - to be abandoned. */ - - if (skip_requested) { - - skip_requested = 0; - cur_skipped_paths++; - return 1; - - } - - /* This handles FAULT_ERROR for us: */ - - queued_discovered += save_if_interesting(argv, out_buf, len, fault); - - if (!(stage_cur % stats_update_freq) || stage_cur + 1 == stage_max) - show_stats(); - - return 0; - -} - - -/* Helper to choose random block len for block operations in fuzz_one(). - Doesn't return zero, provided that max_len is > 0. */ - -static u32 choose_block_len(u32 limit) { - - u32 min_value, max_value; - u32 rlim = MIN(queue_cycle, 3); - - if (!run_over10m) rlim = 1; - - switch (UR(rlim)) { - - case 0: min_value = 1; - max_value = HAVOC_BLK_SMALL; - break; - - case 1: min_value = HAVOC_BLK_SMALL; - max_value = HAVOC_BLK_MEDIUM; - break; - - default: - - if (UR(10)) { - - min_value = HAVOC_BLK_MEDIUM; - max_value = HAVOC_BLK_LARGE; - - } else { - - min_value = HAVOC_BLK_LARGE; - max_value = HAVOC_BLK_XL; - - } - - } - - if (min_value >= limit) min_value = 1; - - return min_value + UR(MIN(max_value, limit) - min_value + 1); - -} - - -/* Calculate case desirability score to adjust the length of havoc fuzzing. - A helper function for fuzz_one(). Maybe some of these constants should - go into config.h. */ - -static u32 calculate_score(struct queue_entry* q) { - - u32 avg_exec_us = total_cal_us / total_cal_cycles; - u32 avg_bitmap_size = total_bitmap_size / total_bitmap_entries; - u32 perf_score = 100; - - /* Adjust score based on execution speed of this path, compared to the - global average. Multiplier ranges from 0.1x to 3x. Fast inputs are - less expensive to fuzz, so we're giving them more air time. */ - - if (q->exec_us * 0.1 > avg_exec_us) perf_score = 10; - else if (q->exec_us * 0.25 > avg_exec_us) perf_score = 25; - else if (q->exec_us * 0.5 > avg_exec_us) perf_score = 50; - else if (q->exec_us * 0.75 > avg_exec_us) perf_score = 75; - else if (q->exec_us * 4 < avg_exec_us) perf_score = 300; - else if (q->exec_us * 3 < avg_exec_us) perf_score = 200; - else if (q->exec_us * 2 < avg_exec_us) perf_score = 150; - - /* Adjust score based on bitmap size. The working theory is that better - coverage translates to better targets. Multiplier from 0.25x to 3x. */ - - if (q->bitmap_size * 0.3 > avg_bitmap_size) perf_score *= 3; - else if (q->bitmap_size * 0.5 > avg_bitmap_size) perf_score *= 2; - else if (q->bitmap_size * 0.75 > avg_bitmap_size) perf_score *= 1.5; - else if (q->bitmap_size * 3 < avg_bitmap_size) perf_score *= 0.25; - else if (q->bitmap_size * 2 < avg_bitmap_size) perf_score *= 0.5; - else if (q->bitmap_size * 1.5 < avg_bitmap_size) perf_score *= 0.75; - - /* Adjust score based on handicap. Handicap is proportional to how late - in the game we learned about this path. Latecomers are allowed to run - for a bit longer until they catch up with the rest. */ - - if (q->handicap >= 4) { - - perf_score *= 4; - q->handicap -= 4; - - } else if (q->handicap) { - - perf_score *= 2; - q->handicap--; - - } - - /* Final adjustment based on input depth, under the assumption that fuzzing - deeper test cases is more likely to reveal stuff that can't be - discovered with traditional fuzzers. */ - - switch (q->depth) { - - case 0 ... 3: break; - case 4 ... 7: perf_score *= 2; break; - case 8 ... 13: perf_score *= 3; break; - case 14 ... 25: perf_score *= 4; break; - default: perf_score *= 5; - - } - - /* Make sure that we don't go over limit. */ - - if (perf_score > HAVOC_MAX_MULT * 100) perf_score = HAVOC_MAX_MULT * 100; - - return perf_score; - -} - - -/* Helper function to see if a particular change (xor_val = old ^ new) could - be a product of deterministic bit flips with the lengths and stepovers - attempted by afl-fuzz. This is used to avoid dupes in some of the - deterministic fuzzing operations that follow bit flips. We also - return 1 if xor_val is zero, which implies that the old and attempted new - values are identical and the exec would be a waste of time. */ - -static u8 could_be_bitflip(u32 xor_val) { - - u32 sh = 0; - - if (!xor_val) return 1; - - /* Shift left until first bit set. */ - - while (!(xor_val & 1)) { sh++; xor_val >>= 1; } - - /* 1-, 2-, and 4-bit patterns are OK anywhere. */ - - if (xor_val == 1 || xor_val == 3 || xor_val == 15) return 1; - - /* 8-, 16-, and 32-bit patterns are OK only if shift factor is - divisible by 8, since that's the stepover for these ops. */ - - if (sh & 7) return 0; - - if (xor_val == 0xff || xor_val == 0xffff || xor_val == 0xffffffff) - return 1; - - return 0; - -} - - -/* Helper function to see if a particular value is reachable through - arithmetic operations. Used for similar purposes. */ - -static u8 could_be_arith(u32 old_val, u32 new_val, u8 blen) { - - u32 i, ov = 0, nv = 0, diffs = 0; - - if (old_val == new_val) return 1; - - /* See if one-byte adjustments to any byte could produce this result. */ - - for (i = 0; i < blen; i++) { - - u8 a = old_val >> (8 * i), - b = new_val >> (8 * i); - - if (a != b) { diffs++; ov = a; nv = b; } - - } - - /* If only one byte differs and the values are within range, return 1. */ - - if (diffs == 1) { - - if ((u8)(ov - nv) <= ARITH_MAX || - (u8)(nv - ov) <= ARITH_MAX) return 1; - - } - - if (blen == 1) return 0; - - /* See if two-byte adjustments to any byte would produce this result. */ - - diffs = 0; - - for (i = 0; i < blen / 2; i++) { - - u16 a = old_val >> (16 * i), - b = new_val >> (16 * i); - - if (a != b) { diffs++; ov = a; nv = b; } - - } - - /* If only one word differs and the values are within range, return 1. */ - - if (diffs == 1) { - - if ((u16)(ov - nv) <= ARITH_MAX || - (u16)(nv - ov) <= ARITH_MAX) return 1; - - ov = SWAP16(ov); nv = SWAP16(nv); - - if ((u16)(ov - nv) <= ARITH_MAX || - (u16)(nv - ov) <= ARITH_MAX) return 1; - - } - - /* Finally, let's do the same thing for dwords. */ - - if (blen == 4) { - - if ((u32)(old_val - new_val) <= ARITH_MAX || - (u32)(new_val - old_val) <= ARITH_MAX) return 1; - - new_val = SWAP32(new_val); - old_val = SWAP32(old_val); - - if ((u32)(old_val - new_val) <= ARITH_MAX || - (u32)(new_val - old_val) <= ARITH_MAX) return 1; - - } - - return 0; - -} - - -/* Last but not least, a similar helper to see if insertion of an - interesting integer is redundant given the insertions done for - shorter blen. The last param (check_le) is set if the caller - already executed LE insertion for current blen and wants to see - if BE variant passed in new_val is unique. */ - -static u8 could_be_interest(u32 old_val, u32 new_val, u8 blen, u8 check_le) { - - u32 i, j; - - if (old_val == new_val) return 1; - - /* See if one-byte insertions from interesting_8 over old_val could - produce new_val. */ - - for (i = 0; i < blen; i++) { - - for (j = 0; j < sizeof(interesting_8); j++) { - - u32 tval = (old_val & ~(0xff << (i * 8))) | - (((u8)interesting_8[j]) << (i * 8)); - - if (new_val == tval) return 1; - - } - - } - - /* Bail out unless we're also asked to examine two-byte LE insertions - as a preparation for BE attempts. */ - - if (blen == 2 && !check_le) return 0; - - /* See if two-byte insertions over old_val could give us new_val. */ - - for (i = 0; i < blen - 1; i++) { - - for (j = 0; j < sizeof(interesting_16) / 2; j++) { - - u32 tval = (old_val & ~(0xffff << (i * 8))) | - (((u16)interesting_16[j]) << (i * 8)); - - if (new_val == tval) return 1; - - /* Continue here only if blen > 2. */ - - if (blen > 2) { - - tval = (old_val & ~(0xffff << (i * 8))) | - (SWAP16(interesting_16[j]) << (i * 8)); - - if (new_val == tval) return 1; - - } - - } - - } - - if (blen == 4 && check_le) { - - /* See if four-byte insertions could produce the same result - (LE only). */ - - for (j = 0; j < sizeof(interesting_32) / 4; j++) - if (new_val == (u32)interesting_32[j]) return 1; - - } - - return 0; - -} - - -/* Take the current entry from the queue, fuzz it for a while. This - function is a tad too long... returns 0 if fuzzed successfully, 1 if - skipped or bailed out. */ - -static u8 fuzz_one(char** argv) { - - s32 len, fd, temp_len, i, j; - u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; - u64 havoc_queued, orig_hit_cnt, new_hit_cnt; - u32 splice_cycle = 0, perf_score = 100, orig_perf, prev_cksum, eff_cnt = 1; - - u8 ret_val = 1, doing_det = 0; - - u8 a_collect[MAX_AUTO_EXTRA]; - u32 a_len = 0; - -#ifdef IGNORE_FINDS - - /* In IGNORE_FINDS mode, skip any entries that weren't in the - initial data set. */ - - if (queue_cur->depth > 1) return 1; - -#else - - if (pending_favored) { - - /* If we have any favored, non-fuzzed new arrivals in the queue, - possibly skip to them at the expense of already-fuzzed or non-favored - cases. */ - - if ((queue_cur->was_fuzzed || !queue_cur->favored) && - UR(100) < SKIP_TO_NEW_PROB) return 1; - - } else if (!dumb_mode && !queue_cur->favored && queued_paths > 10) { - - /* Otherwise, still possibly skip non-favored cases, albeit less often. - The odds of skipping stuff are higher for already-fuzzed inputs and - lower for never-fuzzed entries. */ - - if (queue_cycle > 1 && !queue_cur->was_fuzzed) { - - if (UR(100) < SKIP_NFAV_NEW_PROB) return 1; - - } else { - - if (UR(100) < SKIP_NFAV_OLD_PROB) return 1; - - } - - } - -#endif /* ^IGNORE_FINDS */ - - if (not_on_tty) { - ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...", - current_entry, queued_paths, unique_crashes); - fflush(stdout); - } - - /* Map the test case into memory. */ - - fd = open(queue_cur->fname, O_RDONLY); - - if (fd < 0) PFATAL("Unable to open '%s'", queue_cur->fname); - - len = queue_cur->len; - - orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - - if (orig_in == MAP_FAILED) PFATAL("Unable to mmap '%s'", queue_cur->fname); - - close(fd); - - /* We could mmap() out_buf as MAP_PRIVATE, but we end up clobbering every - single byte anyway, so it wouldn't give us any performance or memory usage - benefits. */ - - out_buf = ck_alloc_nozero(len); - - subseq_tmouts = 0; - - cur_depth = queue_cur->depth; - - /******************************************* - * CALIBRATION (only if failed earlier on) * - *******************************************/ - - if (queue_cur->cal_failed) { - - u8 res = FAULT_TMOUT; - - if (queue_cur->cal_failed < CAL_CHANCES) { - - res = calibrate_case(argv, queue_cur, in_buf, queue_cycle - 1, 0); - - if (res == FAULT_ERROR) - FATAL("Unable to execute target application"); - - } - - if (stop_soon || res != crash_mode) { - cur_skipped_paths++; - goto abandon_entry; - } - - } - - /************ - * TRIMMING * - ************/ - - if (!dumb_mode && !queue_cur->trim_done) { - - u8 res = trim_case(argv, queue_cur, in_buf); - - if (res == FAULT_ERROR) - FATAL("Unable to execute target application"); - - if (stop_soon) { - cur_skipped_paths++; - goto abandon_entry; - } - - /* Don't retry trimming, even if it failed. */ - - queue_cur->trim_done = 1; - - if (len != queue_cur->len) len = queue_cur->len; - - } - - memcpy(out_buf, in_buf, len); - - /********************* - * PERFORMANCE SCORE * - *********************/ - - orig_perf = perf_score = calculate_score(queue_cur); - - /* Skip right away if -d is given, if we have done deterministic fuzzing on - this entry ourselves (was_fuzzed), or if it has gone through deterministic - testing in earlier, resumed runs (passed_det). */ - - if (skip_deterministic || queue_cur->was_fuzzed || queue_cur->passed_det) - goto havoc_stage; - - /* Skip deterministic fuzzing if exec path checksum puts this out of scope - for this master instance. */ - - if (master_max && (queue_cur->exec_cksum % master_max) != master_id - 1) - goto havoc_stage; - - doing_det = 1; - - /********************************************* - * SIMPLE BITFLIP (+dictionary construction) * - *********************************************/ - -#define FLIP_BIT(_ar, _b) do { \ - u8* _arf = (u8*)(_ar); \ - u32 _bf = (_b); \ - _arf[(_bf) >> 3] ^= (128 >> ((_bf) & 7)); \ - } while (0) - - /* Single walking bit. */ - - stage_short = "flip1"; - stage_max = len << 3; - stage_name = "bitflip 1/1"; - - stage_val_type = STAGE_VAL_NONE; - - orig_hit_cnt = queued_paths + unique_crashes; - - prev_cksum = queue_cur->exec_cksum; - - for (stage_cur = 0; stage_cur < stage_max; stage_cur++) { - - stage_cur_byte = stage_cur >> 3; - - FLIP_BIT(out_buf, stage_cur); - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - - FLIP_BIT(out_buf, stage_cur); - - /* While flipping the least significant bit in every byte, pull of an extra - trick to detect possible syntax tokens. In essence, the idea is that if - you have a binary blob like this: - - xxxxxxxxIHDRxxxxxxxx - - ...and changing the leading and trailing bytes causes variable or no - changes in program flow, but touching any character in the "IHDR" string - always produces the same, distinctive path, it's highly likely that - "IHDR" is an atomically-checked magic value of special significance to - the fuzzed format. - - We do this here, rather than as a separate stage, because it's a nice - way to keep the operation approximately "free" (i.e., no extra execs). - - Empirically, performing the check when flipping the least significant bit - is advantageous, compared to doing it at the time of more disruptive - changes, where the program flow may be affected in more violent ways. - - The caveat is that we won't generate dictionaries in the -d mode or -S - mode - but that's probably a fair trade-off. - - This won't work particularly well with paths that exhibit variable - behavior, but fails gracefully, so we'll carry out the checks anyway. - - */ - - if (!dumb_mode && (stage_cur & 7) == 7) { - - u32 cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); - - if (stage_cur == stage_max - 1 && cksum == prev_cksum) { - - /* If at end of file and we are still collecting a string, grab the - final character and force output. */ - - if (a_len < MAX_AUTO_EXTRA) a_collect[a_len] = out_buf[stage_cur >> 3]; - a_len++; - - if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) - maybe_add_auto(a_collect, a_len); - - } else if (cksum != prev_cksum) { - - /* Otherwise, if the checksum has changed, see if we have something - worthwhile queued up, and collect that if the answer is yes. */ - - if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) - maybe_add_auto(a_collect, a_len); - - a_len = 0; - prev_cksum = cksum; - - } - - /* Continue collecting string, but only if the bit flip actually made - any difference - we don't want no-op tokens. */ - - if (cksum != queue_cur->exec_cksum) { - - if (a_len < MAX_AUTO_EXTRA) a_collect[a_len] = out_buf[stage_cur >> 3]; - a_len++; - - } - - } - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_FLIP1] += stage_max; - - /* Two walking bits. */ - - stage_name = "bitflip 2/1"; - stage_short = "flip2"; - stage_max = (len << 3) - 1; - - orig_hit_cnt = new_hit_cnt; - - for (stage_cur = 0; stage_cur < stage_max; stage_cur++) { - - stage_cur_byte = stage_cur >> 3; - - FLIP_BIT(out_buf, stage_cur); - FLIP_BIT(out_buf, stage_cur + 1); - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - - FLIP_BIT(out_buf, stage_cur); - FLIP_BIT(out_buf, stage_cur + 1); - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_FLIP2] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_FLIP2] += stage_max; - - /* Four walking bits. */ - - stage_name = "bitflip 4/1"; - stage_short = "flip4"; - stage_max = (len << 3) - 3; - - orig_hit_cnt = new_hit_cnt; - - for (stage_cur = 0; stage_cur < stage_max; stage_cur++) { - - stage_cur_byte = stage_cur >> 3; - - FLIP_BIT(out_buf, stage_cur); - FLIP_BIT(out_buf, stage_cur + 1); - FLIP_BIT(out_buf, stage_cur + 2); - FLIP_BIT(out_buf, stage_cur + 3); - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - - FLIP_BIT(out_buf, stage_cur); - FLIP_BIT(out_buf, stage_cur + 1); - FLIP_BIT(out_buf, stage_cur + 2); - FLIP_BIT(out_buf, stage_cur + 3); - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_FLIP4] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_FLIP4] += stage_max; - - /* Effector map setup. These macros calculate: - - EFF_APOS - position of a particular file offset in the map. - EFF_ALEN - length of a map with a particular number of bytes. - EFF_SPAN_ALEN - map span for a sequence of bytes. - - */ - -#define EFF_APOS(_p) ((_p) >> EFF_MAP_SCALE2) -#define EFF_REM(_x) ((_x) & ((1 << EFF_MAP_SCALE2) - 1)) -#define EFF_ALEN(_l) (EFF_APOS(_l) + !!EFF_REM(_l)) -#define EFF_SPAN_ALEN(_p, _l) (EFF_APOS((_p) + (_l) - 1) - EFF_APOS(_p) + 1) - - /* Initialize effector map for the next step (see comments below). Always - flag first and last byte as doing something. */ - - eff_map = ck_alloc(EFF_ALEN(len)); - eff_map[0] = 1; - - if (EFF_APOS(len - 1) != 0) { - eff_map[EFF_APOS(len - 1)] = 1; - eff_cnt++; - } - - /* Walking byte. */ - - stage_name = "bitflip 8/8"; - stage_short = "flip8"; - stage_max = len; - - orig_hit_cnt = new_hit_cnt; - - for (stage_cur = 0; stage_cur < stage_max; stage_cur++) { - - stage_cur_byte = stage_cur; - - out_buf[stage_cur] ^= 0xFF; - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - - /* We also use this stage to pull off a simple trick: we identify - bytes that seem to have no effect on the current execution path - even when fully flipped - and we skip them during more expensive - deterministic stages, such as arithmetics or known ints. */ - - if (!eff_map[EFF_APOS(stage_cur)]) { - - u32 cksum; - - /* If in dumb mode or if the file is very short, just flag everything - without wasting time on checksums. */ - - if (!dumb_mode && len >= EFF_MIN_LEN) - cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); - else - cksum = ~queue_cur->exec_cksum; - - if (cksum != queue_cur->exec_cksum) { - eff_map[EFF_APOS(stage_cur)] = 1; - eff_cnt++; - } - - } - - out_buf[stage_cur] ^= 0xFF; - - } - - /* If the effector map is more than EFF_MAX_PERC dense, just flag the - whole thing as worth fuzzing, since we wouldn't be saving much time - anyway. */ - - if (eff_cnt != EFF_ALEN(len) && - eff_cnt * 100 / EFF_ALEN(len) > EFF_MAX_PERC) { - - memset(eff_map, 1, EFF_ALEN(len)); - - blocks_eff_select += EFF_ALEN(len); - - } else { - - blocks_eff_select += eff_cnt; - - } - - blocks_eff_total += EFF_ALEN(len); - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_FLIP8] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_FLIP8] += stage_max; - - /* Two walking bytes. */ - - if (len < 2) goto skip_bitflip; - - stage_name = "bitflip 16/8"; - stage_short = "flip16"; - stage_cur = 0; - stage_max = len - 1; - - orig_hit_cnt = new_hit_cnt; - - for (i = 0; i < len - 1; i++) { - - /* Let's consult the effector map... */ - - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) { - stage_max--; - continue; - } - - stage_cur_byte = i; - - *(u16*)(out_buf + i) ^= 0xFFFF; - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - *(u16*)(out_buf + i) ^= 0xFFFF; - - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_FLIP16] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_FLIP16] += stage_max; - - if (len < 4) goto skip_bitflip; - - /* Four walking bytes. */ - - stage_name = "bitflip 32/8"; - stage_short = "flip32"; - stage_cur = 0; - stage_max = len - 3; - - orig_hit_cnt = new_hit_cnt; - - for (i = 0; i < len - 3; i++) { - - /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] && - !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) { - stage_max--; - continue; - } - - stage_cur_byte = i; - - *(u32*)(out_buf + i) ^= 0xFFFFFFFF; - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - *(u32*)(out_buf + i) ^= 0xFFFFFFFF; - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_FLIP32] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_FLIP32] += stage_max; - -skip_bitflip: - - if (no_arith) goto skip_arith; - - /********************** - * ARITHMETIC INC/DEC * - **********************/ - - /* 8-bit arithmetics. */ - - stage_name = "arith 8/8"; - stage_short = "arith8"; - stage_cur = 0; - stage_max = 2 * len * ARITH_MAX; - - stage_val_type = STAGE_VAL_LE; - - orig_hit_cnt = new_hit_cnt; - - for (i = 0; i < len; i++) { - - u8 orig = out_buf[i]; - - /* Let's consult the effector map... */ - - if (!eff_map[EFF_APOS(i)]) { - stage_max -= 2 * ARITH_MAX; - continue; - } - - stage_cur_byte = i; - - for (j = 1; j <= ARITH_MAX; j++) { - - u8 r = orig ^ (orig + j); - - /* Do arithmetic operations only if the result couldn't be a product - of a bitflip. */ - - if (!could_be_bitflip(r)) { - - stage_cur_val = j; - out_buf[i] = orig + j; - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - r = orig ^ (orig - j); - - if (!could_be_bitflip(r)) { - - stage_cur_val = -j; - out_buf[i] = orig - j; - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - out_buf[i] = orig; - - } - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_ARITH8] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_ARITH8] += stage_max; - - /* 16-bit arithmetics, both endians. */ - - if (len < 2) goto skip_arith; - - stage_name = "arith 16/8"; - stage_short = "arith16"; - stage_cur = 0; - stage_max = 4 * (len - 1) * ARITH_MAX; - - orig_hit_cnt = new_hit_cnt; - - for (i = 0; i < len - 1; i++) { - - u16 orig = *(u16*)(out_buf + i); - - /* Let's consult the effector map... */ - - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) { - stage_max -= 4 * ARITH_MAX; - continue; - } - - stage_cur_byte = i; - - for (j = 1; j <= ARITH_MAX; j++) { - - u16 r1 = orig ^ (orig + j), - r2 = orig ^ (orig - j), - r3 = orig ^ SWAP16(SWAP16(orig) + j), - r4 = orig ^ SWAP16(SWAP16(orig) - j); - - /* Try little endian addition and subtraction first. Do it only - if the operation would affect more than one byte (hence the - & 0xff overflow checks) and if it couldn't be a product of - a bitflip. */ - - stage_val_type = STAGE_VAL_LE; - - if ((orig & 0xff) + j > 0xff && !could_be_bitflip(r1)) { - - stage_cur_val = j; - *(u16*)(out_buf + i) = orig + j; - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - if ((orig & 0xff) < j && !could_be_bitflip(r2)) { - - stage_cur_val = -j; - *(u16*)(out_buf + i) = orig - j; - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - /* Big endian comes next. Same deal. */ - - stage_val_type = STAGE_VAL_BE; - - - if ((orig >> 8) + j > 0xff && !could_be_bitflip(r3)) { - - stage_cur_val = j; - *(u16*)(out_buf + i) = SWAP16(SWAP16(orig) + j); - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - if ((orig >> 8) < j && !could_be_bitflip(r4)) { - - stage_cur_val = -j; - *(u16*)(out_buf + i) = SWAP16(SWAP16(orig) - j); - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - *(u16*)(out_buf + i) = orig; - - } - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_ARITH16] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_ARITH16] += stage_max; - - /* 32-bit arithmetics, both endians. */ - - if (len < 4) goto skip_arith; - - stage_name = "arith 32/8"; - stage_short = "arith32"; - stage_cur = 0; - stage_max = 4 * (len - 3) * ARITH_MAX; - - orig_hit_cnt = new_hit_cnt; - - for (i = 0; i < len - 3; i++) { - - u32 orig = *(u32*)(out_buf + i); - - /* Let's consult the effector map... */ - - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] && - !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) { - stage_max -= 4 * ARITH_MAX; - continue; - } - - stage_cur_byte = i; - - for (j = 1; j <= ARITH_MAX; j++) { - - u32 r1 = orig ^ (orig + j), - r2 = orig ^ (orig - j), - r3 = orig ^ SWAP32(SWAP32(orig) + j), - r4 = orig ^ SWAP32(SWAP32(orig) - j); - - /* Little endian first. Same deal as with 16-bit: we only want to - try if the operation would have effect on more than two bytes. */ - - stage_val_type = STAGE_VAL_LE; - - if ((orig & 0xffff) + j > 0xffff && !could_be_bitflip(r1)) { - - stage_cur_val = j; - *(u32*)(out_buf + i) = orig + j; - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - if ((orig & 0xffff) < j && !could_be_bitflip(r2)) { - - stage_cur_val = -j; - *(u32*)(out_buf + i) = orig - j; - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - /* Big endian next. */ - - stage_val_type = STAGE_VAL_BE; - - if ((SWAP32(orig) & 0xffff) + j > 0xffff && !could_be_bitflip(r3)) { - - stage_cur_val = j; - *(u32*)(out_buf + i) = SWAP32(SWAP32(orig) + j); - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - if ((SWAP32(orig) & 0xffff) < j && !could_be_bitflip(r4)) { - - stage_cur_val = -j; - *(u32*)(out_buf + i) = SWAP32(SWAP32(orig) - j); - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - *(u32*)(out_buf + i) = orig; - - } - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_ARITH32] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_ARITH32] += stage_max; - -skip_arith: - - /********************** - * INTERESTING VALUES * - **********************/ - - stage_name = "interest 8/8"; - stage_short = "int8"; - stage_cur = 0; - stage_max = len * sizeof(interesting_8); - - stage_val_type = STAGE_VAL_LE; - - orig_hit_cnt = new_hit_cnt; - - /* Setting 8-bit integers. */ - - for (i = 0; i < len; i++) { - - u8 orig = out_buf[i]; - - /* Let's consult the effector map... */ - - if (!eff_map[EFF_APOS(i)]) { - stage_max -= sizeof(interesting_8); - continue; - } - - stage_cur_byte = i; - - for (j = 0; j < sizeof(interesting_8); j++) { - - /* Skip if the value could be a product of bitflips or arithmetics. */ - - if (could_be_bitflip(orig ^ (u8)interesting_8[j]) || - could_be_arith(orig, (u8)interesting_8[j], 1)) { - stage_max--; - continue; - } - - stage_cur_val = interesting_8[j]; - out_buf[i] = interesting_8[j]; - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - - out_buf[i] = orig; - stage_cur++; - - } - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_INTEREST8] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_INTEREST8] += stage_max; - - /* Setting 16-bit integers, both endians. */ - - if (no_arith || len < 2) goto skip_interest; - - stage_name = "interest 16/8"; - stage_short = "int16"; - stage_cur = 0; - stage_max = 2 * (len - 1) * (sizeof(interesting_16) >> 1); - - orig_hit_cnt = new_hit_cnt; - - for (i = 0; i < len - 1; i++) { - - u16 orig = *(u16*)(out_buf + i); - - /* Let's consult the effector map... */ - - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) { - stage_max -= sizeof(interesting_16); - continue; - } - - stage_cur_byte = i; - - for (j = 0; j < sizeof(interesting_16) / 2; j++) { - - stage_cur_val = interesting_16[j]; - - /* Skip if this could be a product of a bitflip, arithmetics, - or single-byte interesting value insertion. */ - - if (!could_be_bitflip(orig ^ (u16)interesting_16[j]) && - !could_be_arith(orig, (u16)interesting_16[j], 2) && - !could_be_interest(orig, (u16)interesting_16[j], 2, 0)) { - - stage_val_type = STAGE_VAL_LE; - - *(u16*)(out_buf + i) = interesting_16[j]; - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - if ((u16)interesting_16[j] != SWAP16(interesting_16[j]) && - !could_be_bitflip(orig ^ SWAP16(interesting_16[j])) && - !could_be_arith(orig, SWAP16(interesting_16[j]), 2) && - !could_be_interest(orig, SWAP16(interesting_16[j]), 2, 1)) { - - stage_val_type = STAGE_VAL_BE; - - *(u16*)(out_buf + i) = SWAP16(interesting_16[j]); - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - } - - *(u16*)(out_buf + i) = orig; - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_INTEREST16] += stage_max; - - if (len < 4) goto skip_interest; - - /* Setting 32-bit integers, both endians. */ - - stage_name = "interest 32/8"; - stage_short = "int32"; - stage_cur = 0; - stage_max = 2 * (len - 3) * (sizeof(interesting_32) >> 2); - - orig_hit_cnt = new_hit_cnt; - - for (i = 0; i < len - 3; i++) { - - u32 orig = *(u32*)(out_buf + i); - - /* Let's consult the effector map... */ - - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] && - !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) { - stage_max -= sizeof(interesting_32) >> 1; - continue; - } - - stage_cur_byte = i; - - for (j = 0; j < sizeof(interesting_32) / 4; j++) { - - stage_cur_val = interesting_32[j]; - - /* Skip if this could be a product of a bitflip, arithmetics, - or word interesting value insertion. */ - - if (!could_be_bitflip(orig ^ (u32)interesting_32[j]) && - !could_be_arith(orig, interesting_32[j], 4) && - !could_be_interest(orig, interesting_32[j], 4, 0)) { - - stage_val_type = STAGE_VAL_LE; - - *(u32*)(out_buf + i) = interesting_32[j]; - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - if ((u32)interesting_32[j] != SWAP32(interesting_32[j]) && - !could_be_bitflip(orig ^ SWAP32(interesting_32[j])) && - !could_be_arith(orig, SWAP32(interesting_32[j]), 4) && - !could_be_interest(orig, SWAP32(interesting_32[j]), 4, 1)) { - - stage_val_type = STAGE_VAL_BE; - - *(u32*)(out_buf + i) = SWAP32(interesting_32[j]); - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - stage_cur++; - - } else stage_max--; - - } - - *(u32*)(out_buf + i) = orig; - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_INTEREST32] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_INTEREST32] += stage_max; - -skip_interest: - - /******************** - * DICTIONARY STUFF * - ********************/ - - if (!extras_cnt) goto skip_user_extras; - - /* Overwrite with user-supplied extras. */ - - stage_name = "user extras (over)"; - stage_short = "ext_UO"; - stage_cur = 0; - stage_max = extras_cnt * len; - - stage_val_type = STAGE_VAL_NONE; - - orig_hit_cnt = new_hit_cnt; - - for (i = 0; i < len; i++) { - - u32 last_len = 0; - - stage_cur_byte = i; - - /* Extras are sorted by size, from smallest to largest. This means - that we don't have to worry about restoring the buffer in - between writes at a particular offset determined by the outer - loop. */ - - for (j = 0; j < extras_cnt; j++) { - - /* Skip extras probabilistically if extras_cnt > MAX_DET_EXTRAS. Also - skip them if there's no room to insert the payload, if the token - is redundant, or if its entire span has no bytes set in the effector - map. */ - - if ((extras_cnt > MAX_DET_EXTRAS && UR(extras_cnt) >= MAX_DET_EXTRAS) || - extras[j].len > len - i || - !memcmp(extras[j].data, out_buf + i, extras[j].len) || - !memchr(eff_map + EFF_APOS(i), 1, EFF_SPAN_ALEN(i, extras[j].len))) { - - stage_max--; - continue; - - } - - last_len = extras[j].len; - memcpy(out_buf + i, extras[j].data, last_len); - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - - stage_cur++; - - } - - /* Restore all the clobbered memory. */ - memcpy(out_buf + i, in_buf + i, last_len); - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_EXTRAS_UO] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_EXTRAS_UO] += stage_max; - - /* Insertion of user-supplied extras. */ - - stage_name = "user extras (insert)"; - stage_short = "ext_UI"; - stage_cur = 0; - stage_max = extras_cnt * len; - - orig_hit_cnt = new_hit_cnt; - - ex_tmp = ck_alloc(len + MAX_DICT_FILE); - - for (i = 0; i <= len; i++) { - - stage_cur_byte = i; - - for (j = 0; j < extras_cnt; j++) { - - if (len + extras[j].len > MAX_FILE) { - stage_max--; - continue; - } - - /* Insert token */ - memcpy(ex_tmp + i, extras[j].data, extras[j].len); - - /* Copy tail */ - memcpy(ex_tmp + i + extras[j].len, out_buf + i, len - i); - - if (common_fuzz_stuff(argv, ex_tmp, len + extras[j].len)) { - ck_free(ex_tmp); - goto abandon_entry; - } - - stage_cur++; - - } - - /* Copy head */ - ex_tmp[i] = out_buf[i]; - - } - - ck_free(ex_tmp); - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_EXTRAS_UI] += stage_max; - -skip_user_extras: - - if (!a_extras_cnt) goto skip_extras; - - stage_name = "auto extras (over)"; - stage_short = "ext_AO"; - stage_cur = 0; - stage_max = MIN(a_extras_cnt, USE_AUTO_EXTRAS) * len; - - stage_val_type = STAGE_VAL_NONE; - - orig_hit_cnt = new_hit_cnt; - - for (i = 0; i < len; i++) { - - u32 last_len = 0; - - stage_cur_byte = i; - - for (j = 0; j < MIN(a_extras_cnt, USE_AUTO_EXTRAS); j++) { - - /* See the comment in the earlier code; extras are sorted by size. */ - - if (a_extras[j].len > len - i || - !memcmp(a_extras[j].data, out_buf + i, a_extras[j].len) || - !memchr(eff_map + EFF_APOS(i), 1, EFF_SPAN_ALEN(i, a_extras[j].len))) { - - stage_max--; - continue; - - } - - last_len = a_extras[j].len; - memcpy(out_buf + i, a_extras[j].data, last_len); - - if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; - - stage_cur++; - - } - - /* Restore all the clobbered memory. */ - memcpy(out_buf + i, in_buf + i, last_len); - - } - - new_hit_cnt = queued_paths + unique_crashes; - - stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_EXTRAS_AO] += stage_max; - -skip_extras: - - /* If we made this to here without jumping to havoc_stage or abandon_entry, - we're properly done with deterministic steps and can mark it as such - in the .state/ directory. */ - - if (!queue_cur->passed_det) mark_as_det_done(queue_cur); - - /**************** - * RANDOM HAVOC * - ****************/ - -havoc_stage: - - stage_cur_byte = -1; - - /* The havoc stage mutation code is also invoked when splicing files; if the - splice_cycle variable is set, generate different descriptions and such. */ - - if (!splice_cycle) { - - stage_name = "havoc"; - stage_short = "havoc"; - stage_max = (doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) * - perf_score / havoc_div / 100; - - } else { - - static u8 tmp[32]; - - perf_score = orig_perf; - - sprintf(tmp, "splice %u", splice_cycle); - stage_name = tmp; - stage_short = "splice"; - stage_max = SPLICE_HAVOC * perf_score / havoc_div / 100; - - } - - if (stage_max < HAVOC_MIN) stage_max = HAVOC_MIN; - - temp_len = len; - - orig_hit_cnt = queued_paths + unique_crashes; - - havoc_queued = queued_paths; - - /* We essentially just do several thousand runs (depending on perf_score) - where we take the input file and make random stacked tweaks. */ - - for (stage_cur = 0; stage_cur < stage_max; stage_cur++) { - - u32 use_stacking = 1 << (1 + UR(HAVOC_STACK_POW2)); - - stage_cur_val = use_stacking; - - for (i = 0; i < use_stacking; i++) { - - switch (UR(15 + ((extras_cnt + a_extras_cnt) ? 2 : 0))) { - - case 0: - - /* Flip a single bit somewhere. Spooky! */ - - FLIP_BIT(out_buf, UR(temp_len << 3)); - break; - - case 1: - - /* Set byte to interesting value. */ - - out_buf[UR(temp_len)] = interesting_8[UR(sizeof(interesting_8))]; - break; - - case 2: - - /* Set word to interesting value, randomly choosing endian. */ - - if (temp_len < 2) break; - - if (UR(2)) { - - *(u16*)(out_buf + UR(temp_len - 1)) = - interesting_16[UR(sizeof(interesting_16) >> 1)]; - - } else { - - *(u16*)(out_buf + UR(temp_len - 1)) = SWAP16( - interesting_16[UR(sizeof(interesting_16) >> 1)]); - - } - - break; - - case 3: - - /* Set dword to interesting value, randomly choosing endian. */ - - if (temp_len < 4) break; - - if (UR(2)) { - - *(u32*)(out_buf + UR(temp_len - 3)) = - interesting_32[UR(sizeof(interesting_32) >> 2)]; - - } else { - - *(u32*)(out_buf + UR(temp_len - 3)) = SWAP32( - interesting_32[UR(sizeof(interesting_32) >> 2)]); - - } - - break; - - case 4: - - /* Randomly subtract from byte. */ - - out_buf[UR(temp_len)] -= 1 + UR(ARITH_MAX); - break; - - case 5: - - /* Randomly add to byte. */ - - out_buf[UR(temp_len)] += 1 + UR(ARITH_MAX); - break; - - case 6: - - /* Randomly subtract from word, random endian. */ - - if (temp_len < 2) break; - - if (UR(2)) { - - u32 pos = UR(temp_len - 1); - - *(u16*)(out_buf + pos) -= 1 + UR(ARITH_MAX); - - } else { - - u32 pos = UR(temp_len - 1); - u16 num = 1 + UR(ARITH_MAX); - - *(u16*)(out_buf + pos) = - SWAP16(SWAP16(*(u16*)(out_buf + pos)) - num); - - } - - break; - - case 7: - - /* Randomly add to word, random endian. */ - - if (temp_len < 2) break; - - if (UR(2)) { - - u32 pos = UR(temp_len - 1); - - *(u16*)(out_buf + pos) += 1 + UR(ARITH_MAX); - - } else { - - u32 pos = UR(temp_len - 1); - u16 num = 1 + UR(ARITH_MAX); - - *(u16*)(out_buf + pos) = - SWAP16(SWAP16(*(u16*)(out_buf + pos)) + num); - - } - - break; - - case 8: - - /* Randomly subtract from dword, random endian. */ - - if (temp_len < 4) break; - - if (UR(2)) { - - u32 pos = UR(temp_len - 3); - - *(u32*)(out_buf + pos) -= 1 + UR(ARITH_MAX); - - } else { - - u32 pos = UR(temp_len - 3); - u32 num = 1 + UR(ARITH_MAX); - - *(u32*)(out_buf + pos) = - SWAP32(SWAP32(*(u32*)(out_buf + pos)) - num); - - } - - break; - - case 9: - - /* Randomly add to dword, random endian. */ - - if (temp_len < 4) break; - - if (UR(2)) { - - u32 pos = UR(temp_len - 3); - - *(u32*)(out_buf + pos) += 1 + UR(ARITH_MAX); - - } else { - - u32 pos = UR(temp_len - 3); - u32 num = 1 + UR(ARITH_MAX); - - *(u32*)(out_buf + pos) = - SWAP32(SWAP32(*(u32*)(out_buf + pos)) + num); - - } - - break; - - case 10: - - /* Just set a random byte to a random value. Because, - why not. We use XOR with 1-255 to eliminate the - possibility of a no-op. */ - - out_buf[UR(temp_len)] ^= 1 + UR(255); - break; - - case 11 ... 12: { - - /* Delete bytes. We're making this a bit more likely - than insertion (the next option) in hopes of keeping - files reasonably small. */ - - u32 del_from, del_len; - - if (temp_len < 2) break; - - /* Don't delete too much. */ - - del_len = choose_block_len(temp_len - 1); - - del_from = UR(temp_len - del_len + 1); - - memmove(out_buf + del_from, out_buf + del_from + del_len, - temp_len - del_from - del_len); - - temp_len -= del_len; - - break; - - } - - case 13: - - if (temp_len + HAVOC_BLK_XL < MAX_FILE) { - - /* Clone bytes (75%) or insert a block of constant bytes (25%). */ - - u8 actually_clone = UR(4); - u32 clone_from, clone_to, clone_len; - u8* new_buf; - - if (actually_clone) { - - clone_len = choose_block_len(temp_len); - clone_from = UR(temp_len - clone_len + 1); - - } else { - - clone_len = choose_block_len(HAVOC_BLK_XL); - clone_from = 0; - - } - - clone_to = UR(temp_len); - - new_buf = ck_alloc_nozero(temp_len + clone_len); - - /* Head */ - - memcpy(new_buf, out_buf, clone_to); - - /* Inserted part */ - - if (actually_clone) - memcpy(new_buf + clone_to, out_buf + clone_from, clone_len); - else - memset(new_buf + clone_to, - UR(2) ? UR(256) : out_buf[UR(temp_len)], clone_len); - - /* Tail */ - memcpy(new_buf + clone_to + clone_len, out_buf + clone_to, - temp_len - clone_to); - - ck_free(out_buf); - out_buf = new_buf; - temp_len += clone_len; - - } - - break; - - case 14: { - - /* Overwrite bytes with a randomly selected chunk (75%) or fixed - bytes (25%). */ - - u32 copy_from, copy_to, copy_len; - - if (temp_len < 2) break; - - copy_len = choose_block_len(temp_len - 1); - - copy_from = UR(temp_len - copy_len + 1); - copy_to = UR(temp_len - copy_len + 1); - - if (UR(4)) { - - if (copy_from != copy_to) - memmove(out_buf + copy_to, out_buf + copy_from, copy_len); - - } else memset(out_buf + copy_to, - UR(2) ? UR(256) : out_buf[UR(temp_len)], copy_len); - - break; - - } - - /* Values 15 and 16 can be selected only if there are any extras - present in the dictionaries. */ - - case 15: { - - /* Overwrite bytes with an extra. */ - - if (!extras_cnt || (a_extras_cnt && UR(2))) { - - /* No user-specified extras or odds in our favor. Let's use an - auto-detected one. */ - - u32 use_extra = UR(a_extras_cnt); - u32 extra_len = a_extras[use_extra].len; - u32 insert_at; - - if (extra_len > temp_len) break; - - insert_at = UR(temp_len - extra_len + 1); - memcpy(out_buf + insert_at, a_extras[use_extra].data, extra_len); - - } else { - - /* No auto extras or odds in our favor. Use the dictionary. */ - - u32 use_extra = UR(extras_cnt); - u32 extra_len = extras[use_extra].len; - u32 insert_at; - - if (extra_len > temp_len) break; - - insert_at = UR(temp_len - extra_len + 1); - memcpy(out_buf + insert_at, extras[use_extra].data, extra_len); - - } - - break; - - } - - case 16: { - - u32 use_extra, extra_len, insert_at = UR(temp_len + 1); - u8* new_buf; - - /* Insert an extra. Do the same dice-rolling stuff as for the - previous case. */ - - if (!extras_cnt || (a_extras_cnt && UR(2))) { - - use_extra = UR(a_extras_cnt); - extra_len = a_extras[use_extra].len; - - if (temp_len + extra_len >= MAX_FILE) break; - - new_buf = ck_alloc_nozero(temp_len + extra_len); - - /* Head */ - memcpy(new_buf, out_buf, insert_at); - - /* Inserted part */ - memcpy(new_buf + insert_at, a_extras[use_extra].data, extra_len); - - } else { - - use_extra = UR(extras_cnt); - extra_len = extras[use_extra].len; - - if (temp_len + extra_len >= MAX_FILE) break; - - new_buf = ck_alloc_nozero(temp_len + extra_len); - - /* Head */ - memcpy(new_buf, out_buf, insert_at); - - /* Inserted part */ - memcpy(new_buf + insert_at, extras[use_extra].data, extra_len); - - } - - /* Tail */ - memcpy(new_buf + insert_at + extra_len, out_buf + insert_at, - temp_len - insert_at); - - ck_free(out_buf); - out_buf = new_buf; - temp_len += extra_len; - - break; - - } - - } - - } - - if (common_fuzz_stuff(argv, out_buf, temp_len)) - goto abandon_entry; - - /* out_buf might have been mangled a bit, so let's restore it to its - original size and shape. */ - - if (temp_len < len) out_buf = ck_realloc(out_buf, len); - temp_len = len; - memcpy(out_buf, in_buf, len); - - /* If we're finding new stuff, let's run for a bit longer, limits - permitting. */ - - if (queued_paths != havoc_queued) { - - if (perf_score <= HAVOC_MAX_MULT * 100) { - stage_max *= 2; - perf_score *= 2; - } - - havoc_queued = queued_paths; - - } - - } - - new_hit_cnt = queued_paths + unique_crashes; - - if (!splice_cycle) { - stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_HAVOC] += stage_max; - } else { - stage_finds[STAGE_SPLICE] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_SPLICE] += stage_max; - } - -#ifndef IGNORE_FINDS - - /************ - * SPLICING * - ************/ - - /* This is a last-resort strategy triggered by a full round with no findings. - It takes the current input file, randomly selects another input, and - splices them together at some offset, then relies on the havoc - code to mutate that blob. */ - -retry_splicing: - - if (use_splicing && splice_cycle++ < SPLICE_CYCLES && - queued_paths > 1 && queue_cur->len > 1) { - - struct queue_entry* target; - u32 tid, split_at; - u8* new_buf; - s32 f_diff, l_diff; - - /* First of all, if we've modified in_buf for havoc, let's clean that - up... */ - - if (in_buf != orig_in) { - ck_free(in_buf); - in_buf = orig_in; - len = queue_cur->len; - } - - /* Pick a random queue entry and seek to it. Don't splice with yourself. */ - - do { tid = UR(queued_paths); } while (tid == current_entry); - - splicing_with = tid; - target = queue; - - while (tid >= 100) { target = target->next_100; tid -= 100; } - while (tid--) target = target->next; - - /* Make sure that the target has a reasonable length. */ - - while (target && (target->len < 2 || target == queue_cur)) { - target = target->next; - splicing_with++; - } - - if (!target) goto retry_splicing; - - /* Read the testcase into a new buffer. */ - - fd = open(target->fname, O_RDONLY); - - if (fd < 0) PFATAL("Unable to open '%s'", target->fname); - - new_buf = ck_alloc_nozero(target->len); - - ck_read(fd, new_buf, target->len, target->fname); - - close(fd); - - /* Find a suitable splicing location, somewhere between the first and - the last differing byte. Bail out if the difference is just a single - byte or so. */ - - locate_diffs(in_buf, new_buf, MIN(len, target->len), &f_diff, &l_diff); - - if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) { - ck_free(new_buf); - goto retry_splicing; - } - - /* Split somewhere between the first and last differing byte. */ - - split_at = f_diff + UR(l_diff - f_diff); - - /* Do the thing. */ - - len = target->len; - memcpy(new_buf, in_buf, split_at); - in_buf = new_buf; - - ck_free(out_buf); - out_buf = ck_alloc_nozero(len); - memcpy(out_buf, in_buf, len); - - goto havoc_stage; - - } - -#endif /* !IGNORE_FINDS */ - - ret_val = 0; - -abandon_entry: - - splicing_with = -1; - - /* Update pending_not_fuzzed count if we made it through the calibration - cycle and have not seen this entry before. */ - - if (!stop_soon && !queue_cur->cal_failed && !queue_cur->was_fuzzed) { - queue_cur->was_fuzzed = 1; - pending_not_fuzzed--; - if (queue_cur->favored) pending_favored--; - } - - munmap(orig_in, queue_cur->len); - - if (in_buf != orig_in) ck_free(in_buf); - ck_free(out_buf); - ck_free(eff_map); - - return ret_val; - -#undef FLIP_BIT - -} - - -/* Grab interesting test cases from other fuzzers. */ - -static void sync_fuzzers(char** argv) { - - DIR* sd; - struct dirent* sd_ent; - u32 sync_cnt = 0; - - sd = opendir(sync_dir); - if (!sd) PFATAL("Unable to open '%s'", sync_dir); - - stage_max = stage_cur = 0; - cur_depth = 0; - - /* Look at the entries created for every other fuzzer in the sync directory. */ - - while ((sd_ent = readdir(sd))) { - - static u8 stage_tmp[128]; - - DIR* qd; - struct dirent* qd_ent; - u8 *qd_path, *qd_synced_path; - u32 min_accept = 0, next_min_accept; - - s32 id_fd; - - /* Skip dot files and our own output directory. */ - - if (sd_ent->d_name[0] == '.' || !strcmp(sync_id, sd_ent->d_name)) continue; - - /* Skip anything that doesn't have a queue/ subdirectory. */ - - qd_path = alloc_printf("%s/%s/queue", sync_dir, sd_ent->d_name); - - if (!(qd = opendir(qd_path))) { - ck_free(qd_path); - continue; - } - - /* Retrieve the ID of the last seen test case. */ - - qd_synced_path = alloc_printf("%s/.synced/%s", out_dir, sd_ent->d_name); - - id_fd = open(qd_synced_path, O_RDWR | O_CREAT, 0600); - - if (id_fd < 0) PFATAL("Unable to create '%s'", qd_synced_path); - - if (read(id_fd, &min_accept, sizeof(u32)) > 0) - lseek(id_fd, 0, SEEK_SET); - - next_min_accept = min_accept; - - /* Show stats */ - - sprintf(stage_tmp, "sync %u", ++sync_cnt); - stage_name = stage_tmp; - stage_cur = 0; - stage_max = 0; - - /* For every file queued by this fuzzer, parse ID and see if we have looked at - it before; exec a test case if not. */ - - while ((qd_ent = readdir(qd))) { - - u8* path; - s32 fd; - struct stat st; - - if (qd_ent->d_name[0] == '.' || - sscanf(qd_ent->d_name, CASE_PREFIX "%06u", &syncing_case) != 1 || - syncing_case < min_accept) continue; - - /* OK, sounds like a new one. Let's give it a try. */ - - if (syncing_case >= next_min_accept) - next_min_accept = syncing_case + 1; - - path = alloc_printf("%s/%s", qd_path, qd_ent->d_name); - - /* Allow this to fail in case the other fuzzer is resuming or so... */ - - fd = open(path, O_RDONLY); - - if (fd < 0) { - ck_free(path); - continue; - } - - if (fstat(fd, &st)) PFATAL("fstat() failed"); - - /* Ignore zero-sized or oversized files. */ - - if (st.st_size && st.st_size <= MAX_FILE) { - - u8 fault; - u8* mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - - if (mem == MAP_FAILED) PFATAL("Unable to mmap '%s'", path); - - /* See what happens. We rely on save_if_interesting() to catch major - errors and save the test case. */ - - write_to_testcase(mem, st.st_size); - - fault = run_target(argv, exec_tmout); - - if (stop_soon) return; - - syncing_party = sd_ent->d_name; - queued_imported += save_if_interesting(argv, mem, st.st_size, fault); - syncing_party = 0; - - munmap(mem, st.st_size); - - if (!(stage_cur++ % stats_update_freq)) show_stats(); - - } - - ck_free(path); - close(fd); - - } - - ck_write(id_fd, &next_min_accept, sizeof(u32), qd_synced_path); - - close(id_fd); - closedir(qd); - ck_free(qd_path); - ck_free(qd_synced_path); - - } - - closedir(sd); - -} - - -/* Handle stop signal (Ctrl-C, etc). */ - -static void handle_stop_sig(int sig) { - - stop_soon = 1; - - if (child_pid > 0) kill(child_pid, SIGKILL); - if (forksrv_pid > 0) kill(forksrv_pid, SIGKILL); - -} - - -/* Handle skip request (SIGUSR1). */ - -static void handle_skipreq(int sig) { - - skip_requested = 1; - -} - -/* Handle timeout (SIGALRM). */ - -static void handle_timeout(int sig) { - - if (child_pid > 0) { - - child_timed_out = 1; - kill(child_pid, SIGKILL); - - } else if (child_pid == -1 && forksrv_pid > 0) { - - child_timed_out = 1; - kill(forksrv_pid, SIGKILL); - - } - -} - - -/* Do a PATH search and find target binary to see that it exists and - isn't a shell script - a common and painful mistake. We also check for - a valid ELF header and for evidence of AFL instrumentation. */ - -EXP_ST void check_binary(u8* fname) { - - u8* env_path = 0; - struct stat st; - - s32 fd; - u8* f_data; - u32 f_len = 0; - - ACTF("Validating target binary..."); - - if (strchr(fname, '/') || !(env_path = getenv("PATH"))) { - - target_path = ck_strdup(fname); - if (stat(target_path, &st) || !S_ISREG(st.st_mode) || - !(st.st_mode & 0111) || (f_len = st.st_size) < 4) - FATAL("Program '%s' not found or not executable", fname); - - } else { - - while (env_path) { - - u8 *cur_elem, *delim = strchr(env_path, ':'); - - if (delim) { - - cur_elem = ck_alloc(delim - env_path + 1); - memcpy(cur_elem, env_path, delim - env_path); - delim++; - - } else cur_elem = ck_strdup(env_path); - - env_path = delim; - - if (cur_elem[0]) - target_path = alloc_printf("%s/%s", cur_elem, fname); - else - target_path = ck_strdup(fname); - - ck_free(cur_elem); - - if (!stat(target_path, &st) && S_ISREG(st.st_mode) && - (st.st_mode & 0111) && (f_len = st.st_size) >= 4) break; - - ck_free(target_path); - target_path = 0; - - } - - if (!target_path) FATAL("Program '%s' not found or not executable", fname); - - } - - if (getenv("AFL_SKIP_BIN_CHECK")) return; - - /* Check for blatant user errors. */ - - if ((!strncmp(target_path, "/tmp/", 5) && !strchr(target_path + 5, '/')) || - (!strncmp(target_path, "/var/tmp/", 9) && !strchr(target_path + 9, '/'))) - FATAL("Please don't keep binaries in /tmp or /var/tmp"); - - fd = open(target_path, O_RDONLY); - - if (fd < 0) PFATAL("Unable to open '%s'", target_path); - - f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); - - if (f_data == MAP_FAILED) PFATAL("Unable to mmap file '%s'", target_path); - - close(fd); - - if (f_data[0] == '#' && f_data[1] == '!') { - - SAYF("\n" cLRD "[-] " cRST - "Oops, the target binary looks like a shell script. Some build systems will\n" - " sometimes generate shell stubs for dynamically linked programs; try static\n" - " library mode (./configure --disable-shared) if that's the case.\n\n" - - " Another possible cause is that you are actually trying to use a shell\n" - " wrapper around the fuzzed component. Invoking shell can slow down the\n" - " fuzzing process by a factor of 20x or more; it's best to write the wrapper\n" - " in a compiled language instead.\n"); - - FATAL("Program '%s' is a shell script", target_path); - - } - -#ifndef __APPLE__ - - if (f_data[0] != 0x7f || memcmp(f_data + 1, "ELF", 3)) - FATAL("Program '%s' is not an ELF binary", target_path); - -#else - - if (f_data[0] != 0xCF || f_data[1] != 0xFA || f_data[2] != 0xED) - FATAL("Program '%s' is not a 64-bit Mach-O binary", target_path); - -#endif /* ^!__APPLE__ */ - - if (!qemu_mode && !dumb_mode && - !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { - - SAYF("\n" cLRD "[-] " cRST - "Looks like the target binary is not instrumented! The fuzzer depends on\n" - " compile-time instrumentation to isolate interesting test cases while\n" - " mutating the input data. For more information, and for tips on how to\n" - " instrument binaries, please see %s/README.\n\n" - - " When source code is not available, you may be able to leverage QEMU\n" - " mode support. Consult the README for tips on how to enable this.\n" - - " (It is also possible to use afl-fuzz as a traditional, \"dumb\" fuzzer.\n" - " For that, you can use the -n option - but expect much worse results.)\n", - doc_path); - - FATAL("No instrumentation detected"); - - } - - if (qemu_mode && - memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { - - SAYF("\n" cLRD "[-] " cRST - "This program appears to be instrumented with afl-gcc, but is being run in\n" - " QEMU mode (-Q). This is probably not what you want - this setup will be\n" - " slow and offer no practical benefits.\n"); - - FATAL("Instrumentation found in -Q mode"); - - } - - if (memmem(f_data, f_len, "libasan.so", 10) || - memmem(f_data, f_len, "__msan_init", 11)) uses_asan = 1; - - /* Detect persistent & deferred init signatures in the binary. */ - - if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { - - OKF(cPIN "Persistent mode binary detected."); - setenv(PERSIST_ENV_VAR, "1", 1); - persistent_mode = 1; - - } else if (getenv("AFL_PERSISTENT")) { - - WARNF("AFL_PERSISTENT is no longer supported and may misbehave!"); - - } - - if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) { - - OKF(cPIN "Deferred forkserver binary detected."); - setenv(DEFER_ENV_VAR, "1", 1); - deferred_mode = 1; - - } else if (getenv("AFL_DEFER_FORKSRV")) { - - WARNF("AFL_DEFER_FORKSRV is no longer supported and may misbehave!"); - - } - - if (munmap(f_data, f_len)) PFATAL("unmap() failed"); - -} - - -/* Trim and possibly create a banner for the run. */ - -static void fix_up_banner(u8* name) { - - if (!use_banner) { - - if (sync_id) { - - use_banner = sync_id; - - } else { - - u8* trim = strrchr(name, '/'); - if (!trim) use_banner = name; else use_banner = trim + 1; - - } - - } - - if (strlen(use_banner) > 40) { - - u8* tmp = ck_alloc(44); - sprintf(tmp, "%.40s...", use_banner); - use_banner = tmp; - - } - -} - - -/* Check if we're on TTY. */ - -static void check_if_tty(void) { - - struct winsize ws; - - if (getenv("AFL_NO_UI")) { - OKF("Disabling the UI because AFL_NO_UI is set."); - not_on_tty = 1; - return; - } - - if (ioctl(1, TIOCGWINSZ, &ws)) { - - if (errno == ENOTTY) { - OKF("Looks like we're not running on a tty, so I'll be a bit less verbose."); - not_on_tty = 1; - } - - return; - } - -} - - -/* Check terminal dimensions after resize. */ - -static void check_term_size(void) { - - struct winsize ws; - - term_too_small = 0; - - if (ioctl(1, TIOCGWINSZ, &ws)) return; - - if (ws.ws_row < 25 || ws.ws_col < 80) term_too_small = 1; - -} - - - -/* Display usage hints. */ - -static void usage(u8* argv0) { - - SAYF("\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n" - - "Required parameters:\n\n" - - " -i dir - input directory with test cases\n" - " -o dir - output directory for fuzzer findings\n\n" - - "Execution control settings:\n\n" - - " -f file - location read by the fuzzed program (stdin)\n" - " -t msec - timeout for each run (auto-scaled, 50-%u ms)\n" - " -m megs - memory limit for child process (%u MB)\n" - " -Q - use binary-only instrumentation (QEMU mode)\n\n" - - "Fuzzing behavior settings:\n\n" - - " -d - quick & dirty mode (skips deterministic steps)\n" - " -n - fuzz without instrumentation (dumb mode)\n" - " -x dir - optional fuzzer dictionary (see README)\n\n" - - "Other stuff:\n\n" - - " -T text - text banner to show on the screen\n" - " -M / -S id - distributed mode (see parallel_fuzzing.txt)\n" - " -C - crash exploration mode (the peruvian rabbit thing)\n\n" - - "For additional tips, please consult %s/README.\n\n", - - argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); - - exit(1); - -} - - -/* Prepare output directories and fds. */ - -EXP_ST void setup_dirs_fds(void) { - - u8* tmp; - s32 fd; - - ACTF("Setting up output directories..."); - - if (sync_id && mkdir(sync_dir, 0700) && errno != EEXIST) - PFATAL("Unable to create '%s'", sync_dir); - - if (mkdir(out_dir, 0700)) { - - if (errno != EEXIST) PFATAL("Unable to create '%s'", out_dir); - - maybe_delete_out_dir(); - - } else { - - if (in_place_resume) - FATAL("Resume attempted but old output directory not found"); - - out_dir_fd = open(out_dir, O_RDONLY); - -#ifndef __sun - - if (out_dir_fd < 0 || flock(out_dir_fd, LOCK_EX | LOCK_NB)) - PFATAL("Unable to flock() output directory."); - -#endif /* !__sun */ - - } - - /* Queue directory for any starting & discovered paths. */ - - tmp = alloc_printf("%s/queue", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* Top-level directory for queue metadata used for session - resume and related tasks. */ - - tmp = alloc_printf("%s/queue/.state/", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* Directory for flagging queue entries that went through - deterministic fuzzing in the past. */ - - tmp = alloc_printf("%s/queue/.state/deterministic_done/", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* Directory with the auto-selected dictionary entries. */ - - tmp = alloc_printf("%s/queue/.state/auto_extras/", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* The set of paths currently deemed redundant. */ - - tmp = alloc_printf("%s/queue/.state/redundant_edges/", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* The set of paths showing variable behavior. */ - - tmp = alloc_printf("%s/queue/.state/variable_behavior/", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* Sync directory for keeping track of cooperating fuzzers. */ - - if (sync_id) { - - tmp = alloc_printf("%s/.synced/", out_dir); - - if (mkdir(tmp, 0700) && (!in_place_resume || errno != EEXIST)) - PFATAL("Unable to create '%s'", tmp); - - ck_free(tmp); - - } - - /* All recorded crashes. */ - - tmp = alloc_printf("%s/crashes", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* All recorded hangs. */ - - tmp = alloc_printf("%s/hangs", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* Generally useful file descriptors. */ - - dev_null_fd = open("/dev/null", O_RDWR); - if (dev_null_fd < 0) PFATAL("Unable to open /dev/null"); - - dev_urandom_fd = open("/dev/urandom", O_RDONLY); - if (dev_urandom_fd < 0) PFATAL("Unable to open /dev/urandom"); - - /* Gnuplot output file. */ - - tmp = alloc_printf("%s/plot_data", out_dir); - fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - plot_file = fdopen(fd, "w"); - if (!plot_file) PFATAL("fdopen() failed"); - - fprintf(plot_file, "# unix_time, cycles_done, cur_path, paths_total, " - "pending_total, pending_favs, map_size, unique_crashes, " - "unique_hangs, max_depth, execs_per_sec\n"); - /* ignore errors */ - -} - - -/* Setup the output file for fuzzed data, if not using -f. */ - -EXP_ST void setup_stdio_file(void) { - - u8* fn = alloc_printf("%s/.cur_input", out_dir); - - unlink(fn); /* Ignore errors */ - - out_fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0600); - - if (out_fd < 0) PFATAL("Unable to create '%s'", fn); - - ck_free(fn); - -} - - -/* Make sure that core dumps don't go to a program. */ - -static void check_crash_handling(void) { - -#ifdef __APPLE__ - - /* Yuck! There appears to be no simple C API to query for the state of - loaded daemons on MacOS X, and I'm a bit hesitant to do something - more sophisticated, such as disabling crash reporting via Mach ports, - until I get a box to test the code. So, for now, we check for crash - reporting the awful way. */ - - if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash$'")) return; - - SAYF("\n" cLRD "[-] " cRST - "Whoops, your system is configured to forward crash notifications to an\n" - " external crash reporting utility. This will cause issues due to the\n" - " extended delay between the fuzzed binary malfunctioning and this fact\n" - " being relayed to the fuzzer via the standard waitpid() API.\n\n" - " To avoid having crashes misinterpreted as timeouts, please run the\n" - " following commands:\n\n" - - " SL=/System/Library; PL=com.apple.ReportCrash\n" - " launchctl unload -w ${SL}/LaunchAgents/${PL}.plist\n" - " sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist\n"); - - if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) - FATAL("Crash reporter detected"); - -#else - - /* This is Linux specific, but I don't think there's anything equivalent on - *BSD, so we can just let it slide for now. */ - - s32 fd = open("/proc/sys/kernel/core_pattern", O_RDONLY); - u8 fchar; - - if (fd < 0) return; - - ACTF("Checking core_pattern..."); - - if (read(fd, &fchar, 1) == 1 && fchar == '|') { - - SAYF("\n" cLRD "[-] " cRST - "Hmm, your system is configured to send core dump notifications to an\n" - " external utility. This will cause issues: there will be an extended delay\n" - " between stumbling upon a crash and having this information relayed to the\n" - " fuzzer via the standard waitpid() API.\n\n" - - " To avoid having crashes misinterpreted as timeouts, please log in as root\n" - " and temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n" - - " echo core >/proc/sys/kernel/core_pattern\n"); - - if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) - FATAL("Pipe at the beginning of 'core_pattern'"); - - } - - close(fd); - -#endif /* ^__APPLE__ */ - -} - - -/* Check CPU governor. */ - -static void check_cpu_governor(void) { - - FILE* f; - u8 tmp[128]; - u64 min = 0, max = 0; - - if (getenv("AFL_SKIP_CPUFREQ")) return; - - f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "r"); - if (!f) return; - - ACTF("Checking CPU scaling governor..."); - - if (!fgets(tmp, 128, f)) PFATAL("fgets() failed"); - - fclose(f); - - if (!strncmp(tmp, "perf", 4)) return; - - f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", "r"); - - if (f) { - if (fscanf(f, "%llu", &min) != 1) min = 0; - fclose(f); - } - - f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", "r"); - - if (f) { - if (fscanf(f, "%llu", &max) != 1) max = 0; - fclose(f); - } - - if (min == max) return; - - SAYF("\n" cLRD "[-] " cRST - "Whoops, your system uses on-demand CPU frequency scaling, adjusted\n" - " between %llu and %llu MHz. Unfortunately, the scaling algorithm in the\n" - " kernel is imperfect and can miss the short-lived processes spawned by\n" - " afl-fuzz. To keep things moving, run these commands as root:\n\n" - - " cd /sys/devices/system/cpu\n" - " echo performance | tee cpu*/cpufreq/scaling_governor\n\n" - - " You can later go back to the original state by replacing 'performance' with\n" - " 'ondemand'. If you don't want to change the settings, set AFL_SKIP_CPUFREQ\n" - " to make afl-fuzz skip this check - but expect some performance drop.\n", - min / 1024, max / 1024); - - FATAL("Suboptimal CPU scaling governor"); - -} - - -/* Count the number of logical CPU cores. */ - -static void get_core_count(void) { - - u32 cur_runnable = 0; - -#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) - - size_t s = sizeof(cpu_core_count); - - /* On *BSD systems, we can just use a sysctl to get the number of CPUs. */ - -#ifdef __APPLE__ - - if (sysctlbyname("hw.logicalcpu", &cpu_core_count, &s, NULL, 0) < 0) - return; - -#else - - int s_name[2] = { CTL_HW, HW_NCPU }; - - if (sysctl(s_name, 2, &cpu_core_count, &s, NULL, 0) < 0) return; - -#endif /* ^__APPLE__ */ - -#else - -#ifdef HAVE_AFFINITY - - cpu_core_count = sysconf(_SC_NPROCESSORS_ONLN); - -#else - - FILE* f = fopen("/proc/stat", "r"); - u8 tmp[1024]; - - if (!f) return; - - while (fgets(tmp, sizeof(tmp), f)) - if (!strncmp(tmp, "cpu", 3) && isdigit(tmp[3])) cpu_core_count++; - - fclose(f); - -#endif /* ^HAVE_AFFINITY */ - -#endif /* ^(__APPLE__ || __FreeBSD__ || __OpenBSD__) */ - - if (cpu_core_count > 0) { - - cur_runnable = (u32)get_runnable_processes(); - -#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) - - /* Add ourselves, since the 1-minute average doesn't include that yet. */ - - cur_runnable++; - -#endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */ - - OKF("You have %u CPU core%s and %u runnable tasks (utilization: %0.0f%%).", - cpu_core_count, cpu_core_count > 1 ? "s" : "", - cur_runnable, cur_runnable * 100.0 / cpu_core_count); - - if (cpu_core_count > 1) { - - if (cur_runnable > cpu_core_count * 1.5) { - - WARNF("System under apparent load, performance may be spotty."); - - } else if (cur_runnable + 1 <= cpu_core_count) { - - OKF("Try parallel jobs - see %s/parallel_fuzzing.txt.", doc_path); - - } - - } - - } else { - - cpu_core_count = 0; - WARNF("Unable to figure out the number of CPU cores."); - - } - -} - - -/* Validate and fix up out_dir and sync_dir when using -S. */ - -static void fix_up_sync(void) { - - u8* x = sync_id; - - if (dumb_mode) - FATAL("-S / -M and -n are mutually exclusive"); - - if (skip_deterministic) { - - if (force_deterministic) - FATAL("use -S instead of -M -d"); - else - FATAL("-S already implies -d"); - - } - - while (*x) { - - if (!isalnum(*x) && *x != '_' && *x != '-') - FATAL("Non-alphanumeric fuzzer ID specified via -S or -M"); - - x++; - - } - - if (strlen(sync_id) > 32) FATAL("Fuzzer ID too long"); - - x = alloc_printf("%s/%s", out_dir, sync_id); - - sync_dir = out_dir; - out_dir = x; - - if (!force_deterministic) { - skip_deterministic = 1; - use_splicing = 1; - } - -} - - -/* Handle screen resize (SIGWINCH). */ - -static void handle_resize(int sig) { - clear_screen = 1; -} - - -/* Check ASAN options. */ - -static void check_asan_opts(void) { - u8* x = getenv("ASAN_OPTIONS"); - - if (x) { - - if (!strstr(x, "abort_on_error=1")) - FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!"); - - if (!strstr(x, "symbolize=0")) - FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); - - } - - x = getenv("MSAN_OPTIONS"); - - if (x) { - - if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) - FATAL("Custom MSAN_OPTIONS set without exit_code=" - STRINGIFY(MSAN_ERROR) " - please fix!"); - - if (!strstr(x, "symbolize=0")) - FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); - - } - -} - - -/* Detect @@ in args. */ - -EXP_ST void detect_file_args(char** argv) { - - u32 i = 0; - u8* cwd = getcwd(NULL, 0); - - if (!cwd) PFATAL("getcwd() failed"); - - while (argv[i]) { - - u8* aa_loc = strstr(argv[i], "@@"); - - if (aa_loc) { - - u8 *aa_subst, *n_arg; - - /* If we don't have a file name chosen yet, use a safe default. */ - - if (!out_file) - out_file = alloc_printf("%s/.cur_input", out_dir); - - /* Be sure that we're always using fully-qualified paths. */ - - if (out_file[0] == '/') aa_subst = out_file; - else aa_subst = alloc_printf("%s/%s", cwd, out_file); - - /* Construct a replacement argv value. */ - - *aa_loc = 0; - n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2); - argv[i] = n_arg; - *aa_loc = '@'; - - if (out_file[0] != '/') ck_free(aa_subst); - - } - - i++; - - } - - free(cwd); /* not tracked */ - -} - - -/* Set up signal handlers. More complicated that needs to be, because libc on - Solaris doesn't resume interrupted reads(), sets SA_RESETHAND when you call - siginterrupt(), and does other stupid things. */ - -EXP_ST void setup_signal_handlers(void) { - - struct sigaction sa; - - sa.sa_handler = NULL; - sa.sa_flags = SA_RESTART; - sa.sa_sigaction = NULL; - - sigemptyset(&sa.sa_mask); - - /* Various ways of saying "stop". */ - - sa.sa_handler = handle_stop_sig; - sigaction(SIGHUP, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - - /* Exec timeout notifications. */ - - sa.sa_handler = handle_timeout; - sigaction(SIGALRM, &sa, NULL); - - /* Window resize */ - - sa.sa_handler = handle_resize; - sigaction(SIGWINCH, &sa, NULL); - - /* SIGUSR1: skip entry */ - - sa.sa_handler = handle_skipreq; - sigaction(SIGUSR1, &sa, NULL); - - /* Things we don't care about. */ - - sa.sa_handler = SIG_IGN; - sigaction(SIGTSTP, &sa, NULL); - sigaction(SIGPIPE, &sa, NULL); - -} - - -/* Rewrite argv for QEMU. */ - -static char** get_qemu_argv(u8* own_loc, char** argv, int argc) { - - char** new_argv = ck_alloc(sizeof(char*) * (argc + 4)); - u8 *tmp, *cp, *rsl, *own_copy; - - /* Workaround for a QEMU stability glitch. */ - - setenv("QEMU_LOG", "nochain", 1); - - memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc); - - new_argv[2] = target_path; - new_argv[1] = "--"; - - /* Now we need to actually find the QEMU binary to put in argv[0]. */ - - tmp = getenv("AFL_PATH"); - - if (tmp) { - - cp = alloc_printf("%s/afl-qemu-trace", tmp); - - if (access(cp, X_OK)) - FATAL("Unable to find '%s'", tmp); - - target_path = new_argv[0] = cp; - return new_argv; - - } - - own_copy = ck_strdup(own_loc); - rsl = strrchr(own_copy, '/'); - - if (rsl) { - - *rsl = 0; - - cp = alloc_printf("%s/afl-qemu-trace", own_copy); - ck_free(own_copy); - - if (!access(cp, X_OK)) { - - target_path = new_argv[0] = cp; - return new_argv; - - } - - } else ck_free(own_copy); - - if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { - - target_path = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace"); - return new_argv; - - } - - SAYF("\n" cLRD "[-] " cRST - "Oops, unable to find the 'afl-qemu-trace' binary. The binary must be built\n" - " separately by following the instructions in qemu_mode/README.qemu. If you\n" - " already have the binary installed, you may need to specify AFL_PATH in the\n" - " environment.\n\n" - - " Of course, even without QEMU, afl-fuzz can still work with binaries that are\n" - " instrumented at compile time with afl-gcc. It is also possible to use it as a\n" - " traditional \"dumb\" fuzzer by specifying '-n' in the command line.\n"); - - FATAL("Failed to locate 'afl-qemu-trace'."); - -} - - -/* Make a copy of the current command line. */ - -static void save_cmdline(u32 argc, char** argv) { - - u32 len = 1, i; - u8* buf; - - for (i = 0; i < argc; i++) - len += strlen(argv[i]) + 1; - - buf = orig_cmdline = ck_alloc(len); - - for (i = 0; i < argc; i++) { - - u32 l = strlen(argv[i]); - - memcpy(buf, argv[i], l); - buf += l; - - if (i != argc - 1) *(buf++) = ' '; - - } - - *buf = 0; - -} - - -#ifndef AFL_LIB - -/* Main entry point */ - -int main(int argc, char** argv) { - - s32 opt; - u64 prev_queued = 0; - u32 sync_interval_cnt = 0, seek_to; - u8 *extras_dir = 0; - u8 mem_limit_given = 0; - u8 exit_1 = !!getenv("AFL_BENCH_JUST_ONE"); - char** use_argv; - - struct timeval tv; - struct timezone tz; - - SAYF(cCYA "afl-fuzz " cBRI VERSION cRST " by \n"); - - doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; - - gettimeofday(&tv, &tz); - srandom(tv.tv_sec ^ tv.tv_usec ^ getpid()); - - while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Q")) > 0) - - switch (opt) { - - case 'i': /* input dir */ - - if (in_dir) FATAL("Multiple -i options not supported"); - in_dir = optarg; - - if (!strcmp(in_dir, "-")) in_place_resume = 1; - - break; - - case 'o': /* output dir */ - - if (out_dir) FATAL("Multiple -o options not supported"); - out_dir = optarg; - break; - - case 'M': { /* master sync ID */ - - u8* c; - - if (sync_id) FATAL("Multiple -S or -M options not supported"); - sync_id = ck_strdup(optarg); - - if ((c = strchr(sync_id, ':'))) { - - *c = 0; - - if (sscanf(c + 1, "%u/%u", &master_id, &master_max) != 2 || - !master_id || !master_max || master_id > master_max || - master_max > 1000000) FATAL("Bogus master ID passed to -M"); - - } - - force_deterministic = 1; - - } - - break; - - case 'S': - - if (sync_id) FATAL("Multiple -S or -M options not supported"); - sync_id = ck_strdup(optarg); - break; - - case 'f': /* target file */ - - if (out_file) FATAL("Multiple -f options not supported"); - out_file = optarg; - break; - - case 'x': /* dictionary */ - - if (extras_dir) FATAL("Multiple -x options not supported"); - extras_dir = optarg; - break; - - case 't': { /* timeout */ - - u8 suffix = 0; - - if (timeout_given) FATAL("Multiple -t options not supported"); - - if (sscanf(optarg, "%u%c", &exec_tmout, &suffix) < 1 || - optarg[0] == '-') FATAL("Bad syntax used for -t"); - - if (exec_tmout < 5) FATAL("Dangerously low value of -t"); - - if (suffix == '+') timeout_given = 2; else timeout_given = 1; - - break; - - } - - case 'm': { /* mem limit */ - - u8 suffix = 'M'; - - if (mem_limit_given) FATAL("Multiple -m options not supported"); - mem_limit_given = 1; - - if (!strcmp(optarg, "none")) { - - mem_limit = 0; - break; - - } - - if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 || - optarg[0] == '-') FATAL("Bad syntax used for -m"); - - switch (suffix) { - - case 'T': mem_limit *= 1024 * 1024; break; - case 'G': mem_limit *= 1024; break; - case 'k': mem_limit /= 1024; break; - case 'M': break; - - default: FATAL("Unsupported suffix or bad syntax for -m"); - - } - - if (mem_limit < 5) FATAL("Dangerously low value of -m"); - - if (sizeof(rlim_t) == 4 && mem_limit > 2000) - FATAL("Value of -m out of range on 32-bit systems"); - - } - - break; - - case 'd': /* skip deterministic */ - - if (skip_deterministic) FATAL("Multiple -d options not supported"); - skip_deterministic = 1; - use_splicing = 1; - break; - - case 'B': /* load bitmap */ - - /* This is a secret undocumented option! It is useful if you find - an interesting test case during a normal fuzzing process, and want - to mutate it without rediscovering any of the test cases already - found during an earlier run. - - To use this mode, you need to point -B to the fuzz_bitmap produced - by an earlier run for the exact same binary... and that's it. - - I only used this once or twice to get variants of a particular - file, so I'm not making this an official setting. */ - - if (in_bitmap) FATAL("Multiple -B options not supported"); - - in_bitmap = optarg; - read_bitmap(in_bitmap); - break; - - case 'C': /* crash mode */ - - if (crash_mode) FATAL("Multiple -C options not supported"); - crash_mode = FAULT_CRASH; - break; - - case 'n': /* dumb mode */ - - if (dumb_mode) FATAL("Multiple -n options not supported"); - if (getenv("AFL_DUMB_FORKSRV")) dumb_mode = 2; else dumb_mode = 1; - - break; - - case 'T': /* banner */ - - if (use_banner) FATAL("Multiple -T options not supported"); - use_banner = optarg; - break; - - case 'Q': /* QEMU mode */ - - if (qemu_mode) FATAL("Multiple -Q options not supported"); - qemu_mode = 1; - - if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU; - - break; - - default: - - usage(argv[0]); - - } - - if (optind == argc || !in_dir || !out_dir) usage(argv[0]); - - setup_signal_handlers(); - check_asan_opts(); - - if (sync_id) fix_up_sync(); - - if (!strcmp(in_dir, out_dir)) - FATAL("Input and output directories can't be the same"); - - if (dumb_mode) { - - if (crash_mode) FATAL("-C and -n are mutually exclusive"); - if (qemu_mode) FATAL("-Q and -n are mutually exclusive"); - - } - - if (getenv("AFL_NO_FORKSRV")) no_forkserver = 1; - if (getenv("AFL_NO_CPU_RED")) no_cpu_meter_red = 1; - if (getenv("AFL_NO_ARITH")) no_arith = 1; - if (getenv("AFL_SHUFFLE_QUEUE")) shuffle_queue = 1; - if (getenv("AFL_FAST_CAL")) fast_cal = 1; - - if (getenv("AFL_HANG_TMOUT")) { - hang_tmout = atoi(getenv("AFL_HANG_TMOUT")); - if (!hang_tmout) FATAL("Invalid value of AFL_HANG_TMOUT"); - } - - if (dumb_mode == 2 && no_forkserver) - FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive"); - - if (getenv("AFL_PRELOAD")) { - setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); - setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); - } - - if (getenv("AFL_LD_PRELOAD")) - FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD"); - - save_cmdline(argc, argv); - - fix_up_banner(argv[optind]); - - check_if_tty(); - - get_core_count(); - -#ifdef HAVE_AFFINITY - bind_to_free_cpu(); -#endif /* HAVE_AFFINITY */ - - check_crash_handling(); - check_cpu_governor(); - - setup_post(); - setup_shm(); - init_count_class16(); - - setup_dirs_fds(); - read_testcases(); - load_auto(); - - pivot_inputs(); - - if (extras_dir) load_extras(extras_dir); - - if (!timeout_given) find_timeout(); - - detect_file_args(argv + optind + 1); - - if (!out_file) setup_stdio_file(); - - check_binary(argv[optind]); - - start_time = get_cur_time(); - - if (qemu_mode) - use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); - else - use_argv = argv + optind; - - perform_dry_run(use_argv); - - cull_queue(); - - show_init_stats(); - - seek_to = find_start_position(); - - write_stats_file(0, 0, 0); - save_auto(); - - if (stop_soon) goto stop_fuzzing; - - /* Woop woop woop */ - - if (!not_on_tty) { - sleep(4); - start_time += 4000; - if (stop_soon) goto stop_fuzzing; - } - - while (1) { - - u8 skipped_fuzz; - - cull_queue(); - - if (!queue_cur) { - - queue_cycle++; - current_entry = 0; - cur_skipped_paths = 0; - queue_cur = queue; - - while (seek_to) { - current_entry++; - seek_to--; - queue_cur = queue_cur->next; - } - - show_stats(); - - if (not_on_tty) { - ACTF("Entering queue cycle %llu.", queue_cycle); - fflush(stdout); - } - - /* If we had a full queue cycle with no new finds, try - recombination strategies next. */ - - if (queued_paths == prev_queued) { - - if (use_splicing) cycles_wo_finds++; else use_splicing = 1; - - } else cycles_wo_finds = 0; - - prev_queued = queued_paths; - - if (sync_id && queue_cycle == 1 && getenv("AFL_IMPORT_FIRST")) - sync_fuzzers(use_argv); - - } - - skipped_fuzz = fuzz_one(use_argv); - - if (!stop_soon && sync_id && !skipped_fuzz) { - - if (!(sync_interval_cnt++ % SYNC_INTERVAL)) - sync_fuzzers(use_argv); - - } - - if (!stop_soon && exit_1) stop_soon = 2; - - if (stop_soon) break; - - queue_cur = queue_cur->next; - current_entry++; - - } - - if (queue_cur) show_stats(); - - write_bitmap(); - write_stats_file(0, 0, 0); - save_auto(); - -stop_fuzzing: - - SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST, - stop_soon == 2 ? "programmatically" : "by user"); - - /* Running for more than 30 minutes but still doing first cycle? */ - - if (queue_cycle == 1 && get_cur_time() - start_time > 30 * 60 * 1000) { - - SAYF("\n" cYEL "[!] " cRST - "Stopped during the first cycle, results may be incomplete.\n" - " (For info on resuming, see %s/README.)\n", doc_path); - - } - - fclose(plot_file); - destroy_queue(); - destroy_extras(); - ck_free(target_path); - ck_free(sync_id); - - alloc_report(); - - OKF("We're done here. Have a nice day!\n"); - - exit(0); - -} - -#endif /* !AFL_LIB */ \ No newline at end of file diff --git a/third_party/afl/afl-showmap.c b/third_party/afl/afl-showmap.c deleted file mode 100644 index 2e2d24bc7..000000000 --- a/third_party/afl/afl-showmap.c +++ /dev/null @@ -1,780 +0,0 @@ -/* - american fuzzy lop - map display utility - ---------------------------------------- - - Written and maintained by Michal Zalewski - - Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - A very simple tool that runs the targeted binary and displays - the contents of the trace bitmap in a human-readable form. Useful in - scripts to eliminate redundant inputs and perform other checks. - - Exit code is 2 if the target program crashes; 1 if it times out or - there is a problem executing it; or 0 if execution is successful. - - */ - -#define AFL_MAIN - -#include "config.h" -#include "types.h" -#include "debug.h" -#include "alloc-inl.h" -#include "hash.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -static s32 child_pid; /* PID of the tested program */ - -static u8* trace_bits; /* SHM with instrumentation bitmap */ - -static u8 *out_file, /* Trace output file */ - *doc_path, /* Path to docs */ - *target_path, /* Path to target binary */ - *at_file; /* Substitution string for @@ */ - -static u32 exec_tmout; /* Exec timeout (ms) */ - -static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ - -static s32 shm_id; /* ID of the SHM region */ - -static u8 quiet_mode, /* Hide non-essential messages? */ - edges_only, /* Ignore hit counts? */ - cmin_mode, /* Generate output in afl-cmin mode? */ - binary_mode, /* Write output as a binary map */ - keep_cores; /* Allow coredumps? */ - -static volatile u8 - stop_soon, /* Ctrl-C pressed? */ - child_timed_out, /* Child timed out? */ - child_crashed; /* Child crashed? */ - -/* Classify tuple counts. Instead of mapping to individual bits, as in - afl-fuzz.c, we map to more user-friendly numbers between 1 and 8. */ - -static const u8 count_class_human[256] = { - - [0] = 0, - [1] = 1, - [2] = 2, - [3] = 3, - [4 ... 7] = 4, - [8 ... 15] = 5, - [16 ... 31] = 6, - [32 ... 127] = 7, - [128 ... 255] = 8 - -}; - -static const u8 count_class_binary[256] = { - - [0] = 0, - [1] = 1, - [2] = 2, - [3] = 4, - [4 ... 7] = 8, - [8 ... 15] = 16, - [16 ... 31] = 32, - [32 ... 127] = 64, - [128 ... 255] = 128 - -}; - -static void classify_counts(u8* mem, const u8* map) { - - u32 i = MAP_SIZE; - - if (edges_only) { - - while (i--) { - if (*mem) *mem = 1; - mem++; - } - - } else { - - while (i--) { - *mem = map[*mem]; - mem++; - } - - } - -} - - -/* Get rid of shared memory (atexit handler). */ - -static void remove_shm(void) { - - shmctl(shm_id, IPC_RMID, NULL); - -} - - -/* Configure shared memory. */ - -static void setup_shm(void) { - - u8* shm_str; - - shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); - - if (shm_id < 0) PFATAL("shmget() failed"); - - atexit(remove_shm); - - shm_str = alloc_printf("%d", shm_id); - - setenv(SHM_ENV_VAR, shm_str, 1); - - ck_free(shm_str); - - trace_bits = shmat(shm_id, NULL, 0); - - if (!trace_bits) PFATAL("shmat() failed"); - -} - -/* Write results. */ - -static u32 write_results(void) { - - s32 fd; - u32 i, ret = 0; - - u8 cco = !!getenv("AFL_CMIN_CRASHES_ONLY"), - caa = !!getenv("AFL_CMIN_ALLOW_ANY"); - - if (!strncmp(out_file, "/dev/", 5)) { - - fd = open(out_file, O_WRONLY, 0600); - if (fd < 0) PFATAL("Unable to open '%s'", out_file); - - } else if (!strcmp(out_file, "-")) { - - fd = dup(1); - if (fd < 0) PFATAL("Unable to open stdout"); - - } else { - - unlink(out_file); /* Ignore errors */ - fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", out_file); - - } - - - if (binary_mode) { - - for (i = 0; i < MAP_SIZE; i++) - if (trace_bits[i]) ret++; - - ck_write(fd, trace_bits, MAP_SIZE, out_file); - close(fd); - - } else { - - FILE* f = fdopen(fd, "w"); - - if (!f) PFATAL("fdopen() failed"); - - for (i = 0; i < MAP_SIZE; i++) { - - if (!trace_bits[i]) continue; - ret++; - - if (cmin_mode) { - - if (child_timed_out) break; - if (!caa && child_crashed != cco) break; - - fprintf(f, "%u%u\n", trace_bits[i], i); - - } else fprintf(f, "%06u:%u\n", i, trace_bits[i]); - - } - - fclose(f); - - } - - return ret; - -} - - -/* Handle timeout signal. */ - -static void handle_timeout(int sig) { - - child_timed_out = 1; - if (child_pid > 0) kill(child_pid, SIGKILL); - -} - - -/* Execute target application. */ - -static void run_target(char** argv) { - - static struct itimerval it; - int status = 0; - - if (!quiet_mode) - SAYF("-- Program output begins --\n" cRST); - - MEM_BARRIER(); - - child_pid = fork(); - - if (child_pid < 0) PFATAL("fork() failed"); - - if (!child_pid) { - - struct rlimit r; - - if (quiet_mode) { - - s32 fd = open("/dev/null", O_RDWR); - - if (fd < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0) { - *(u32*)trace_bits = EXEC_FAIL_SIG; - PFATAL("Descriptor initialization failed"); - } - - close(fd); - - } - - if (mem_limit) { - - r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20; - -#ifdef RLIMIT_AS - - setrlimit(RLIMIT_AS, &r); /* Ignore errors */ - -#else - - setrlimit(RLIMIT_DATA, &r); /* Ignore errors */ - -#endif /* ^RLIMIT_AS */ - - } - - if (!keep_cores) r.rlim_max = r.rlim_cur = 0; - else r.rlim_max = r.rlim_cur = RLIM_INFINITY; - - setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ - - if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0); - - setsid(); - - execv(target_path, argv); - - *(u32*)trace_bits = EXEC_FAIL_SIG; - exit(0); - - } - - /* Configure timeout, wait for child, cancel timeout. */ - - if (exec_tmout) { - - child_timed_out = 0; - it.it_value.tv_sec = (exec_tmout / 1000); - it.it_value.tv_usec = (exec_tmout % 1000) * 1000; - - } - - setitimer(ITIMER_REAL, &it, NULL); - - if (waitpid(child_pid, &status, 0) <= 0) FATAL("waitpid() failed"); - - child_pid = 0; - it.it_value.tv_sec = 0; - it.it_value.tv_usec = 0; - setitimer(ITIMER_REAL, &it, NULL); - - MEM_BARRIER(); - - /* Clean up bitmap, analyze exit condition, etc. */ - - if (*(u32*)trace_bits == EXEC_FAIL_SIG) - FATAL("Unable to execute '%s'", argv[0]); - - classify_counts(trace_bits, binary_mode ? - count_class_binary : count_class_human); - - if (!quiet_mode) - SAYF(cRST "-- Program output ends --\n"); - - if (!child_timed_out && !stop_soon && WIFSIGNALED(status)) - child_crashed = 1; - - if (!quiet_mode) { - - if (child_timed_out) - SAYF(cLRD "\n+++ Program timed off +++\n" cRST); - else if (stop_soon) - SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST); - else if (child_crashed) - SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST, WTERMSIG(status)); - - } - - -} - - -/* Handle Ctrl-C and the like. */ - -static void handle_stop_sig(int sig) { - - stop_soon = 1; - - if (child_pid > 0) kill(child_pid, SIGKILL); - -} - - -/* Do basic preparations - persistent fds, filenames, etc. */ - -static void set_up_environment(void) { - - setenv("ASAN_OPTIONS", "abort_on_error=1:" - "detect_leaks=0:" - "symbolize=0:" - "allocator_may_return_null=1", 0); - - setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" - "symbolize=0:" - "abort_on_error=1:" - "allocator_may_return_null=1:" - "msan_track_origins=0", 0); - - if (getenv("AFL_PRELOAD")) { - setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); - setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); - } - -} - - -/* Setup signal handlers, duh. */ - -static void setup_signal_handlers(void) { - - struct sigaction sa; - - sa.sa_handler = NULL; - sa.sa_flags = SA_RESTART; - sa.sa_sigaction = NULL; - - sigemptyset(&sa.sa_mask); - - /* Various ways of saying "stop". */ - - sa.sa_handler = handle_stop_sig; - sigaction(SIGHUP, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - - /* Exec timeout notifications. */ - - sa.sa_handler = handle_timeout; - sigaction(SIGALRM, &sa, NULL); - -} - - -/* Detect @@ in args. */ - -static void detect_file_args(char** argv) { - - u32 i = 0; - u8* cwd = getcwd(NULL, 0); - - if (!cwd) PFATAL("getcwd() failed"); - - while (argv[i]) { - - u8* aa_loc = strstr(argv[i], "@@"); - - if (aa_loc) { - - u8 *aa_subst, *n_arg; - - if (!at_file) FATAL("@@ syntax is not supported by this tool."); - - /* Be sure that we're always using fully-qualified paths. */ - - if (at_file[0] == '/') aa_subst = at_file; - else aa_subst = alloc_printf("%s/%s", cwd, at_file); - - /* Construct a replacement argv value. */ - - *aa_loc = 0; - n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2); - argv[i] = n_arg; - *aa_loc = '@'; - - if (at_file[0] != '/') ck_free(aa_subst); - - } - - i++; - - } - - free(cwd); /* not tracked */ - -} - - -/* Show banner. */ - -static void show_banner(void) { - - SAYF(cCYA "afl-showmap " cBRI VERSION cRST " by \n"); - -} - -/* Display usage hints. */ - -static void usage(u8* argv0) { - - show_banner(); - - SAYF("\n%s [ options ] -- /path/to/target_app [ ... ]\n\n" - - "Required parameters:\n\n" - - " -o file - file to write the trace data to\n\n" - - "Execution control settings:\n\n" - - " -t msec - timeout for each run (none)\n" - " -m megs - memory limit for child process (%u MB)\n" - " -Q - use binary-only instrumentation (QEMU mode)\n\n" - - "Other settings:\n\n" - - " -q - sink program's output and don't show messages\n" - " -e - show edge coverage only, ignore hit counts\n" - " -c - allow core dumps\n\n" - - "This tool displays raw tuple data captured by AFL instrumentation.\n" - "For additional help, consult %s/README.\n\n" cRST, - - argv0, MEM_LIMIT, doc_path); - - exit(1); - -} - - -/* Find binary. */ - -static void find_binary(u8* fname) { - - u8* env_path = 0; - struct stat st; - - if (strchr(fname, '/') || !(env_path = getenv("PATH"))) { - - target_path = ck_strdup(fname); - - if (stat(target_path, &st) || !S_ISREG(st.st_mode) || - !(st.st_mode & 0111) || st.st_size < 4) - FATAL("Program '%s' not found or not executable", fname); - - } else { - - while (env_path) { - - u8 *cur_elem, *delim = strchr(env_path, ':'); - - if (delim) { - - cur_elem = ck_alloc(delim - env_path + 1); - memcpy(cur_elem, env_path, delim - env_path); - delim++; - - } else cur_elem = ck_strdup(env_path); - - env_path = delim; - - if (cur_elem[0]) - target_path = alloc_printf("%s/%s", cur_elem, fname); - else - target_path = ck_strdup(fname); - - ck_free(cur_elem); - - if (!stat(target_path, &st) && S_ISREG(st.st_mode) && - (st.st_mode & 0111) && st.st_size >= 4) break; - - ck_free(target_path); - target_path = 0; - - } - - if (!target_path) FATAL("Program '%s' not found or not executable", fname); - - } - -} - - -/* Fix up argv for QEMU. */ - -static char** get_qemu_argv(u8* own_loc, char** argv, int argc) { - - char** new_argv = ck_alloc(sizeof(char*) * (argc + 4)); - u8 *tmp, *cp, *rsl, *own_copy; - - /* Workaround for a QEMU stability glitch. */ - - setenv("QEMU_LOG", "nochain", 1); - - memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc); - - new_argv[2] = target_path; - new_argv[1] = "--"; - - /* Now we need to actually find qemu for argv[0]. */ - - tmp = getenv("AFL_PATH"); - - if (tmp) { - - cp = alloc_printf("%s/afl-qemu-trace", tmp); - - if (access(cp, X_OK)) - FATAL("Unable to find '%s'", tmp); - - target_path = new_argv[0] = cp; - return new_argv; - - } - - own_copy = ck_strdup(own_loc); - rsl = strrchr(own_copy, '/'); - - if (rsl) { - - *rsl = 0; - - cp = alloc_printf("%s/afl-qemu-trace", own_copy); - ck_free(own_copy); - - if (!access(cp, X_OK)) { - - target_path = new_argv[0] = cp; - return new_argv; - - } - - } else ck_free(own_copy); - - if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { - - target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace"; - return new_argv; - - } - - FATAL("Unable to find 'afl-qemu-trace'."); - -} - - -/* Main entry point */ - -int main(int argc, char** argv) { - - s32 opt; - u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0; - u32 tcnt; - char** use_argv; - - doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; - - while ((opt = getopt(argc,argv,"+o:m:t:A:eqZQbc")) > 0) - - switch (opt) { - - case 'o': - - if (out_file) FATAL("Multiple -o options not supported"); - out_file = optarg; - break; - - case 'm': { - - u8 suffix = 'M'; - - if (mem_limit_given) FATAL("Multiple -m options not supported"); - mem_limit_given = 1; - - if (!strcmp(optarg, "none")) { - - mem_limit = 0; - break; - - } - - if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 || - optarg[0] == '-') FATAL("Bad syntax used for -m"); - - switch (suffix) { - - case 'T': mem_limit *= 1024 * 1024; break; - case 'G': mem_limit *= 1024; break; - case 'k': mem_limit /= 1024; break; - case 'M': break; - - default: FATAL("Unsupported suffix or bad syntax for -m"); - - } - - if (mem_limit < 5) FATAL("Dangerously low value of -m"); - - if (sizeof(rlim_t) == 4 && mem_limit > 2000) - FATAL("Value of -m out of range on 32-bit systems"); - - } - - break; - - case 't': - - if (timeout_given) FATAL("Multiple -t options not supported"); - timeout_given = 1; - - if (strcmp(optarg, "none")) { - exec_tmout = atoi(optarg); - - if (exec_tmout < 20 || optarg[0] == '-') - FATAL("Dangerously low value of -t"); - - } - - break; - - case 'e': - - if (edges_only) FATAL("Multiple -e options not supported"); - edges_only = 1; - break; - - case 'q': - - if (quiet_mode) FATAL("Multiple -q options not supported"); - quiet_mode = 1; - break; - - case 'Z': - - /* This is an undocumented option to write data in the syntax expected - by afl-cmin. Nobody else should have any use for this. */ - - cmin_mode = 1; - quiet_mode = 1; - break; - - case 'A': - - /* Another afl-cmin specific feature. */ - at_file = optarg; - break; - - case 'Q': - - if (qemu_mode) FATAL("Multiple -Q options not supported"); - if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU; - - qemu_mode = 1; - break; - - case 'b': - - /* Secret undocumented mode. Writes output in raw binary format - similar to that dumped by afl-fuzz in test_fuzzer.cc -#include -#include -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (size > 0 && data[0] == 'H') - if (size > 1 && data[1] == 'I') - if (size > 2 && data[2] == '!') - __builtin_trap(); - return 0; -} -EOF -# Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang. -clang -g -fsanitize-coverage=trace-pc-guard test_fuzzer.cc -c -# Build afl-llvm-rt.o.c from the AFL distribution. -clang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c -# Build this file, link it with afl-llvm-rt.o.o and the target code. -clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o -# Run AFL: -rm -rf IN OUT; mkdir IN OUT; echo z > IN/z; -$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out -################################################################################ -AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file -specified. If the file does not exist, it is created. This is useful for getting -stack traces (when using ASAN for example) or original error messages on hard -to reproduce bugs. Note that any content written to stderr will be written to -this file instead of stderr's usual location. - -AFL_DRIVER_CLOSE_FD_MASK: Similar to libFuzzer's -close_fd_mask behavior option. -If 1, close stdout at startup. If 2 close stderr; if 3 close both. - -*/ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -// Platform detection. Copied from FuzzerInternal.h -#ifdef __linux__ -#define LIBFUZZER_LINUX 1 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#elif __APPLE__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 1 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#elif __NetBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 1 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#elif __FreeBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 1 -#define LIBFUZZER_OPENBSD 0 -#elif __OpenBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 1 -#else -#error "Support for your platform has not been implemented" -#endif - -// libFuzzer interface is thin, so we don't include any libFuzzer headers. -extern "C" { -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); -__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); -} - -// Notify AFL about persistent mode. -static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; -extern "C" int __afl_persistent_loop(unsigned int); -static volatile char suppress_warning2 = AFL_PERSISTENT[0]; - -// Notify AFL about deferred forkserver. -static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; -extern "C" void __afl_manual_init(); -static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0]; - -// Input buffer. -static const size_t kMaxAflInputSize = 1 << 20; -static uint8_t AflInputBuf[kMaxAflInputSize]; - -// Use this optionally defined function to output sanitizer messages even if -// user asks to close stderr. -__attribute__((weak)) extern "C" void __sanitizer_set_report_fd(void *); - -// Keep track of where stderr content is being written to, so that -// dup_and_close_stderr can use the correct one. -static FILE *output_file = stderr; - -// Experimental feature to use afl_driver without AFL's deferred mode. -// Needs to run before __afl_auto_init. -__attribute__((constructor(0))) static void __decide_deferred_forkserver(void) { - if (getenv("AFL_DRIVER_DONT_DEFER")) { - if (unsetenv("__AFL_DEFER_FORKSRV")) { - perror("Failed to unset __AFL_DEFER_FORKSRV"); - abort(); - } - } -} - -// If the user asks us to duplicate stderr, then do it. -static void maybe_duplicate_stderr() { - char *stderr_duplicate_filename = - getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); - - if (!stderr_duplicate_filename) - return; - - FILE *stderr_duplicate_stream = - freopen(stderr_duplicate_filename, "a+", stderr); - - if (!stderr_duplicate_stream) { - fprintf( - stderr, - "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); - abort(); - } - output_file = stderr_duplicate_stream; -} - -// Most of these I/O functions were inspired by/copied from libFuzzer's code. -static void discard_output(int fd) { - FILE *temp = fopen("/dev/null", "w"); - if (!temp) - abort(); - dup2(fileno(temp), fd); - fclose(temp); -} - -static void close_stdout() { discard_output(STDOUT_FILENO); } - -// Prevent the targeted code from writing to "stderr" but allow sanitizers and -// this driver to do so. -static void dup_and_close_stderr() { - int output_fileno = fileno(output_file); - int output_fd = dup(output_fileno); - if (output_fd <= 0) - abort(); - FILE *new_output_file = fdopen(output_fd, "w"); - if (!new_output_file) - abort(); - if (!__sanitizer_set_report_fd) - return; - __sanitizer_set_report_fd(reinterpret_cast(output_fd)); - discard_output(output_fileno); -} - -static void Printf(const char *Fmt, ...) { - va_list ap; - va_start(ap, Fmt); - vfprintf(output_file, Fmt, ap); - va_end(ap); - fflush(output_file); -} - -// Close stdout and/or stderr if user asks for it. -static void maybe_close_fd_mask() { - char *fd_mask_str = getenv("AFL_DRIVER_CLOSE_FD_MASK"); - if (!fd_mask_str) - return; - int fd_mask = atoi(fd_mask_str); - if (fd_mask & 2) - dup_and_close_stderr(); - if (fd_mask & 1) - close_stdout(); -} - -// Define LLVMFuzzerMutate to avoid link failures for targets that use it -// with libFuzzer's LLVMFuzzerCustomMutator. -extern "C" size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { - assert(false && "LLVMFuzzerMutate should not be called from afl_driver"); - return 0; -} - -// Execute any files provided as parameters. -static int ExecuteFilesOnyByOne(int argc, char **argv) { - for (int i = 1; i < argc; i++) { - std::ifstream in(argv[i], std::ios::binary); - in.seekg(0, in.end); - size_t length = in.tellg(); - in.seekg (0, in.beg); - std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl; - // Allocate exactly length bytes so that we reliably catch buffer overflows. - std::vector bytes(length); - in.read(bytes.data(), bytes.size()); - assert(in); - LLVMFuzzerTestOneInput(reinterpret_cast(bytes.data()), - bytes.size()); - std::cout << "Execution successful" << std::endl; - } - return 0; -} - -int main(int argc, char **argv) { - Printf( - "======================= INFO =========================\n" - "This binary is built for AFL-fuzz.\n" - "To run the target function on individual input(s) execute this:\n" - " %s < INPUT_FILE\n" - "or\n" - " %s INPUT_FILE1 [INPUT_FILE2 ... ]\n" - "To fuzz with afl-fuzz execute this:\n" - " afl-fuzz [afl-flags] %s [-N]\n" - "afl-fuzz will run N iterations before " - "re-spawning the process (default: 1000)\n" - "======================================================\n", - argv[0], argv[0], argv[0]); - - maybe_duplicate_stderr(); - maybe_close_fd_mask(); - if (LLVMFuzzerInitialize) - LLVMFuzzerInitialize(&argc, &argv); - // Do any other expensive one-time initialization here. - - if (!getenv("AFL_DRIVER_DONT_DEFER")) - __afl_manual_init(); - - int N = 1000; - if (argc == 2 && argv[1][0] == '-') - N = atoi(argv[1] + 1); - else if(argc == 2 && (N = atoi(argv[1])) > 0) - Printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N); - else if (argc > 1) - return ExecuteFilesOnyByOne(argc, argv); - - assert(N > 0); - - // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization - // on the first execution of LLVMFuzzerTestOneInput is ignored. - uint8_t dummy_input[1] = {0}; - LLVMFuzzerTestOneInput(dummy_input, 1); - - int num_runs = 0; - while (__afl_persistent_loop(N)) { - ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize); - if (n_read > 0) { - // Copy AflInputBuf into a separate buffer to let asan find buffer - // overflows. Don't use unique_ptr/etc to avoid extra dependencies. - uint8_t *copy = new uint8_t[n_read]; - memcpy(copy, AflInputBuf, n_read); - num_runs++; - LLVMFuzzerTestOneInput(copy, n_read); - delete[] copy; - } - } - Printf("%s: successfully executed %d input(s)\n", argv[0], num_runs); -} \ No newline at end of file diff --git a/third_party/afl/alloc-inl.h b/third_party/afl/alloc-inl.h deleted file mode 100644 index 87cc0b114..000000000 --- a/third_party/afl/alloc-inl.h +++ /dev/null @@ -1,570 +0,0 @@ -/* - american fuzzy lop - error-checking, memory-zeroing alloc routines - ------------------------------------------------------------------ - - Written and maintained by Michal Zalewski - - Copyright 2013, 2014, 2015 Google Inc. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This allocator is not designed to resist malicious attackers (the canaries - are small and predictable), but provides a robust and portable way to detect - use-after-free, off-by-one writes, stale pointers, and so on. - - */ - -#ifndef _HAVE_ALLOC_INL_H -#define _HAVE_ALLOC_INL_H - -#include -#include -#include - -#include "config.h" -#include "types.h" -#include "debug.h" - -/* User-facing macro to sprintf() to a dynamically allocated buffer. */ - -#define alloc_printf(_str...) ({ \ - u8* _tmp; \ - s32 _len = snprintf(NULL, 0, _str); \ - if (_len < 0) FATAL("Whoa, snprintf() fails?!"); \ - _tmp = ck_alloc(_len + 1); \ - snprintf((char*)_tmp, _len + 1, _str); \ - _tmp; \ - }) - -/* Macro to enforce allocation limits as a last-resort defense against - integer overflows. */ - -#define ALLOC_CHECK_SIZE(_s) do { \ - if ((_s) > MAX_ALLOC) \ - ABORT("Bad alloc request: %u bytes", (_s)); \ - } while (0) - -/* Macro to check malloc() failures and the like. */ - -#define ALLOC_CHECK_RESULT(_r, _s) do { \ - if (!(_r)) \ - ABORT("Out of memory: can't allocate %u bytes", (_s)); \ - } while (0) - -/* Magic tokens used to mark used / freed chunks. */ - -#define ALLOC_MAGIC_C1 0xFF00FF00 /* Used head (dword) */ -#define ALLOC_MAGIC_F 0xFE00FE00 /* Freed head (dword) */ -#define ALLOC_MAGIC_C2 0xF0 /* Used tail (byte) */ - -/* Positions of guard tokens in relation to the user-visible pointer. */ - -#define ALLOC_C1(_ptr) (((u32*)(_ptr))[-2]) -#define ALLOC_S(_ptr) (((u32*)(_ptr))[-1]) -#define ALLOC_C2(_ptr) (((u8*)(_ptr))[ALLOC_S(_ptr)]) - -#define ALLOC_OFF_HEAD 8 -#define ALLOC_OFF_TOTAL (ALLOC_OFF_HEAD + 1) - -/* Allocator increments for ck_realloc_block(). */ - -#define ALLOC_BLK_INC 256 - -/* Sanity-checking macros for pointers. */ - -#define CHECK_PTR(_p) do { \ - if (_p) { \ - if (ALLOC_C1(_p) ^ ALLOC_MAGIC_C1) {\ - if (ALLOC_C1(_p) == ALLOC_MAGIC_F) \ - ABORT("Use after free."); \ - else ABORT("Corrupted head alloc canary."); \ - } \ - if (ALLOC_C2(_p) ^ ALLOC_MAGIC_C2) \ - ABORT("Corrupted tail alloc canary."); \ - } \ - } while (0) - -#define CHECK_PTR_EXPR(_p) ({ \ - typeof (_p) _tmp = (_p); \ - CHECK_PTR(_tmp); \ - _tmp; \ - }) - - -/* Allocate a buffer, explicitly not zeroing it. Returns NULL for zero-sized - requests. */ - -static inline void* DFL_ck_alloc_nozero(u32 size) { - - void* ret; - - if (!size) return NULL; - - ALLOC_CHECK_SIZE(size); - ret = malloc(size + ALLOC_OFF_TOTAL); - ALLOC_CHECK_RESULT(ret, size); - - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; - - return ret; - -} - - -/* Allocate a buffer, returning zeroed memory. */ - -static inline void* DFL_ck_alloc(u32 size) { - - void* mem; - - if (!size) return NULL; - mem = DFL_ck_alloc_nozero(size); - - return memset(mem, 0, size); - -} - - -/* Free memory, checking for double free and corrupted heap. When DEBUG_BUILD - is set, the old memory will be also clobbered with 0xFF. */ - -static inline void DFL_ck_free(void* mem) { - - if (!mem) return; - - CHECK_PTR(mem); - -#ifdef DEBUG_BUILD - - /* Catch pointer issues sooner. */ - memset(mem, 0xFF, ALLOC_S(mem)); - -#endif /* DEBUG_BUILD */ - - ALLOC_C1(mem) = ALLOC_MAGIC_F; - - free(mem - ALLOC_OFF_HEAD); - -} - - -/* Re-allocate a buffer, checking for issues and zeroing any newly-added tail. - With DEBUG_BUILD, the buffer is always reallocated to a new addresses and the - old memory is clobbered with 0xFF. */ - -static inline void* DFL_ck_realloc(void* orig, u32 size) { - - void* ret; - u32 old_size = 0; - - if (!size) { - - DFL_ck_free(orig); - return NULL; - - } - - if (orig) { - - CHECK_PTR(orig); - -#ifndef DEBUG_BUILD - ALLOC_C1(orig) = ALLOC_MAGIC_F; -#endif /* !DEBUG_BUILD */ - - old_size = ALLOC_S(orig); - orig -= ALLOC_OFF_HEAD; - - ALLOC_CHECK_SIZE(old_size); - - } - - ALLOC_CHECK_SIZE(size); - -#ifndef DEBUG_BUILD - - ret = realloc(orig, size + ALLOC_OFF_TOTAL); - ALLOC_CHECK_RESULT(ret, size); - -#else - - /* Catch pointer issues sooner: force relocation and make sure that the - original buffer is wiped. */ - - ret = malloc(size + ALLOC_OFF_TOTAL); - ALLOC_CHECK_RESULT(ret, size); - - if (orig) { - - memcpy(ret + ALLOC_OFF_HEAD, orig + ALLOC_OFF_HEAD, MIN(size, old_size)); - memset(orig + ALLOC_OFF_HEAD, 0xFF, old_size); - - ALLOC_C1(orig + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F; - - free(orig); - - } - -#endif /* ^!DEBUG_BUILD */ - - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; - - if (size > old_size) - memset(ret + old_size, 0, size - old_size); - - return ret; - -} - - -/* Re-allocate a buffer with ALLOC_BLK_INC increments (used to speed up - repeated small reallocs without complicating the user code). */ - -static inline void* DFL_ck_realloc_block(void* orig, u32 size) { - -#ifndef DEBUG_BUILD - - if (orig) { - - CHECK_PTR(orig); - - if (ALLOC_S(orig) >= size) return orig; - - size += ALLOC_BLK_INC; - - } - -#endif /* !DEBUG_BUILD */ - - return DFL_ck_realloc(orig, size); - -} - - -/* Create a buffer with a copy of a string. Returns NULL for NULL inputs. */ - -static inline u8* DFL_ck_strdup(u8* str) { - - void* ret; - u32 size; - - if (!str) return NULL; - - size = strlen((char*)str) + 1; - - ALLOC_CHECK_SIZE(size); - ret = malloc(size + ALLOC_OFF_TOTAL); - ALLOC_CHECK_RESULT(ret, size); - - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; - - return memcpy(ret, str, size); - -} - - -/* Create a buffer with a copy of a memory block. Returns NULL for zero-sized - or NULL inputs. */ - -static inline void* DFL_ck_memdup(void* mem, u32 size) { - - void* ret; - - if (!mem || !size) return NULL; - - ALLOC_CHECK_SIZE(size); - ret = malloc(size + ALLOC_OFF_TOTAL); - ALLOC_CHECK_RESULT(ret, size); - - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; - - return memcpy(ret, mem, size); - -} - - -/* Create a buffer with a block of text, appending a NUL terminator at the end. - Returns NULL for zero-sized or NULL inputs. */ - -static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) { - - u8* ret; - - if (!mem || !size) return NULL; - - ALLOC_CHECK_SIZE(size); - ret = malloc(size + ALLOC_OFF_TOTAL + 1); - ALLOC_CHECK_RESULT(ret, size); - - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; - - memcpy(ret, mem, size); - ret[size] = 0; - - return ret; - -} - - -#ifndef DEBUG_BUILD - -/* In non-debug mode, we just do straightforward aliasing of the above functions - to user-visible names such as ck_alloc(). */ - -#define ck_alloc DFL_ck_alloc -#define ck_alloc_nozero DFL_ck_alloc_nozero -#define ck_realloc DFL_ck_realloc -#define ck_realloc_block DFL_ck_realloc_block -#define ck_strdup DFL_ck_strdup -#define ck_memdup DFL_ck_memdup -#define ck_memdup_str DFL_ck_memdup_str -#define ck_free DFL_ck_free - -#define alloc_report() - -#else - -/* In debugging mode, we also track allocations to detect memory leaks, and the - flow goes through one more layer of indirection. */ - -/* Alloc tracking data structures: */ - -#define ALLOC_BUCKETS 4096 - -struct TRK_obj { - void *ptr; - char *file, *func; - u32 line; -}; - -#ifdef AFL_MAIN - -struct TRK_obj* TRK[ALLOC_BUCKETS]; -u32 TRK_cnt[ALLOC_BUCKETS]; - -# define alloc_report() TRK_report() - -#else - -extern struct TRK_obj* TRK[ALLOC_BUCKETS]; -extern u32 TRK_cnt[ALLOC_BUCKETS]; - -# define alloc_report() - -#endif /* ^AFL_MAIN */ - -/* Bucket-assigning function for a given pointer: */ - -#define TRKH(_ptr) (((((u32)(_ptr)) >> 16) ^ ((u32)(_ptr))) % ALLOC_BUCKETS) - - -/* Add a new entry to the list of allocated objects. */ - -static inline void TRK_alloc_buf(void* ptr, const char* file, const char* func, - u32 line) { - - u32 i, bucket; - - if (!ptr) return; - - bucket = TRKH(ptr); - - /* Find a free slot in the list of entries for that bucket. */ - - for (i = 0; i < TRK_cnt[bucket]; i++) - - if (!TRK[bucket][i].ptr) { - - TRK[bucket][i].ptr = ptr; - TRK[bucket][i].file = (char*)file; - TRK[bucket][i].func = (char*)func; - TRK[bucket][i].line = line; - return; - - } - - /* No space available - allocate more. */ - - TRK[bucket] = DFL_ck_realloc_block(TRK[bucket], - (TRK_cnt[bucket] + 1) * sizeof(struct TRK_obj)); - - TRK[bucket][i].ptr = ptr; - TRK[bucket][i].file = (char*)file; - TRK[bucket][i].func = (char*)func; - TRK[bucket][i].line = line; - - TRK_cnt[bucket]++; - -} - - -/* Remove entry from the list of allocated objects. */ - -static inline void TRK_free_buf(void* ptr, const char* file, const char* func, - u32 line) { - - u32 i, bucket; - - if (!ptr) return; - - bucket = TRKH(ptr); - - /* Find the element on the list... */ - - for (i = 0; i < TRK_cnt[bucket]; i++) - - if (TRK[bucket][i].ptr == ptr) { - - TRK[bucket][i].ptr = 0; - return; - - } - - WARNF("ALLOC: Attempt to free non-allocated memory in %s (%s:%u)", - func, file, line); - -} - - -/* Do a final report on all non-deallocated objects. */ - -static inline void TRK_report(void) { - - u32 i, bucket; - - fflush(0); - - for (bucket = 0; bucket < ALLOC_BUCKETS; bucket++) - for (i = 0; i < TRK_cnt[bucket]; i++) - if (TRK[bucket][i].ptr) - WARNF("ALLOC: Memory never freed, created in %s (%s:%u)", - TRK[bucket][i].func, TRK[bucket][i].file, TRK[bucket][i].line); - -} - - -/* Simple wrappers for non-debugging functions: */ - -static inline void* TRK_ck_alloc(u32 size, const char* file, const char* func, - u32 line) { - - void* ret = DFL_ck_alloc(size); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - - -static inline void* TRK_ck_realloc(void* orig, u32 size, const char* file, - const char* func, u32 line) { - - void* ret = DFL_ck_realloc(orig, size); - TRK_free_buf(orig, file, func, line); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - - -static inline void* TRK_ck_realloc_block(void* orig, u32 size, const char* file, - const char* func, u32 line) { - - void* ret = DFL_ck_realloc_block(orig, size); - TRK_free_buf(orig, file, func, line); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - - -static inline void* TRK_ck_strdup(u8* str, const char* file, const char* func, - u32 line) { - - void* ret = DFL_ck_strdup(str); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - - -static inline void* TRK_ck_memdup(void* mem, u32 size, const char* file, - const char* func, u32 line) { - - void* ret = DFL_ck_memdup(mem, size); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - - -static inline void* TRK_ck_memdup_str(void* mem, u32 size, const char* file, - const char* func, u32 line) { - - void* ret = DFL_ck_memdup_str(mem, size); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - - -static inline void TRK_ck_free(void* ptr, const char* file, - const char* func, u32 line) { - - TRK_free_buf(ptr, file, func, line); - DFL_ck_free(ptr); - -} - -/* Aliasing user-facing names to tracking functions: */ - -#define ck_alloc(_p1) \ - TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) - -#define ck_alloc_nozero(_p1) \ - TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) - -#define ck_realloc(_p1, _p2) \ - TRK_ck_realloc(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) - -#define ck_realloc_block(_p1, _p2) \ - TRK_ck_realloc_block(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) - -#define ck_strdup(_p1) \ - TRK_ck_strdup(_p1, __FILE__, __FUNCTION__, __LINE__) - -#define ck_memdup(_p1, _p2) \ - TRK_ck_memdup(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) - -#define ck_memdup_str(_p1, _p2) \ - TRK_ck_memdup_str(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) - -#define ck_free(_p1) \ - TRK_ck_free(_p1, __FILE__, __FUNCTION__, __LINE__) - -#endif /* ^!DEBUG_BUILD */ - -#endif /* ! _HAVE_ALLOC_INL_H */ \ No newline at end of file diff --git a/third_party/afl/config.h b/third_party/afl/config.h deleted file mode 100644 index 7ecaa3179..000000000 --- a/third_party/afl/config.h +++ /dev/null @@ -1,350 +0,0 @@ -/* - american fuzzy lop - vaguely configurable bits - ---------------------------------------------- - - Written and maintained by Michal Zalewski - - Copyright 2013, 2014, 2015, 2016 Google Inc. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - */ - -#ifndef _HAVE_CONFIG_H -#define _HAVE_CONFIG_H - -#include "types.h" - -/* Version string: */ - -#define VERSION "2.52b" - -/****************************************************** - * * - * Settings that may be of interest to power users: * - * * - ******************************************************/ - -/* Comment out to disable terminal colors (note that this makes afl-analyze - a lot less nice): */ - -#define USE_COLOR - -/* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */ - -#define FANCY_BOXES - -/* Default timeout for fuzzed code (milliseconds). This is the upper bound, - also used for detecting hangs; the actual value is auto-scaled: */ - -#define EXEC_TIMEOUT 1000 - -/* Timeout rounding factor when auto-scaling (milliseconds): */ - -#define EXEC_TM_ROUND 20 - -/* Default memory limit for child process (MB): */ - -#ifndef __x86_64__ -# define MEM_LIMIT 25 -#else -# define MEM_LIMIT 50 -#endif /* ^!__x86_64__ */ - -/* Default memory limit when running in QEMU mode (MB): */ - -#define MEM_LIMIT_QEMU 200 - -/* Number of calibration cycles per every new test case (and for test - cases that show variable behavior): */ - -#define CAL_CYCLES 8 -#define CAL_CYCLES_LONG 40 - -/* Number of subsequent timeouts before abandoning an input file: */ - -#define TMOUT_LIMIT 250 - -/* Maximum number of unique hangs or crashes to record: */ - -#define KEEP_UNIQUE_HANG 500 -#define KEEP_UNIQUE_CRASH 5000 - -/* Baseline number of random tweaks during a single 'havoc' stage: */ - -#define HAVOC_CYCLES 256 -#define HAVOC_CYCLES_INIT 1024 - -/* Maximum multiplier for the above (should be a power of two, beware - of 32-bit int overflows): */ - -#define HAVOC_MAX_MULT 16 - -/* Absolute minimum number of havoc cycles (after all adjustments): */ - -#define HAVOC_MIN 16 - -/* Maximum stacking for havoc-stage tweaks. The actual value is calculated - like this: - - n = random between 1 and HAVOC_STACK_POW2 - stacking = 2^n - - In other words, the default (n = 7) produces 2, 4, 8, 16, 32, 64, or - 128 stacked tweaks: */ - -#define HAVOC_STACK_POW2 7 - -/* Caps on block sizes for cloning and deletion operations. Each of these - ranges has a 33% probability of getting picked, except for the first - two cycles where smaller blocks are favored: */ - -#define HAVOC_BLK_SMALL 32 -#define HAVOC_BLK_MEDIUM 128 -#define HAVOC_BLK_LARGE 1500 - -/* Extra-large blocks, selected very rarely (<5% of the time): */ - -#define HAVOC_BLK_XL 32768 - -/* Probabilities of skipping non-favored entries in the queue, expressed as - percentages: */ - -#define SKIP_TO_NEW_PROB 99 /* ...when there are new, pending favorites */ -#define SKIP_NFAV_OLD_PROB 95 /* ...no new favs, cur entry already fuzzed */ -#define SKIP_NFAV_NEW_PROB 75 /* ...no new favs, cur entry not fuzzed yet */ - -/* Splicing cycle count: */ - -#define SPLICE_CYCLES 15 - -/* Nominal per-splice havoc cycle length: */ - -#define SPLICE_HAVOC 32 - -/* Maximum offset for integer addition / subtraction stages: */ - -#define ARITH_MAX 35 - -/* Limits for the test case trimmer. The absolute minimum chunk size; and - the starting and ending divisors for chopping up the input file: */ - -#define TRIM_MIN_BYTES 4 -#define TRIM_START_STEPS 16 -#define TRIM_END_STEPS 1024 - -/* Maximum size of input file, in bytes (keep under 100MB): */ - -#define MAX_FILE (1 * 1024 * 1024) - -/* The same, for the test case minimizer: */ - -#define TMIN_MAX_FILE (10 * 1024 * 1024) - -/* Block normalization steps for afl-tmin: */ - -#define TMIN_SET_MIN_SIZE 4 -#define TMIN_SET_STEPS 128 - -/* Maximum dictionary token size (-x), in bytes: */ - -#define MAX_DICT_FILE 128 - -/* Length limits for auto-detected dictionary tokens: */ - -#define MIN_AUTO_EXTRA 3 -#define MAX_AUTO_EXTRA 32 - -/* Maximum number of user-specified dictionary tokens to use in deterministic - steps; past this point, the "extras/user" step will be still carried out, - but with proportionally lower odds: */ - -#define MAX_DET_EXTRAS 200 - -/* Maximum number of auto-extracted dictionary tokens to actually use in fuzzing - (first value), and to keep in memory as candidates. The latter should be much - higher than the former. */ - -#define USE_AUTO_EXTRAS 50 -#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 10) - -/* Scaling factor for the effector map used to skip some of the more - expensive deterministic steps. The actual divisor is set to - 2^EFF_MAP_SCALE2 bytes: */ - -#define EFF_MAP_SCALE2 3 - -/* Minimum input file length at which the effector logic kicks in: */ - -#define EFF_MIN_LEN 128 - -/* Maximum effector density past which everything is just fuzzed - unconditionally (%): */ - -#define EFF_MAX_PERC 90 - -/* UI refresh frequency (Hz): */ - -#define UI_TARGET_HZ 5 - -/* Fuzzer stats file and plot update intervals (sec): */ - -#define STATS_UPDATE_SEC 60 -#define PLOT_UPDATE_SEC 5 - -/* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */ - -#define AVG_SMOOTHING 16 - -/* Sync interval (every n havoc cycles): */ - -#define SYNC_INTERVAL 5 - -/* Output directory reuse grace period (minutes): */ - -#define OUTPUT_GRACE 25 - -/* Uncomment to use simple file names (id_NNNNNN): */ - -// #define SIMPLE_FILES - -/* List of interesting values to use in fuzzing. */ - -#define INTERESTING_8 \ - -128, /* Overflow signed 8-bit when decremented */ \ - -1, /* */ \ - 0, /* */ \ - 1, /* */ \ - 16, /* One-off with common buffer size */ \ - 32, /* One-off with common buffer size */ \ - 64, /* One-off with common buffer size */ \ - 100, /* One-off with common buffer size */ \ - 127 /* Overflow signed 8-bit when incremented */ - -#define INTERESTING_16 \ - -32768, /* Overflow signed 16-bit when decremented */ \ - -129, /* Overflow signed 8-bit */ \ - 128, /* Overflow signed 8-bit */ \ - 255, /* Overflow unsig 8-bit when incremented */ \ - 256, /* Overflow unsig 8-bit */ \ - 512, /* One-off with common buffer size */ \ - 1000, /* One-off with common buffer size */ \ - 1024, /* One-off with common buffer size */ \ - 4096, /* One-off with common buffer size */ \ - 32767 /* Overflow signed 16-bit when incremented */ - -#define INTERESTING_32 \ - -2147483648LL, /* Overflow signed 32-bit when decremented */ \ - -100663046, /* Large negative number (endian-agnostic) */ \ - -32769, /* Overflow signed 16-bit */ \ - 32768, /* Overflow signed 16-bit */ \ - 65535, /* Overflow unsig 16-bit when incremented */ \ - 65536, /* Overflow unsig 16 bit */ \ - 100663045, /* Large positive number (endian-agnostic) */ \ - 2147483647 /* Overflow signed 32-bit when incremented */ - -/*********************************************************** - * * - * Really exotic stuff you probably don't want to touch: * - * * - ***********************************************************/ - -/* Call count interval between reseeding the libc PRNG from /dev/urandom: */ - -#define RESEED_RNG 10000 - -/* Maximum line length passed from GCC to 'as' and used for parsing - configuration files: */ - -#define MAX_LINE 8192 - -/* Environment variable used to pass SHM ID to the called program. */ - -#define SHM_ENV_VAR "__AFL_SHM_ID" - -/* Other less interesting, internal-only variables. */ - -#define CLANG_ENV_VAR "__AFL_CLANG_MODE" -#define AS_LOOP_ENV_VAR "__AFL_AS_LOOPCHECK" -#define PERSIST_ENV_VAR "__AFL_PERSISTENT" -#define DEFER_ENV_VAR "__AFL_DEFER_FORKSRV" - -/* In-code signatures for deferred and persistent mode. */ - -#define PERSIST_SIG "##SIG_AFL_PERSISTENT##" -#define DEFER_SIG "##SIG_AFL_DEFER_FORKSRV##" - -/* Distinctive bitmap signature used to indicate failed execution: */ - -#define EXEC_FAIL_SIG 0xfee1dead - -/* Distinctive exit code used to indicate MSAN trip condition: */ - -#define MSAN_ERROR 86 - -/* Designated file descriptors for forkserver commands (the application will - use FORKSRV_FD and FORKSRV_FD + 1): */ - -#define FORKSRV_FD 198 - -/* Fork server init timeout multiplier: we'll wait the user-selected - timeout plus this much for the fork server to spin up. */ - -#define FORK_WAIT_MULT 10 - -/* Calibration timeout adjustments, to be a bit more generous when resuming - fuzzing sessions or trying to calibrate already-added internal finds. - The first value is a percentage, the other is in milliseconds: */ - -#define CAL_TMOUT_PERC 125 -#define CAL_TMOUT_ADD 50 - -/* Number of chances to calibrate a case before giving up: */ - -#define CAL_CHANCES 3 - -/* Map size for the traced binary (2^MAP_SIZE_POW2). Must be greater than - 2; you probably want to keep it under 18 or so for performance reasons - (adjusting AFL_INST_RATIO when compiling is probably a better way to solve - problems with complex programs). You need to recompile the target binary - after changing this - otherwise, SEGVs may ensue. */ - -#define MAP_SIZE_POW2 16 -#define MAP_SIZE (1 << MAP_SIZE_POW2) - -/* Maximum allocator request size (keep well under INT_MAX): */ - -#define MAX_ALLOC 0x40000000 - -/* A made-up hashing seed: */ - -#define HASH_CONST 0xa5b35705 - -/* Constants for afl-gotcpu to control busy loop timing: */ - -#define CTEST_TARGET_MS 5000 -#define CTEST_CORE_TRG_MS 1000 -#define CTEST_BUSY_CYCLES (10 * 1000 * 1000) - -/* Uncomment this to use inferior block-coverage-based instrumentation. Note - that you need to recompile the target binary for this to have any effect: */ - -// #define COVERAGE_ONLY - -/* Uncomment this to ignore hit counts and output just one bit per tuple. - As with the previous setting, you will need to recompile the target - binary: */ - -// #define SKIP_COUNTS - -/* Uncomment this to use instrumentation data to record newly discovered paths, - but do not use them as seeds for fuzzing. This is useful for conveniently - measuring coverage that could be attained by a "dumb" fuzzing algorithm: */ - -// #define IGNORE_FINDS - -#endif /* ! _HAVE_CONFIG_H */ \ No newline at end of file diff --git a/third_party/afl/debug.h b/third_party/afl/debug.h deleted file mode 100644 index 61f627d9a..000000000 --- a/third_party/afl/debug.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - american fuzzy lop - debug / error handling macros - -------------------------------------------------- - - Written and maintained by Michal Zalewski - - Copyright 2013, 2014, 2015, 2016 Google Inc. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - */ - -#ifndef _HAVE_DEBUG_H -#define _HAVE_DEBUG_H - -#include - -#include "types.h" -#include "config.h" - -/******************* - * Terminal colors * - *******************/ - -#ifdef USE_COLOR - -# define cBLK "\x1b[0;30m" -# define cRED "\x1b[0;31m" -# define cGRN "\x1b[0;32m" -# define cBRN "\x1b[0;33m" -# define cBLU "\x1b[0;34m" -# define cMGN "\x1b[0;35m" -# define cCYA "\x1b[0;36m" -# define cLGR "\x1b[0;37m" -# define cGRA "\x1b[1;90m" -# define cLRD "\x1b[1;91m" -# define cLGN "\x1b[1;92m" -# define cYEL "\x1b[1;93m" -# define cLBL "\x1b[1;94m" -# define cPIN "\x1b[1;95m" -# define cLCY "\x1b[1;96m" -# define cBRI "\x1b[1;97m" -# define cRST "\x1b[0m" - -# define bgBLK "\x1b[40m" -# define bgRED "\x1b[41m" -# define bgGRN "\x1b[42m" -# define bgBRN "\x1b[43m" -# define bgBLU "\x1b[44m" -# define bgMGN "\x1b[45m" -# define bgCYA "\x1b[46m" -# define bgLGR "\x1b[47m" -# define bgGRA "\x1b[100m" -# define bgLRD "\x1b[101m" -# define bgLGN "\x1b[102m" -# define bgYEL "\x1b[103m" -# define bgLBL "\x1b[104m" -# define bgPIN "\x1b[105m" -# define bgLCY "\x1b[106m" -# define bgBRI "\x1b[107m" - -#else - -# define cBLK "" -# define cRED "" -# define cGRN "" -# define cBRN "" -# define cBLU "" -# define cMGN "" -# define cCYA "" -# define cLGR "" -# define cGRA "" -# define cLRD "" -# define cLGN "" -# define cYEL "" -# define cLBL "" -# define cPIN "" -# define cLCY "" -# define cBRI "" -# define cRST "" - -# define bgBLK "" -# define bgRED "" -# define bgGRN "" -# define bgBRN "" -# define bgBLU "" -# define bgMGN "" -# define bgCYA "" -# define bgLGR "" -# define bgGRA "" -# define bgLRD "" -# define bgLGN "" -# define bgYEL "" -# define bgLBL "" -# define bgPIN "" -# define bgLCY "" -# define bgBRI "" - -#endif /* ^USE_COLOR */ - -/************************* - * Box drawing sequences * - *************************/ - -#ifdef FANCY_BOXES - -# define SET_G1 "\x1b)0" /* Set G1 for box drawing */ -# define RESET_G1 "\x1b)B" /* Reset G1 to ASCII */ -# define bSTART "\x0e" /* Enter G1 drawing mode */ -# define bSTOP "\x0f" /* Leave G1 drawing mode */ -# define bH "q" /* Horizontal line */ -# define bV "x" /* Vertical line */ -# define bLT "l" /* Left top corner */ -# define bRT "k" /* Right top corner */ -# define bLB "m" /* Left bottom corner */ -# define bRB "j" /* Right bottom corner */ -# define bX "n" /* Cross */ -# define bVR "t" /* Vertical, branch right */ -# define bVL "u" /* Vertical, branch left */ -# define bHT "v" /* Horizontal, branch top */ -# define bHB "w" /* Horizontal, branch bottom */ - -#else - -# define SET_G1 "" -# define RESET_G1 "" -# define bSTART "" -# define bSTOP "" -# define bH "-" -# define bV "|" -# define bLT "+" -# define bRT "+" -# define bLB "+" -# define bRB "+" -# define bX "+" -# define bVR "+" -# define bVL "+" -# define bHT "+" -# define bHB "+" - -#endif /* ^FANCY_BOXES */ - -/*********************** - * Misc terminal codes * - ***********************/ - -#define TERM_HOME "\x1b[H" -#define TERM_CLEAR TERM_HOME "\x1b[2J" -#define cEOL "\x1b[0K" -#define CURSOR_HIDE "\x1b[?25l" -#define CURSOR_SHOW "\x1b[?25h" - -/************************ - * Debug & error macros * - ************************/ - -/* Just print stuff to the appropriate stream. */ - -#ifdef MESSAGES_TO_STDOUT -# define SAYF(x...) printf(x) -#else -# define SAYF(x...) fprintf(stderr, x) -#endif /* ^MESSAGES_TO_STDOUT */ - -/* Show a prefixed warning. */ - -#define WARNF(x...) do { \ - SAYF(cYEL "[!] " cBRI "WARNING: " cRST x); \ - SAYF(cRST "\n"); \ - } while (0) - -/* Show a prefixed "doing something" message. */ - -#define ACTF(x...) do { \ - SAYF(cLBL "[*] " cRST x); \ - SAYF(cRST "\n"); \ - } while (0) - -/* Show a prefixed "success" message. */ - -#define OKF(x...) do { \ - SAYF(cLGN "[+] " cRST x); \ - SAYF(cRST "\n"); \ - } while (0) - -/* Show a prefixed fatal error message (not used in afl). */ - -#define BADF(x...) do { \ - SAYF(cLRD "\n[-] " cRST x); \ - SAYF(cRST "\n"); \ - } while (0) - -/* Die with a verbose non-OS fatal error message. */ - -#define FATAL(x...) do { \ - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ - cBRI x); \ - SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", \ - __FUNCTION__, __FILE__, __LINE__); \ - exit(1); \ - } while (0) - -/* Die by calling abort() to provide a core dump. */ - -#define ABORT(x...) do { \ - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ - cBRI x); \ - SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", \ - __FUNCTION__, __FILE__, __LINE__); \ - abort(); \ - } while (0) - -/* Die while also including the output of perror(). */ - -#define PFATAL(x...) do { \ - fflush(stdout); \ - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] SYSTEM ERROR : " \ - cBRI x); \ - SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", \ - __FUNCTION__, __FILE__, __LINE__); \ - SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ - exit(1); \ - } while (0) - -/* Die with FAULT() or PFAULT() depending on the value of res (used to - interpret different failure modes for read(), write(), etc). */ - -#define RPFATAL(res, x...) do { \ - if (res < 0) PFATAL(x); else FATAL(x); \ - } while (0) - -/* Error-checking versions of read() and write() that call RPFATAL() as - appropriate. */ - -#define ck_write(fd, buf, len, fn) do { \ - u32 _len = (len); \ - s32 _res = write(fd, buf, _len); \ - if (_res != _len) RPFATAL(_res, "Short write to %s", fn); \ - } while (0) - -#define ck_read(fd, buf, len, fn) do { \ - u32 _len = (len); \ - s32 _res = read(fd, buf, _len); \ - if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \ - } while (0) - -#endif /* ! _HAVE_DEBUG_H */ \ No newline at end of file diff --git a/third_party/afl/hash.h b/third_party/afl/hash.h deleted file mode 100644 index b99362c42..000000000 --- a/third_party/afl/hash.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - american fuzzy lop - hashing function - ------------------------------------- - - The hash32() function is a variant of MurmurHash3, a good - non-cryptosafe hashing function developed by Austin Appleby. - - For simplicity, this variant does *NOT* accept buffer lengths - that are not divisible by 8 bytes. The 32-bit version is otherwise - similar to the original; the 64-bit one is a custom hack with - mostly-unproven properties. - - Austin's original code is public domain. - - Other code written and maintained by Michal Zalewski - - Copyright 2016 Google Inc. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - */ - -#ifndef _HAVE_HASH_H -#define _HAVE_HASH_H - -#include "types.h" - -#ifdef __x86_64__ - -#define ROL64(_x, _r) ((((u64)(_x)) << (_r)) | (((u64)(_x)) >> (64 - (_r)))) - -static inline u32 hash32(const void* key, u32 len, u32 seed) { - - const u64* data = (u64*)key; - u64 h1 = seed ^ len; - - len >>= 3; - - while (len--) { - - u64 k1 = *data++; - - k1 *= 0x87c37b91114253d5ULL; - k1 = ROL64(k1, 31); - k1 *= 0x4cf5ad432745937fULL; - - h1 ^= k1; - h1 = ROL64(h1, 27); - h1 = h1 * 5 + 0x52dce729; - - } - - h1 ^= h1 >> 33; - h1 *= 0xff51afd7ed558ccdULL; - h1 ^= h1 >> 33; - h1 *= 0xc4ceb9fe1a85ec53ULL; - h1 ^= h1 >> 33; - - return h1; - -} - -#else - -#define ROL32(_x, _r) ((((u32)(_x)) << (_r)) | (((u32)(_x)) >> (32 - (_r)))) - -static inline u32 hash32(const void* key, u32 len, u32 seed) { - - const u32* data = (u32*)key; - u32 h1 = seed ^ len; - - len >>= 2; - - while (len--) { - - u32 k1 = *data++; - - k1 *= 0xcc9e2d51; - k1 = ROL32(k1, 15); - k1 *= 0x1b873593; - - h1 ^= k1; - h1 = ROL32(h1, 13); - h1 = h1 * 5 + 0xe6546b64; - - } - - h1 ^= h1 >> 16; - h1 *= 0x85ebca6b; - h1 ^= h1 >> 13; - h1 *= 0xc2b2ae35; - h1 ^= h1 >> 16; - - return h1; - -} - -#endif /* ^__x86_64__ */ - -#endif /* !_HAVE_HASH_H */ \ No newline at end of file diff --git a/third_party/afl/llvm_mode/afl-llvm-rt.o.c b/third_party/afl/llvm_mode/afl-llvm-rt.o.c deleted file mode 100644 index 2c83b954f..000000000 --- a/third_party/afl/llvm_mode/afl-llvm-rt.o.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - american fuzzy lop - LLVM instrumentation bootstrap - --------------------------------------------------- - - Written by Laszlo Szekeres and - Michal Zalewski - - LLVM integration design comes from Laszlo Szekeres. - - Copyright 2015, 2016 Google Inc. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This code is the rewrite of afl-as.h's main_payload. - -*/ - -#include "../config.h" -#include "../types.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* This is a somewhat ugly hack for the experimental 'trace-pc-guard' mode. - Basically, we need to make sure that the forkserver is initialized after - the LLVM-generated runtime initialization pass, not before. */ - -#ifdef USE_TRACE_PC -# define CONST_PRIO 5 -#else -# define CONST_PRIO 0 -#endif /* ^USE_TRACE_PC */ - - -/* Globals needed by the injected instrumentation. The __afl_area_initial region - is used for instrumentation output before __afl_map_shm() has a chance to run. - It will end up as .comm, so it shouldn't be too wasteful. */ - -u8 __afl_area_initial[MAP_SIZE]; -u8* __afl_area_ptr = __afl_area_initial; - -__thread u32 __afl_prev_loc; - - -/* Running in persistent mode? */ - -static u8 is_persistent; - - -/* SHM setup. */ - -static void __afl_map_shm(void) { - - u8 *id_str = getenv(SHM_ENV_VAR); - - /* If we're running under AFL, attach to the appropriate region, replacing the - early-stage __afl_area_initial region that is needed to allow some really - hacky .init code to work correctly in projects such as OpenSSL. */ - - if (id_str) { - - u32 shm_id = atoi(id_str); - - __afl_area_ptr = shmat(shm_id, NULL, 0); - - /* Whooooops. */ - - if (__afl_area_ptr == (void *)-1) _exit(1); - - /* Write something into the bitmap so that even with low AFL_INST_RATIO, - our parent doesn't give up on us. */ - - __afl_area_ptr[0] = 1; - - } - -} - - -/* Fork server logic. */ - -static void __afl_start_forkserver(void) { - - static u8 tmp[4]; - s32 child_pid; - - u8 child_stopped = 0; - - /* Phone home and tell the parent that we're OK. If parent isn't there, - assume we're not running in forkserver mode and just execute program. */ - - if (write(FORKSRV_FD + 1, tmp, 4) != 4) return; - - while (1) { - - u32 was_killed; - int status; - - /* Wait for parent by reading from the pipe. Abort if read fails. */ - - if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); - - /* If we stopped the child in persistent mode, but there was a race - condition and afl-fuzz already issued SIGKILL, write off the old - process. */ - - if (child_stopped && was_killed) { - child_stopped = 0; - if (waitpid(child_pid, &status, 0) < 0) _exit(1); - } - - if (!child_stopped) { - - /* Once woken up, create a clone of our process. */ - - child_pid = fork(); - if (child_pid < 0) _exit(1); - - /* In child process: close fds, resume execution. */ - - if (!child_pid) { - - close(FORKSRV_FD); - close(FORKSRV_FD + 1); - return; - - } - - } else { - - /* Special handling for persistent mode: if the child is alive but - currently stopped, simply restart it with SIGCONT. */ - - kill(child_pid, SIGCONT); - child_stopped = 0; - - } - - /* In parent process: write PID to pipe, then wait for child. */ - - if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) _exit(1); - - if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) - _exit(1); - - /* In persistent mode, the child stops itself with SIGSTOP to indicate - a successful run. In this case, we want to wake it up without forking - again. */ - - if (WIFSTOPPED(status)) child_stopped = 1; - - /* Relay wait status to pipe, then loop back. */ - - if (write(FORKSRV_FD + 1, &status, 4) != 4) _exit(1); - - } - -} - - -/* A simplified persistent mode handler, used as explained in README.llvm. */ - -int __afl_persistent_loop(unsigned int max_cnt) { - - static u8 first_pass = 1; - static u32 cycle_cnt; - - if (first_pass) { - - /* Make sure that every iteration of __AFL_LOOP() starts with a clean slate. - On subsequent calls, the parent will take care of that, but on the first - iteration, it's our job to erase any trace of whatever happened - before the loop. */ - - if (is_persistent) { - - memset(__afl_area_ptr, 0, MAP_SIZE); - __afl_area_ptr[0] = 1; - __afl_prev_loc = 0; - } - - cycle_cnt = max_cnt; - first_pass = 0; - return 1; - - } - - if (is_persistent) { - - if (--cycle_cnt) { - - raise(SIGSTOP); - - __afl_area_ptr[0] = 1; - __afl_prev_loc = 0; - - return 1; - - } else { - - /* When exiting __AFL_LOOP(), make sure that the subsequent code that - follows the loop is not traced. We do that by pivoting back to the - dummy output region. */ - - __afl_area_ptr = __afl_area_initial; - - } - - } - - return 0; - -} - - -/* This one can be called from user code when deferred forkserver mode - is enabled. */ - -void __afl_manual_init(void) { - - static u8 init_done; - - if (!init_done) { - - __afl_map_shm(); - __afl_start_forkserver(); - init_done = 1; - - } - -} - - -/* Proper initialization routine. */ - -__attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) { - - is_persistent = !!getenv(PERSIST_ENV_VAR); - - if (getenv(DEFER_ENV_VAR)) return; - - __afl_manual_init(); - -} - - -/* The following stuff deals with supporting -fsanitize-coverage=trace-pc-guard. - It remains non-operational in the traditional, plugin-backed LLVM mode. - For more info about 'trace-pc-guard', see README.llvm. - - The first function (__sanitizer_cov_trace_pc_guard) is called back on every - edge (as opposed to every basic block). */ - -void __sanitizer_cov_trace_pc_guard(uint32_t* guard) { - __afl_area_ptr[*guard]++; -} - - -/* Init callback. Populates instrumentation IDs. Note that we're using - ID of 0 as a special value to indicate non-instrumented bits. That may - still touch the bitmap, but in a fairly harmless way. */ - -void __sanitizer_cov_trace_pc_guard_init(uint32_t* start, uint32_t* stop) { - - u32 inst_ratio = 100; - u8* x; - - if (start == stop || *start) return; - - x = getenv("AFL_INST_RATIO"); - if (x) inst_ratio = atoi(x); - - if (!inst_ratio || inst_ratio > 100) { - fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n"); - abort(); - } - - /* Make sure that the first element in the range is always set - we use that - to avoid duplicate calls (which can happen as an artifact of the underlying - implementation in LLVM). */ - - *(start++) = R(MAP_SIZE - 1) + 1; - - while (start < stop) { - - if (R(100) < inst_ratio) *start = R(MAP_SIZE - 1) + 1; - else *start = 0; - - start++; - - } - -} \ No newline at end of file diff --git a/third_party/afl/types.h b/third_party/afl/types.h deleted file mode 100644 index 3e2af4b9b..000000000 --- a/third_party/afl/types.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - american fuzzy lop - type definitions and minor macros - ------------------------------------------------------ - - Written and maintained by Michal Zalewski - - Copyright 2013, 2014, 2015 Google Inc. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - */ - -#ifndef _HAVE_TYPES_H -#define _HAVE_TYPES_H - -#include -#include - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; - -/* - - Ugh. There is an unintended compiler / glibc #include glitch caused by - combining the u64 type an %llu in format strings, necessitating a workaround. - - In essence, the compiler is always looking for 'unsigned long long' for %llu. - On 32-bit systems, the u64 type (aliased to uint64_t) is expanded to - 'unsigned long long' in , so everything checks out. - - But on 64-bit systems, it is #ifdef'ed in the same file as 'unsigned long'. - Now, it only happens in circumstances where the type happens to have the - expected bit width, *but* the compiler does not know that... and complains - about 'unsigned long' being unsafe to pass to %llu. - - */ - -#ifdef __x86_64__ -typedef unsigned long long u64; -#else -typedef uint64_t u64; -#endif /* ^__x86_64__ */ - -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; - -#ifndef MIN -# define MIN(_a,_b) ((_a) > (_b) ? (_b) : (_a)) -# define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b)) -#endif /* !MIN */ - -#define SWAP16(_x) ({ \ - u16 _ret = (_x); \ - (u16)((_ret << 8) | (_ret >> 8)); \ - }) - -#define SWAP32(_x) ({ \ - u32 _ret = (_x); \ - (u32)((_ret << 24) | (_ret >> 24) | \ - ((_ret << 8) & 0x00FF0000) | \ - ((_ret >> 8) & 0x0000FF00)); \ - }) - -#ifdef AFL_LLVM_PASS -# define AFL_R(x) (random() % (x)) -#else -# define R(x) (random() % (x)) -#endif /* ^AFL_LLVM_PASS */ - -#define STRINGIFY_INTERNAL(x) #x -#define STRINGIFY(x) STRINGIFY_INTERNAL(x) - -#define MEM_BARRIER() \ - __asm__ volatile("" ::: "memory") - -#define likely(_x) __builtin_expect(!!(_x), 1) -#define unlikely(_x) __builtin_expect(!!(_x), 0) - -#endif /* ! _HAVE_TYPES_H */ \ No newline at end of file diff --git a/third_party/beacon-fuzz/corpora.BUILD b/third_party/beacon-fuzz/corpora.BUILD deleted file mode 100644 index 4d59c4b68..000000000 --- a/third_party/beacon-fuzz/corpora.BUILD +++ /dev/null @@ -1,60 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -filegroup( - name = "all", - srcs = glob(["**"]), -) - -# See: https://github.com/sigp/beacon-fuzz-corpora - -current_version = "0_11_0" - -alias( - name = "current_mainnet_attestation", - actual = ":" + current_version + "_mainnet_attestation", -) - -alias( - name = "current_mainnet_attester_slashing", - actual = ":" + current_version + "_mainnet_attester_slashing", -) - -alias( - name = "current_mainnet_block_header", - actual = ":" + current_version + "_mainnet_block_header", -) - -alias( - name = "current_mainnet_beaconstate", - actual = ":" + current_version + "_mainnet_beaconstate", -) - -alias( - name = "current_mainnet_proposer_slashing", - actual = ":" + current_version + "_mainnet_proposer_slashing", -) - -filegroup( - name = "0_11_0_mainnet_attestation", - srcs = glob(["0-11-0/mainnet/attestation/*"]), -) - -filegroup( - name = "0_11_0_mainnet_attester_slashing", - srcs = glob(["0-11-0/mainnet/attester_slashing/*"]), -) - -filegroup( - name = "0_11_0_mainnet_block_header", - srcs = glob(["0-11-0/mainnet/block_header/*"]), -) - -filegroup( - name = "0_11_0_mainnet_beaconstate", - srcs = glob(["0-11-0/mainnet/beaconstate/*"]), -) - -filegroup( - name = "0_11_0_mainnet_proposer_slashing", - srcs = glob(["0-11-0/mainnet/proposer_slashing/*"]), -) diff --git a/third_party/herumi/bls_eth_go_binary.BUILD b/third_party/herumi/bls_eth_go_binary.BUILD index 0936af163..9ee0fc2af 100644 --- a/third_party/herumi/bls_eth_go_binary.BUILD +++ b/third_party/herumi/bls_eth_go_binary.BUILD @@ -154,7 +154,6 @@ go_library( "@com_github_wealdtech_go_eth2_types_v2//:__pkg__", ], clinkopts = select({ - "@prysm//testing/fuzz:fuzzing_enabled": ["-Wl,--unresolved-symbols=ignore-all", "-fsanitize=address"], "//conditions:default": [], }), ) diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel index 92834bbf8..6c2c34298 100644 --- a/tools/BUILD.bazel +++ b/tools/BUILD.bazel @@ -3,12 +3,6 @@ load("@io_bazel_rules_docker//contrib:passwd.bzl", "passwd_entry", "passwd_file" load("@io_bazel_rules_docker//container:container.bzl", "container_image") load("//tools:build_settings.bzl", "base_image") -sh_binary( - name = "fuzz_wrapper", - srcs = ["fuzz_wrapper.sh"], - tags = ["manual"], -) - ################################################################################ ## Docker images as non-root user ## ################################################################################ diff --git a/tools/fuzz_wrapper.sh b/tools/fuzz_wrapper.sh deleted file mode 100755 index 75a08e30d..000000000 --- a/tools/fuzz_wrapper.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -set -e - -# A wrapper for libfuzz tests that sets test undeclared outputs directory as the first corpus -# which libfuzz will write to and the artifact prefix to write any crashes. - -$1 "$TEST_UNDECLARED_OUTPUTS_DIR" "${@:2}" -artifact_prefix="$TEST_UNDECLARED_OUTPUTS_DIR"/ diff --git a/tools/go/BUILD.bazel b/tools/go/BUILD.bazel index 7a5a5bd6d..e69de29bb 100644 --- a/tools/go/BUILD.bazel +++ b/tools/go/BUILD.bazel @@ -1,6 +0,0 @@ -config_setting( - name = "libfuzz_enabled", - define_values = { - "FUZZING_ENGINE": "libfuzzer", - }, -) diff --git a/tools/go/def.bzl b/tools/go/def.bzl index 115b15abb..ccf0eb1f8 100644 --- a/tools/go/def.bzl +++ b/tools/go/def.bzl @@ -52,19 +52,8 @@ def _go_test_transition_rule(**kwargs): go_test = _go_test_transition_rule(**go_test_kwargs) -def go_library(name, **kwargs): - gc_goopts = [] - - if "gc_goopts" in kwargs: - go_goopts = kwargs["gc_goopts"] - - gc_goopts += select({ - "@prysm//tools/go:libfuzz_enabled": ["-d=libfuzzer,checkptr"], - "//conditions:default": [], - }) - - kwargs["gc_goopts"] = gc_goopts - _go_library(name = name, **kwargs) +# Alias retained for future ease of use. +go_library = _go_library # Maybe download a repository rule, if it doesn't exist already. def maybe(repo_rule, name, **kwargs): @@ -73,13 +62,6 @@ def maybe(repo_rule, name, **kwargs): # A wrapper around go_repository to add gazelle directives. def go_repository(name, **kwargs): - # Some third party go tools may be used by the fuzzing pipeline to generate code. This causes - # an issue when running with --config=fuzz and is not necessary since the dependency is not - # part of the final binary. - if "nofuzz" in kwargs: - kwargs.pop("nofuzz", None) - return maybe(_go_repository, name, **kwargs) - directives = [] if "build_directives" in kwargs: directives = kwargs["build_directives"] diff --git a/tools/go/fuzz.bzl b/tools/go/fuzz.bzl deleted file mode 100644 index d905e44ef..000000000 --- a/tools/go/fuzz.bzl +++ /dev/null @@ -1,233 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_context", "go_rule") -load( - "@io_bazel_rules_go//go/private:providers.bzl", - "GoLibrary", - "INFERRED_PATH", -) -load( - "@io_bazel_rules_go//go/private:mode.bzl", - "LINKMODE_C_ARCHIVE", -) -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -main_tpl = """ -// Generated file. DO NOT EDIT. - -package main -import ( - "unsafe" - target "%s" -) -// #include -import "C" -//export LLVMFuzzerTestOneInput -func LLVMFuzzerTestOneInput(data *C.char, size C.size_t) C.int { - s := make([]byte, size) - copy(s, (*[1 << 30]byte)(unsafe.Pointer(data))[:size:size]) - target.%s(s) - return 0 -} -func main() { -} -""" - -def _gen_fuzz_main_impl(ctx): - if ctx.var.get("gotags") != "libfuzzer": - fail("gotags must be set to libfuzzer. Use --config=fuzz or --config=fuzzit.") - if "libfuzzer" not in ctx.var.get("gc_goopts"): - fail("gc_goopts must be set to -d=libfuzzer. Use --config=fuzz or --config=fuzzit.") - - pkg = ctx.attr.target_pkg - func = ctx.attr.func - - output_file_name = ctx.label.name + "_main.fuzz.go" - output_file = ctx.actions.declare_file(output_file_name) - ctx.actions.write(output_file, main_tpl % (pkg, func)) - return [DefaultInfo(files = depset([output_file]))] - -gen_fuzz_main = rule( - implementation = _gen_fuzz_main_impl, - attrs = { - "target_pkg": attr.string(mandatory = True), - "func": attr.string(mandatory = True), - }, -) - -fuzzer_options_tpl = """[libfuzzer] -max_len=%d -""" - -def _generate_libfuzzer_config(ctx): - output_file_name = ctx.label.name + ".options" - output = fuzzer_options_tpl % ( - ctx.attr.max_len, - ) - output_file = ctx.actions.declare_file(output_file_name) - ctx.actions.write(output_file, output) - return [DefaultInfo(files = depset([output_file]))] - -gen_libfuzzer_config = rule( - implementation = _generate_libfuzzer_config, - attrs = { - "max_len": attr.int(default = 0), - }, -) - -def _upload_to_gcp_impl(ctx): - return [ - DefaultInfo(), - ] - -upload_to_gcp = rule( - implementation = _upload_to_gcp_impl, - attrs = { - "gcp_bucket": attr.string(mandatory = True), - "libfuzzer_bundle": attr.label(mandatory = True), - "afl_bundle": attr.label(mandatory = True), - }, -) - -def go_fuzz_test( - name, - corpus, - corpus_path, - importpath, - func = "Fuzz", - repository = "", - max_len = 0, - gcp_bucket = "gs://builds.prysmaticlabs.appspot.com", - size = "medium", - tags = [], - **kwargs): - go_library( - name = name + "_lib_with_fuzzer", - tags = ["manual"] + tags, - visibility = ["//visibility:private"], - testonly = 1, - importpath = importpath, - gc_goopts = ["-d=libfuzzer"], - **kwargs - ) - gen_fuzz_main( - name = name + "_libfuzz_main", - target_pkg = importpath, - func = func, - tags = ["manual"] + tags, - testonly = 1, - visibility = ["//visibility:private"], - ) - gen_libfuzzer_config( - name = name + "_options", - max_len = max_len, - ) - go_binary( - name = name + "_binary", - srcs = [name + "_libfuzz_main"], - deps = [name + "_lib_with_fuzzer"], - linkmode = LINKMODE_C_ARCHIVE, - cgo = True, - tags = ["manual"] + tags, - visibility = ["//visibility:private"], - gc_goopts = ["-d=libfuzzer"], - testonly = 1, - ) - native.genrule( - name = name, - outs = [name + ".a"], - srcs = [":" + name + "_binary"], - cmd = "cp $< $@", - visibility = kwargs.get("visibility"), - tags = ["manual"] + tags, - testonly = 1, - ) - - if not (corpus.startswith("//") or corpus.startswith(":") or corpus.startswith("@")): - corpus_name = name + "_corpus" - corpus = native.glob([corpus + "/**"]) - native.filegroup( - name = corpus_name, - srcs = corpus, - ) - else: - corpus_name = corpus - - additional_args = [] - if max_len > 0: - additional_args += ["-max_len=%s" % max_len] - - native.cc_test( - name = name + "_with_afl", - linkopts = [ - "-fsanitize=address", - "-fsanitize-coverage=trace-pc-guard", - ], - linkstatic = 1, - testonly = 1, - srcs = [":" + name], - deps = [ - "@herumi_bls_eth_go_binary//:lib", - "//third_party/afl:fuzzing_engine", - ], - tags = ["manual", "fuzzer"] + tags, - ) - - native.genrule( - name = name + "_afl_bundle", - outs = [name + "_afl_bundle.zip"], - srcs = [ - "//third_party/afl:libs", - ":" + name + "_with_afl", - ], - cmd = "cp $(location :" + name + "_with_afl) fuzzer; $(location @bazel_tools//tools/zip:zipper) cf $@ $(locations //third_party/afl:libs) fuzzer", - tools = [ - "@bazel_tools//tools/zip:zipper", - ], - testonly = 1, - tags = ["manual"] + tags, - ) - - native.cc_test( - name = name + "_with_libfuzzer", - linkopts = ["-fsanitize=fuzzer,address"], - copts = ["-fsanitize=fuzzer,address"], - linkstatic = 1, - testonly = 1, - srcs = [":" + name], - deps = ["@herumi_bls_eth_go_binary//:lib"], - tags = ["manual", "fuzzer"] + tags, - args = [ - corpus_path, - "-print_final_stats=1", - "-use_value_profile=1", - "-max_total_time=3540", # One minute early of 3600. - ] + additional_args, - data = [corpus_name], - timeout = "eternal", - ) - - native.genrule( - name = name + "_libfuzzer_bundle", - outs = [name + "_libfuzzer_bundle.zip"], - srcs = [ - ":" + name + "_with_libfuzzer", - ":" + name + "_options", - ], - cmd = "cp $(location :" + name + "_with_libfuzzer) fuzzer; " + - "cp $(location :" + name + "_options) fuzzer.options; " + - "$(location @bazel_tools//tools/zip:zipper) cf $@ fuzzer fuzzer.options", - tools = ["@bazel_tools//tools/zip:zipper"], - testonly = 1, - tags = ["manual"] + tags, - ) - - upload_to_gcp( - name = name + "_uploader", - gcp_bucket = gcp_bucket, - afl_bundle = ":" + name + "_afl_bundle", - libfuzzer_bundle = ":" + name + "_libfuzzer_bundle", - tags = ["manual"] + tags, - )