mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 03:30:35 +00:00
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>
This commit is contained in:
parent
49c73e65a1
commit
7df01feb58
15
.bazelrc
15
.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
|
||||
|
@ -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
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -30,9 +30,5 @@ password.txt
|
||||
# Dist files
|
||||
dist
|
||||
|
||||
# libfuzzer
|
||||
oom-*
|
||||
crash-*
|
||||
|
||||
# deepsource cli
|
||||
bin
|
||||
|
@ -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"],
|
||||
|
10
WORKSPACE
10
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(
|
||||
|
@ -25,7 +25,6 @@ go_library(
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//cmd/beacon-chain:__subpackages__",
|
||||
"//testing/fuzz:__pkg__",
|
||||
"//testing/slasher/simulator:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
|
@ -8,7 +8,6 @@ go_library(
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//testing:__subpackages__",
|
||||
"//testing/fuzz:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//async/event:go_default_library",
|
||||
|
26
beacon-chain/cache/BUILD.bazel
vendored
26
beacon-chain/cache/BUILD.bazel
vendored
@ -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 = [
|
||||
|
2
beacon-chain/cache/active_balance.go
vendored
2
beacon-chain/cache/active_balance.go
vendored
@ -1,4 +1,4 @@
|
||||
// +build !libfuzzer
|
||||
// +build !fuzz
|
||||
|
||||
package cache
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// +build libfuzzer
|
||||
// +build fuzz
|
||||
|
||||
package cache
|
||||
|
||||
|
2
beacon-chain/cache/committee.go
vendored
2
beacon-chain/cache/committee.go
vendored
@ -1,4 +1,4 @@
|
||||
// +build !libfuzzer
|
||||
// +build !fuzz
|
||||
|
||||
package cache
|
||||
|
||||
|
2
beacon-chain/cache/committee_disabled.go
vendored
2
beacon-chain/cache/committee_disabled.go
vendored
@ -1,4 +1,4 @@
|
||||
// +build libfuzzer
|
||||
// +build fuzz
|
||||
|
||||
// This file is used in fuzzer builds to bypass global committee caches.
|
||||
package cache
|
||||
|
2
beacon-chain/cache/proposer_indices.go
vendored
2
beacon-chain/cache/proposer_indices.go
vendored
@ -1,4 +1,4 @@
|
||||
// +build !libfuzzer
|
||||
// +build !fuzz
|
||||
|
||||
package cache
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// +build libfuzzer
|
||||
// +build fuzz
|
||||
|
||||
// This file is used in fuzzer builds to bypass proposer indices caches.
|
||||
package cache
|
||||
|
2
beacon-chain/cache/sync_committee.go
vendored
2
beacon-chain/cache/sync_committee.go
vendored
@ -1,4 +1,4 @@
|
||||
// +build !libfuzzer
|
||||
// +build !fuzz
|
||||
|
||||
package cache
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// +build libfuzzer
|
||||
// +build fuzz
|
||||
|
||||
package cache
|
||||
|
||||
|
@ -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__",
|
||||
|
@ -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__",
|
||||
|
@ -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__",
|
||||
|
@ -13,7 +13,6 @@ go_library(
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//cmd/beacon-chain:__subpackages__",
|
||||
"//testing/fuzz:__pkg__",
|
||||
"//testing/slasher/simulator:__pkg__",
|
||||
"//tools:__subpackages__",
|
||||
],
|
||||
|
@ -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 = [
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -14,7 +14,6 @@ go_library(
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//testing/endtoend:__subpackages__",
|
||||
"//testing/fuzz:__pkg__",
|
||||
"//testing/slasher/simulator:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
|
@ -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",
|
||||
|
@ -36,7 +36,6 @@ go_library(
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//testing/endtoend/evaluators:__pkg__",
|
||||
"//testing/fuzz:__pkg__",
|
||||
"//tools:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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__",
|
||||
|
@ -19,7 +19,6 @@ go_library(
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//testing/endtoend:__subpackages__",
|
||||
"//testing/fuzz:__pkg__",
|
||||
"//testing/slasher/simulator:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
|
@ -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__",
|
||||
|
@ -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__",
|
||||
|
@ -1,5 +1,5 @@
|
||||
//go:build libfuzzer
|
||||
// +build libfuzzer
|
||||
//go:build fuzz
|
||||
// +build fuzz
|
||||
|
||||
package sync
|
||||
|
||||
|
@ -7,6 +7,5 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing",
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//testing/fuzz:__pkg__",
|
||||
],
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// +build blst_disabled libfuzzer
|
||||
// +build blst_disabled fuzz
|
||||
|
||||
package blst
|
||||
|
||||
|
4
deps.bzl
4
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",
|
||||
)
|
||||
|
@ -2,5 +2,5 @@ base:
|
||||
language: go
|
||||
docker_image: golang:latest
|
||||
build_tags:
|
||||
- libfuzzer
|
||||
- fuzz
|
||||
- blst_disabled
|
||||
|
@ -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=()
|
||||
|
@ -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
|
@ -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
|
||||
)
|
@ -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.
|
@ -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
|
||||
}
|
||||
}
|
@ -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,
|
||||
})
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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))
|
||||
}
|
||||
}
|
@ -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"],
|
||||
)
|
@ -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
|
||||
}
|
@ -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)
|
||||
}
|
80
third_party/afl/BUILD.bazel
vendored
80
third_party/afl/BUILD.bazel
vendored
@ -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)
|
||||
""",
|
||||
)
|
BIN
third_party/afl/afl-fuzz
vendored
BIN
third_party/afl/afl-fuzz
vendored
Binary file not shown.
8099
third_party/afl/afl-fuzz.c
vendored
8099
third_party/afl/afl-fuzz.c
vendored
File diff suppressed because it is too large
Load Diff
780
third_party/afl/afl-showmap.c
vendored
780
third_party/afl/afl-showmap.c
vendored
@ -1,780 +0,0 @@
|
||||
/*
|
||||
american fuzzy lop - map display utility
|
||||
----------------------------------------
|
||||
|
||||
Written and maintained by Michal Zalewski <lcamtuf@google.com>
|
||||
|
||||
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 <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
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 <lcamtuf@google.com>\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 <out_dir/queue/fuzz_bitmap. */
|
||||
|
||||
binary_mode = 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
|
||||
if (keep_cores) FATAL("Multiple -c options not supported");
|
||||
keep_cores = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
usage(argv[0]);
|
||||
|
||||
}
|
||||
|
||||
if (optind == argc || !out_file) usage(argv[0]);
|
||||
|
||||
setup_shm();
|
||||
setup_signal_handlers();
|
||||
|
||||
set_up_environment();
|
||||
|
||||
find_binary(argv[optind]);
|
||||
|
||||
if (!quiet_mode) {
|
||||
show_banner();
|
||||
ACTF("Executing '%s'...\n", target_path);
|
||||
}
|
||||
|
||||
detect_file_args(argv + optind);
|
||||
|
||||
if (qemu_mode)
|
||||
use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind);
|
||||
else
|
||||
use_argv = argv + optind;
|
||||
|
||||
run_target(use_argv);
|
||||
|
||||
tcnt = write_results();
|
||||
|
||||
if (!quiet_mode) {
|
||||
|
||||
if (!tcnt) FATAL("No instrumentation detected" cRST);
|
||||
OKF("Captured %u tuples in '%s'." cRST, tcnt, out_file);
|
||||
|
||||
}
|
||||
|
||||
exit(child_crashed * 2 + child_timed_out);
|
||||
|
||||
}
|
277
third_party/afl/afl_driver.cpp
vendored
277
third_party/afl/afl_driver.cpp
vendored
@ -1,277 +0,0 @@
|
||||
//===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* This file allows to fuzz libFuzzer-style target functions
|
||||
(LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode.
|
||||
|
||||
Usage:
|
||||
################################################################################
|
||||
cat << EOF > test_fuzzer.cc
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
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 <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
// 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<void *>(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<char> bytes(length);
|
||||
in.read(bytes.data(), bytes.size());
|
||||
assert(in);
|
||||
LLVMFuzzerTestOneInput(reinterpret_cast<const uint8_t *>(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);
|
||||
}
|
570
third_party/afl/alloc-inl.h
vendored
570
third_party/afl/alloc-inl.h
vendored
@ -1,570 +0,0 @@
|
||||
/*
|
||||
american fuzzy lop - error-checking, memory-zeroing alloc routines
|
||||
------------------------------------------------------------------
|
||||
|
||||
Written and maintained by Michal Zalewski <lcamtuf@google.com>
|
||||
|
||||
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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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 */
|
350
third_party/afl/config.h
vendored
350
third_party/afl/config.h
vendored
@ -1,350 +0,0 @@
|
||||
/*
|
||||
american fuzzy lop - vaguely configurable bits
|
||||
----------------------------------------------
|
||||
|
||||
Written and maintained by Michal Zalewski <lcamtuf@google.com>
|
||||
|
||||
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 */
|
251
third_party/afl/debug.h
vendored
251
third_party/afl/debug.h
vendored
@ -1,251 +0,0 @@
|
||||
/*
|
||||
american fuzzy lop - debug / error handling macros
|
||||
--------------------------------------------------
|
||||
|
||||
Written and maintained by Michal Zalewski <lcamtuf@google.com>
|
||||
|
||||
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 <errno.h>
|
||||
|
||||
#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 */
|
104
third_party/afl/hash.h
vendored
104
third_party/afl/hash.h
vendored
@ -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 <lcamtuf@google.com>
|
||||
|
||||
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 */
|
306
third_party/afl/llvm_mode/afl-llvm-rt.o.c
vendored
306
third_party/afl/llvm_mode/afl-llvm-rt.o.c
vendored
@ -1,306 +0,0 @@
|
||||
/*
|
||||
american fuzzy lop - LLVM instrumentation bootstrap
|
||||
---------------------------------------------------
|
||||
|
||||
Written by Laszlo Szekeres <lszekeres@google.com> and
|
||||
Michal Zalewski <lcamtuf@google.com>
|
||||
|
||||
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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* 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++;
|
||||
|
||||
}
|
||||
|
||||
}
|
86
third_party/afl/types.h
vendored
86
third_party/afl/types.h
vendored
@ -1,86 +0,0 @@
|
||||
/*
|
||||
american fuzzy lop - type definitions and minor macros
|
||||
------------------------------------------------------
|
||||
|
||||
Written and maintained by Michal Zalewski <lcamtuf@google.com>
|
||||
|
||||
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 <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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 <bits/types.h>, 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 */
|
60
third_party/beacon-fuzz/corpora.BUILD
vendored
60
third_party/beacon-fuzz/corpora.BUILD
vendored
@ -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/*"]),
|
||||
)
|
1
third_party/herumi/bls_eth_go_binary.BUILD
vendored
1
third_party/herumi/bls_eth_go_binary.BUILD
vendored
@ -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": [],
|
||||
}),
|
||||
)
|
||||
|
@ -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 ##
|
||||
################################################################################
|
||||
|
@ -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"/
|
@ -1,6 +0,0 @@
|
||||
config_setting(
|
||||
name = "libfuzz_enabled",
|
||||
define_values = {
|
||||
"FUZZING_ENGINE": "libfuzzer",
|
||||
},
|
||||
)
|
@ -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"]
|
||||
|
@ -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 <stdint.h>
|
||||
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,
|
||||
)
|
Loading…
Reference in New Issue
Block a user