From 8651eed65278b1f592538b4fc95d9e407c69c9cb Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Thu, 9 May 2024 15:25:44 +0100 Subject: [PATCH 01/25] Initial integration of PrescientFuzz --- fuzzers/prescientfuzz/builder.Dockerfile | 49 ++++++++++++++ fuzzers/prescientfuzz/description.md | 8 +++ fuzzers/prescientfuzz/fuzzer.py | 83 ++++++++++++++++++++++++ fuzzers/prescientfuzz/runner.Dockerfile | 25 +++++++ 4 files changed, 165 insertions(+) create mode 100644 fuzzers/prescientfuzz/builder.Dockerfile create mode 100644 fuzzers/prescientfuzz/description.md create mode 100755 fuzzers/prescientfuzz/fuzzer.py create mode 100644 fuzzers/prescientfuzz/runner.Dockerfile diff --git a/fuzzers/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz/builder.Dockerfile new file mode 100644 index 000000000..d06c839f5 --- /dev/null +++ b/fuzzers/prescientfuzz/builder.Dockerfile @@ -0,0 +1,49 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ + rm /rustup.sh + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + cargo && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz +RUN cd PrescientFuzz && git checkout PrescientFuzz + +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz/description.md b/fuzzers/prescientfuzz/description.md new file mode 100644 index 000000000..452b0e374 --- /dev/null +++ b/fuzzers/prescientfuzz/description.md @@ -0,0 +1,8 @@ +# PrescientFuzz + +based on libafl fuzzer instance + - persistent mode + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz/fuzzer.py b/fuzzers/prescientfuzz/fuzzer.py new file mode 100755 index 000000000..6266eb30f --- /dev/null +++ b/fuzzers/prescientfuzz/fuzzer.py @@ -0,0 +1,83 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import sys +import subprocess +import shutil +from pathlib import Path + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): # pylint: disable=too-many-branches,too-many-statements + """Build benchmark.""" + os.environ[ + 'CC'] = '/PrescientFuzz/fuzzers/fuzzbench/target/release-fuzzbench/libafl_cc' + os.environ[ + 'CXX'] = '/PrescientFuzz/fuzzers/fuzzbench/target/release-fuzzbench/libafl_cxx' + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file + utils.build_benchmark() + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus]) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz/runner.Dockerfile b/fuzzers/prescientfuzz/runner.Dockerfile new file mode 100644 index 000000000..1a023b81e --- /dev/null +++ b/fuzzers/prescientfuzz/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 From 40063b4078bfbd8f432b2a9b76743dda504e49c7 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Thu, 9 May 2024 15:36:53 +0100 Subject: [PATCH 02/25] Fix typo (paths r hard) --- fuzzers/prescientfuzz/builder.Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fuzzers/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz/builder.Dockerfile index d06c839f5..d7f93c567 100644 --- a/fuzzers/prescientfuzz/builder.Dockerfile +++ b/fuzzers/prescientfuzz/builder.Dockerfile @@ -32,8 +32,8 @@ RUN apt-get update && \ PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make # Download PrescientFuzz -RUN git clone https://github.com/DanBlackwell/PrescientFuzz -RUN cd PrescientFuzz && git checkout PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +RUN cd /PrescientFuzz && git checkout PrescientFuzz # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ From c8ad8e17a201fbd5956af42f7d6e204cb227107e Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Thu, 9 May 2024 17:26:56 +0100 Subject: [PATCH 03/25] Actually run make presubmit this time... --- fuzzers/prescientfuzz/fuzzer.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fuzzers/prescientfuzz/fuzzer.py b/fuzzers/prescientfuzz/fuzzer.py index 6266eb30f..fdf942217 100755 --- a/fuzzers/prescientfuzz/fuzzer.py +++ b/fuzzers/prescientfuzz/fuzzer.py @@ -17,7 +17,6 @@ import os import sys import subprocess -import shutil from pathlib import Path from fuzzers import utils @@ -41,12 +40,12 @@ def prepare_fuzz_environment(input_corpus): utils.create_seed_file_for_empty_corpus(input_corpus) -def build(): # pylint: disable=too-many-branches,too-many-statements +def build(): """Build benchmark.""" - os.environ[ - 'CC'] = '/PrescientFuzz/fuzzers/fuzzbench/target/release-fuzzbench/libafl_cc' - os.environ[ - 'CXX'] = '/PrescientFuzz/fuzzers/fuzzbench/target/release-fuzzbench/libafl_cxx' + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' @@ -63,6 +62,7 @@ def build(): # pylint: disable=too-many-branches,too-many-statements os.environ['AFL_LLVM_CFG_FILE'] = cfg_file utils.build_benchmark() + def fuzz(input_corpus, output_corpus, target_binary): """Run fuzzer.""" prepare_fuzz_environment(input_corpus) From 31a157eb25a22b4a8eb5d198c1011452d3cf1176 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Fri, 10 May 2024 09:21:21 +0100 Subject: [PATCH 04/25] Add trivial change to gcbrun --- service/gcbrun_experiment.py | 1 + 1 file changed, 1 insertion(+) diff --git a/service/gcbrun_experiment.py b/service/gcbrun_experiment.py index f19ab493d..36892f9a0 100644 --- a/service/gcbrun_experiment.py +++ b/service/gcbrun_experiment.py @@ -16,6 +16,7 @@ """Entrypoint for gcbrun into run_experiment. This script will get the command from the last PR comment containing "/gcbrun" and pass it to run_experiment.py which will run an experiment.""" +# Please don't break the linter import logging import os From 2af753f0172b17fb72f12cf1dac342a4833b4db1 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Thu, 16 May 2024 09:08:42 +0100 Subject: [PATCH 05/25] Bump PrescientFuzz commit --- fuzzers/prescientfuzz/builder.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuzzers/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz/builder.Dockerfile index d7f93c567..c81bb09be 100644 --- a/fuzzers/prescientfuzz/builder.Dockerfile +++ b/fuzzers/prescientfuzz/builder.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git checkout PrescientFuzz +RUN cd /PrescientFuzz && git checkout f0512a2c68be63b19524f68e0192128e7854fb04 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ From 65326a86cee7f87332e5ba640393529360219996 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Thu, 16 May 2024 14:50:44 +0100 Subject: [PATCH 06/25] Needed to fetch first... --- fuzzers/prescientfuzz/builder.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuzzers/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz/builder.Dockerfile index c81bb09be..44a571587 100644 --- a/fuzzers/prescientfuzz/builder.Dockerfile +++ b/fuzzers/prescientfuzz/builder.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git checkout f0512a2c68be63b19524f68e0192128e7854fb04 +RUN cd /PrescientFuzz && git fetch && git checkout f0512a2c68be63b19524f68e0192128e7854fb04 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ From e3282245c5382d6554487b20cfd54a3c237874d1 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Fri, 17 May 2024 10:40:49 +0100 Subject: [PATCH 07/25] Fix error in resizing map --- fuzzers/prescientfuzz/builder.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuzzers/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz/builder.Dockerfile index 44a571587..e8536717a 100644 --- a/fuzzers/prescientfuzz/builder.Dockerfile +++ b/fuzzers/prescientfuzz/builder.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout f0512a2c68be63b19524f68e0192128e7854fb04 +RUN cd /PrescientFuzz && git fetch && git checkout 8ae1b88b8509eb9395351badca557705e5ec5619 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ From 7ef3691ee8c43ebb9d64117d79dd698da6098d45 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Mon, 20 May 2024 14:46:52 +0100 Subject: [PATCH 08/25] Added experimental setups for backoff --- .../builder.Dockerfile | 49 +++++++++++ .../description.md | 8 ++ .../prescientfuzz_0_99999_backoff/fuzzer.py | 83 +++++++++++++++++++ .../runner.Dockerfile | 25 ++++++ .../builder.Dockerfile | 49 +++++++++++ .../description.md | 8 ++ .../prescientfuzz_0_9999_backoff/fuzzer.py | 83 +++++++++++++++++++ .../runner.Dockerfile | 25 ++++++ .../builder.Dockerfile | 49 +++++++++++ .../description.md | 8 ++ fuzzers/prescientfuzz_0_999_backoff/fuzzer.py | 83 +++++++++++++++++++ .../runner.Dockerfile | 25 ++++++ .../builder.Dockerfile | 49 +++++++++++ .../prescientfuzz_no_backoff/description.md | 8 ++ fuzzers/prescientfuzz_no_backoff/fuzzer.py | 83 +++++++++++++++++++ .../runner.Dockerfile | 25 ++++++ 16 files changed, 660 insertions(+) create mode 100644 fuzzers/prescientfuzz_0_99999_backoff/builder.Dockerfile create mode 100644 fuzzers/prescientfuzz_0_99999_backoff/description.md create mode 100755 fuzzers/prescientfuzz_0_99999_backoff/fuzzer.py create mode 100644 fuzzers/prescientfuzz_0_99999_backoff/runner.Dockerfile create mode 100644 fuzzers/prescientfuzz_0_9999_backoff/builder.Dockerfile create mode 100644 fuzzers/prescientfuzz_0_9999_backoff/description.md create mode 100755 fuzzers/prescientfuzz_0_9999_backoff/fuzzer.py create mode 100644 fuzzers/prescientfuzz_0_9999_backoff/runner.Dockerfile create mode 100644 fuzzers/prescientfuzz_0_999_backoff/builder.Dockerfile create mode 100644 fuzzers/prescientfuzz_0_999_backoff/description.md create mode 100755 fuzzers/prescientfuzz_0_999_backoff/fuzzer.py create mode 100644 fuzzers/prescientfuzz_0_999_backoff/runner.Dockerfile create mode 100644 fuzzers/prescientfuzz_no_backoff/builder.Dockerfile create mode 100644 fuzzers/prescientfuzz_no_backoff/description.md create mode 100755 fuzzers/prescientfuzz_no_backoff/fuzzer.py create mode 100644 fuzzers/prescientfuzz_no_backoff/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_0_99999_backoff/builder.Dockerfile b/fuzzers/prescientfuzz_0_99999_backoff/builder.Dockerfile new file mode 100644 index 000000000..4fc30402f --- /dev/null +++ b/fuzzers/prescientfuzz_0_99999_backoff/builder.Dockerfile @@ -0,0 +1,49 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ + rm /rustup.sh + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + cargo && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +RUN cd /PrescientFuzz && git fetch && git checkout 9f61f245be96f705279d1bc48057ccc4c6e763ba + +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_0_99999_backoff/description.md b/fuzzers/prescientfuzz_0_99999_backoff/description.md new file mode 100644 index 000000000..452b0e374 --- /dev/null +++ b/fuzzers/prescientfuzz_0_99999_backoff/description.md @@ -0,0 +1,8 @@ +# PrescientFuzz + +based on libafl fuzzer instance + - persistent mode + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_0_99999_backoff/fuzzer.py b/fuzzers/prescientfuzz_0_99999_backoff/fuzzer.py new file mode 100755 index 000000000..801a40b67 --- /dev/null +++ b/fuzzers/prescientfuzz_0_99999_backoff/fuzzer.py @@ -0,0 +1,83 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import sys +import subprocess +from pathlib import Path + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): + """Build benchmark.""" + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.99999']) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_0_99999_backoff/runner.Dockerfile b/fuzzers/prescientfuzz_0_99999_backoff/runner.Dockerfile new file mode 100644 index 000000000..1a023b81e --- /dev/null +++ b/fuzzers/prescientfuzz_0_99999_backoff/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_0_9999_backoff/builder.Dockerfile b/fuzzers/prescientfuzz_0_9999_backoff/builder.Dockerfile new file mode 100644 index 000000000..4fc30402f --- /dev/null +++ b/fuzzers/prescientfuzz_0_9999_backoff/builder.Dockerfile @@ -0,0 +1,49 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ + rm /rustup.sh + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + cargo && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +RUN cd /PrescientFuzz && git fetch && git checkout 9f61f245be96f705279d1bc48057ccc4c6e763ba + +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_0_9999_backoff/description.md b/fuzzers/prescientfuzz_0_9999_backoff/description.md new file mode 100644 index 000000000..452b0e374 --- /dev/null +++ b/fuzzers/prescientfuzz_0_9999_backoff/description.md @@ -0,0 +1,8 @@ +# PrescientFuzz + +based on libafl fuzzer instance + - persistent mode + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_0_9999_backoff/fuzzer.py b/fuzzers/prescientfuzz_0_9999_backoff/fuzzer.py new file mode 100755 index 000000000..5f2dfa95f --- /dev/null +++ b/fuzzers/prescientfuzz_0_9999_backoff/fuzzer.py @@ -0,0 +1,83 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import sys +import subprocess +from pathlib import Path + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): + """Build benchmark.""" + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_0_9999_backoff/runner.Dockerfile b/fuzzers/prescientfuzz_0_9999_backoff/runner.Dockerfile new file mode 100644 index 000000000..1a023b81e --- /dev/null +++ b/fuzzers/prescientfuzz_0_9999_backoff/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_0_999_backoff/builder.Dockerfile b/fuzzers/prescientfuzz_0_999_backoff/builder.Dockerfile new file mode 100644 index 000000000..4fc30402f --- /dev/null +++ b/fuzzers/prescientfuzz_0_999_backoff/builder.Dockerfile @@ -0,0 +1,49 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ + rm /rustup.sh + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + cargo && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +RUN cd /PrescientFuzz && git fetch && git checkout 9f61f245be96f705279d1bc48057ccc4c6e763ba + +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_0_999_backoff/description.md b/fuzzers/prescientfuzz_0_999_backoff/description.md new file mode 100644 index 000000000..452b0e374 --- /dev/null +++ b/fuzzers/prescientfuzz_0_999_backoff/description.md @@ -0,0 +1,8 @@ +# PrescientFuzz + +based on libafl fuzzer instance + - persistent mode + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_0_999_backoff/fuzzer.py b/fuzzers/prescientfuzz_0_999_backoff/fuzzer.py new file mode 100755 index 000000000..c1f354299 --- /dev/null +++ b/fuzzers/prescientfuzz_0_999_backoff/fuzzer.py @@ -0,0 +1,83 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import sys +import subprocess +from pathlib import Path + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): + """Build benchmark.""" + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.999']) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_0_999_backoff/runner.Dockerfile b/fuzzers/prescientfuzz_0_999_backoff/runner.Dockerfile new file mode 100644 index 000000000..1a023b81e --- /dev/null +++ b/fuzzers/prescientfuzz_0_999_backoff/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_no_backoff/builder.Dockerfile b/fuzzers/prescientfuzz_no_backoff/builder.Dockerfile new file mode 100644 index 000000000..4fc30402f --- /dev/null +++ b/fuzzers/prescientfuzz_no_backoff/builder.Dockerfile @@ -0,0 +1,49 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ + rm /rustup.sh + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + cargo && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +RUN cd /PrescientFuzz && git fetch && git checkout 9f61f245be96f705279d1bc48057ccc4c6e763ba + +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_no_backoff/description.md b/fuzzers/prescientfuzz_no_backoff/description.md new file mode 100644 index 000000000..452b0e374 --- /dev/null +++ b/fuzzers/prescientfuzz_no_backoff/description.md @@ -0,0 +1,8 @@ +# PrescientFuzz + +based on libafl fuzzer instance + - persistent mode + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_no_backoff/fuzzer.py b/fuzzers/prescientfuzz_no_backoff/fuzzer.py new file mode 100755 index 000000000..3b91db7c3 --- /dev/null +++ b/fuzzers/prescientfuzz_no_backoff/fuzzer.py @@ -0,0 +1,83 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import sys +import subprocess +from pathlib import Path + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): + """Build benchmark.""" + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '1.0']) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_no_backoff/runner.Dockerfile b/fuzzers/prescientfuzz_no_backoff/runner.Dockerfile new file mode 100644 index 000000000..1a023b81e --- /dev/null +++ b/fuzzers/prescientfuzz_no_backoff/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 From 2a67a980f53a99a6e6108994ec241cd65a9d882e Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Tue, 21 May 2024 10:24:58 +0100 Subject: [PATCH 09/25] Update experiment-config.yaml --- .../builder.Dockerfile | 0 .../{prescientfuzz => prescientfuzz_no_filter}/description.md | 0 fuzzers/{prescientfuzz => prescientfuzz_no_filter}/fuzzer.py | 0 .../runner.Dockerfile | 0 service/experiment-config.yaml | 4 ++-- 5 files changed, 2 insertions(+), 2 deletions(-) rename fuzzers/{prescientfuzz => prescientfuzz_no_filter}/builder.Dockerfile (100%) rename fuzzers/{prescientfuzz => prescientfuzz_no_filter}/description.md (100%) rename fuzzers/{prescientfuzz => prescientfuzz_no_filter}/fuzzer.py (100%) rename fuzzers/{prescientfuzz => prescientfuzz_no_filter}/runner.Dockerfile (100%) diff --git a/fuzzers/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz_no_filter/builder.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz/builder.Dockerfile rename to fuzzers/prescientfuzz_no_filter/builder.Dockerfile diff --git a/fuzzers/prescientfuzz/description.md b/fuzzers/prescientfuzz_no_filter/description.md similarity index 100% rename from fuzzers/prescientfuzz/description.md rename to fuzzers/prescientfuzz_no_filter/description.md diff --git a/fuzzers/prescientfuzz/fuzzer.py b/fuzzers/prescientfuzz_no_filter/fuzzer.py similarity index 100% rename from fuzzers/prescientfuzz/fuzzer.py rename to fuzzers/prescientfuzz_no_filter/fuzzer.py diff --git a/fuzzers/prescientfuzz/runner.Dockerfile b/fuzzers/prescientfuzz_no_filter/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz/runner.Dockerfile rename to fuzzers/prescientfuzz_no_filter/runner.Dockerfile diff --git a/service/experiment-config.yaml b/service/experiment-config.yaml index b9acb09f8..9ed2887d0 100644 --- a/service/experiment-config.yaml +++ b/service/experiment-config.yaml @@ -2,7 +2,7 @@ # Unless you are a fuzzbench maintainer running this service, this # will not work with your setup. -trials: 20 +trials: 10 max_total_time: 82800 # 23 hours, the default time for preemptible experiments. cloud_project: fuzzbench docker_registry: gcr.io/fuzzbench @@ -15,7 +15,7 @@ preemptible_runners: true # This experiment should generate a report that is combined with other public # "production" experiments. -merge_with_nonprivate: true +merge_with_nonprivate: false # This experiment should be merged with other reports in later experiments. private: false From 4a4626553c31a3159175adb18c9893f3825d1f29 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Wed, 22 May 2024 12:23:46 +0100 Subject: [PATCH 10/25] Added fuzzer setups for evaluation --- .../builder.Dockerfile | 2 +- .../description.md | 0 .../fuzzer.py | 3 + .../runner.Dockerfile | 0 .../builder.Dockerfile | 50 +++++++++++ .../description.md | 0 .../fuzzer.py | 5 +- fuzzers/prescientfuzz_depth_const_1/patch | 13 +++ .../prescientfuzz}/builder.Dockerfile | 2 +- .../prescientfuzz}/description.md | 0 .../prescientfuzz}/fuzzer.py | 5 +- .../prescientfuzz}/runner.Dockerfile | 0 .../runner.Dockerfile | 0 .../builder.Dockerfile | 50 +++++++++++ .../description.md | 0 .../fuzzer.py | 5 +- fuzzers/prescientfuzz_depth_squared/patch | 13 +++ .../prescientfuzz}/builder.Dockerfile | 2 +- .../prescientfuzz}/description.md | 0 .../prescientfuzz/fuzzer.py | 86 +++++++++++++++++++ .../prescientfuzz}/runner.Dockerfile | 0 .../runner.Dockerfile | 0 fuzzers/prescientfuzz_nn/builder.Dockerfile | 50 +++++++++++ fuzzers/prescientfuzz_nn/description.md | 8 ++ fuzzers/prescientfuzz_nn/fuzzer.py | 86 +++++++++++++++++++ fuzzers/prescientfuzz_nn/patch | 13 +++ .../prescientfuzz}/builder.Dockerfile | 2 +- .../prescientfuzz/description.md | 8 ++ .../prescientfuzz_nn/prescientfuzz/fuzzer.py | 86 +++++++++++++++++++ .../prescientfuzz/runner.Dockerfile | 25 ++++++ fuzzers/prescientfuzz_nn/runner.Dockerfile | 25 ++++++ .../builder.Dockerfile | 49 ----------- fuzzers/prescientfuzz_no_filter/fuzzer.py | 83 ------------------ 33 files changed, 532 insertions(+), 139 deletions(-) rename fuzzers/{prescientfuzz_0_99999_backoff => prescientfuzz}/builder.Dockerfile (95%) rename fuzzers/{prescientfuzz_0_99999_backoff => prescientfuzz}/description.md (100%) rename fuzzers/{prescientfuzz_0_9999_backoff => prescientfuzz}/fuzzer.py (96%) rename fuzzers/{prescientfuzz_0_99999_backoff => prescientfuzz}/runner.Dockerfile (100%) create mode 100644 fuzzers/prescientfuzz_depth_const_1/builder.Dockerfile rename fuzzers/{prescientfuzz_0_9999_backoff => prescientfuzz_depth_const_1}/description.md (100%) rename fuzzers/{prescientfuzz_0_999_backoff => prescientfuzz_depth_const_1}/fuzzer.py (96%) create mode 100644 fuzzers/prescientfuzz_depth_const_1/patch rename fuzzers/{prescientfuzz_0_999_backoff => prescientfuzz_depth_const_1/prescientfuzz}/builder.Dockerfile (95%) rename fuzzers/{prescientfuzz_0_999_backoff => prescientfuzz_depth_const_1/prescientfuzz}/description.md (100%) rename fuzzers/{prescientfuzz_0_99999_backoff => prescientfuzz_depth_const_1/prescientfuzz}/fuzzer.py (96%) rename fuzzers/{prescientfuzz_0_9999_backoff => prescientfuzz_depth_const_1/prescientfuzz}/runner.Dockerfile (100%) rename fuzzers/{prescientfuzz_0_999_backoff => prescientfuzz_depth_const_1}/runner.Dockerfile (100%) create mode 100644 fuzzers/prescientfuzz_depth_squared/builder.Dockerfile rename fuzzers/{prescientfuzz_no_backoff => prescientfuzz_depth_squared}/description.md (100%) rename fuzzers/{prescientfuzz_no_backoff => prescientfuzz_depth_squared}/fuzzer.py (96%) create mode 100644 fuzzers/prescientfuzz_depth_squared/patch rename fuzzers/{prescientfuzz_0_9999_backoff => prescientfuzz_depth_squared/prescientfuzz}/builder.Dockerfile (95%) rename fuzzers/{prescientfuzz_no_filter => prescientfuzz_depth_squared/prescientfuzz}/description.md (100%) create mode 100755 fuzzers/prescientfuzz_depth_squared/prescientfuzz/fuzzer.py rename fuzzers/{prescientfuzz_no_backoff => prescientfuzz_depth_squared/prescientfuzz}/runner.Dockerfile (100%) rename fuzzers/{prescientfuzz_no_filter => prescientfuzz_depth_squared}/runner.Dockerfile (100%) create mode 100644 fuzzers/prescientfuzz_nn/builder.Dockerfile create mode 100644 fuzzers/prescientfuzz_nn/description.md create mode 100755 fuzzers/prescientfuzz_nn/fuzzer.py create mode 100644 fuzzers/prescientfuzz_nn/patch rename fuzzers/{prescientfuzz_no_backoff => prescientfuzz_nn/prescientfuzz}/builder.Dockerfile (95%) create mode 100644 fuzzers/prescientfuzz_nn/prescientfuzz/description.md create mode 100755 fuzzers/prescientfuzz_nn/prescientfuzz/fuzzer.py create mode 100644 fuzzers/prescientfuzz_nn/prescientfuzz/runner.Dockerfile create mode 100644 fuzzers/prescientfuzz_nn/runner.Dockerfile delete mode 100644 fuzzers/prescientfuzz_no_filter/builder.Dockerfile delete mode 100755 fuzzers/prescientfuzz_no_filter/fuzzer.py diff --git a/fuzzers/prescientfuzz_0_99999_backoff/builder.Dockerfile b/fuzzers/prescientfuzz/builder.Dockerfile similarity index 95% rename from fuzzers/prescientfuzz_0_99999_backoff/builder.Dockerfile rename to fuzzers/prescientfuzz/builder.Dockerfile index 4fc30402f..2449a3b14 100644 --- a/fuzzers/prescientfuzz_0_99999_backoff/builder.Dockerfile +++ b/fuzzers/prescientfuzz/builder.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 9f61f245be96f705279d1bc48057ccc4c6e763ba +RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz_0_99999_backoff/description.md b/fuzzers/prescientfuzz/description.md similarity index 100% rename from fuzzers/prescientfuzz_0_99999_backoff/description.md rename to fuzzers/prescientfuzz/description.md diff --git a/fuzzers/prescientfuzz_0_9999_backoff/fuzzer.py b/fuzzers/prescientfuzz/fuzzer.py similarity index 96% rename from fuzzers/prescientfuzz_0_9999_backoff/fuzzer.py rename to fuzzers/prescientfuzz/fuzzer.py index 5f2dfa95f..4f4601c91 100755 --- a/fuzzers/prescientfuzz_0_9999_backoff/fuzzer.py +++ b/fuzzers/prescientfuzz/fuzzer.py @@ -55,6 +55,9 @@ def build(): utils.append_flags('CXXFLAGS', cflags) utils.append_flags('LDFLAGS', cflags) + os.environ['RANLIB'] = 'llvm-ranlib' + os.environ['AR'] = 'llvm-ar' + os.environ['AS'] = 'llvm-as' os.environ['FUZZER_LIB'] = '/stub_rt.a' build_directory = os.environ['OUT'] cfg_file = build_directory + '/afl_cfg.bin' diff --git a/fuzzers/prescientfuzz_0_99999_backoff/runner.Dockerfile b/fuzzers/prescientfuzz/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_0_99999_backoff/runner.Dockerfile rename to fuzzers/prescientfuzz/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_depth_const_1/builder.Dockerfile b/fuzzers/prescientfuzz_depth_const_1/builder.Dockerfile new file mode 100644 index 000000000..954583e89 --- /dev/null +++ b/fuzzers/prescientfuzz_depth_const_1/builder.Dockerfile @@ -0,0 +1,50 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ + rm /rustup.sh + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + cargo && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +COPY ./patch /PrescientFuzz/patch +RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 && git apply patch + +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_0_9999_backoff/description.md b/fuzzers/prescientfuzz_depth_const_1/description.md similarity index 100% rename from fuzzers/prescientfuzz_0_9999_backoff/description.md rename to fuzzers/prescientfuzz_depth_const_1/description.md diff --git a/fuzzers/prescientfuzz_0_999_backoff/fuzzer.py b/fuzzers/prescientfuzz_depth_const_1/fuzzer.py similarity index 96% rename from fuzzers/prescientfuzz_0_999_backoff/fuzzer.py rename to fuzzers/prescientfuzz_depth_const_1/fuzzer.py index c1f354299..4f4601c91 100755 --- a/fuzzers/prescientfuzz_0_999_backoff/fuzzer.py +++ b/fuzzers/prescientfuzz_depth_const_1/fuzzer.py @@ -55,6 +55,9 @@ def build(): utils.append_flags('CXXFLAGS', cflags) utils.append_flags('LDFLAGS', cflags) + os.environ['RANLIB'] = 'llvm-ranlib' + os.environ['AR'] = 'llvm-ar' + os.environ['AS'] = 'llvm-as' os.environ['FUZZER_LIB'] = '/stub_rt.a' build_directory = os.environ['OUT'] cfg_file = build_directory + '/afl_cfg.bin' @@ -76,7 +79,7 @@ def fuzz(input_corpus, output_corpus, target_binary): command += (['-c', cfg_file]) else: sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.999']) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) fuzzer_env = os.environ.copy() fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' print(command) diff --git a/fuzzers/prescientfuzz_depth_const_1/patch b/fuzzers/prescientfuzz_depth_const_1/patch new file mode 100644 index 000000000..1ba9ef931 --- /dev/null +++ b/fuzzers/prescientfuzz_depth_const_1/patch @@ -0,0 +1,13 @@ +diff --git a/libafl/src/schedulers/probabilistic_sampling.rs b/libafl/src/schedulers/probabilistic_sampling.rs +index fd552a3d..c275d211 100644 +--- a/libafl/src/schedulers/probabilistic_sampling.rs ++++ b/libafl/src/schedulers/probabilistic_sampling.rs +@@ -294,7 +294,7 @@ where + let rarity = 1f64 / *freq.unwrap() as f64; + let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); + if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } +- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; ++ neighbour_score += backoff_weighting.unwrap() * rarity; + reachability_favored |= favored_filled.insert(reachability.index); + } + } diff --git a/fuzzers/prescientfuzz_0_999_backoff/builder.Dockerfile b/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/builder.Dockerfile similarity index 95% rename from fuzzers/prescientfuzz_0_999_backoff/builder.Dockerfile rename to fuzzers/prescientfuzz_depth_const_1/prescientfuzz/builder.Dockerfile index 4fc30402f..2449a3b14 100644 --- a/fuzzers/prescientfuzz_0_999_backoff/builder.Dockerfile +++ b/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/builder.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 9f61f245be96f705279d1bc48057ccc4c6e763ba +RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz_0_999_backoff/description.md b/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/description.md similarity index 100% rename from fuzzers/prescientfuzz_0_999_backoff/description.md rename to fuzzers/prescientfuzz_depth_const_1/prescientfuzz/description.md diff --git a/fuzzers/prescientfuzz_0_99999_backoff/fuzzer.py b/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/fuzzer.py similarity index 96% rename from fuzzers/prescientfuzz_0_99999_backoff/fuzzer.py rename to fuzzers/prescientfuzz_depth_const_1/prescientfuzz/fuzzer.py index 801a40b67..4f4601c91 100755 --- a/fuzzers/prescientfuzz_0_99999_backoff/fuzzer.py +++ b/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/fuzzer.py @@ -55,6 +55,9 @@ def build(): utils.append_flags('CXXFLAGS', cflags) utils.append_flags('LDFLAGS', cflags) + os.environ['RANLIB'] = 'llvm-ranlib' + os.environ['AR'] = 'llvm-ar' + os.environ['AS'] = 'llvm-as' os.environ['FUZZER_LIB'] = '/stub_rt.a' build_directory = os.environ['OUT'] cfg_file = build_directory + '/afl_cfg.bin' @@ -76,7 +79,7 @@ def fuzz(input_corpus, output_corpus, target_binary): command += (['-c', cfg_file]) else: sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.99999']) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) fuzzer_env = os.environ.copy() fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' print(command) diff --git a/fuzzers/prescientfuzz_0_9999_backoff/runner.Dockerfile b/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_0_9999_backoff/runner.Dockerfile rename to fuzzers/prescientfuzz_depth_const_1/prescientfuzz/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_0_999_backoff/runner.Dockerfile b/fuzzers/prescientfuzz_depth_const_1/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_0_999_backoff/runner.Dockerfile rename to fuzzers/prescientfuzz_depth_const_1/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_depth_squared/builder.Dockerfile b/fuzzers/prescientfuzz_depth_squared/builder.Dockerfile new file mode 100644 index 000000000..954583e89 --- /dev/null +++ b/fuzzers/prescientfuzz_depth_squared/builder.Dockerfile @@ -0,0 +1,50 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ + rm /rustup.sh + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + cargo && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +COPY ./patch /PrescientFuzz/patch +RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 && git apply patch + +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_no_backoff/description.md b/fuzzers/prescientfuzz_depth_squared/description.md similarity index 100% rename from fuzzers/prescientfuzz_no_backoff/description.md rename to fuzzers/prescientfuzz_depth_squared/description.md diff --git a/fuzzers/prescientfuzz_no_backoff/fuzzer.py b/fuzzers/prescientfuzz_depth_squared/fuzzer.py similarity index 96% rename from fuzzers/prescientfuzz_no_backoff/fuzzer.py rename to fuzzers/prescientfuzz_depth_squared/fuzzer.py index 3b91db7c3..4f4601c91 100755 --- a/fuzzers/prescientfuzz_no_backoff/fuzzer.py +++ b/fuzzers/prescientfuzz_depth_squared/fuzzer.py @@ -55,6 +55,9 @@ def build(): utils.append_flags('CXXFLAGS', cflags) utils.append_flags('LDFLAGS', cflags) + os.environ['RANLIB'] = 'llvm-ranlib' + os.environ['AR'] = 'llvm-ar' + os.environ['AS'] = 'llvm-as' os.environ['FUZZER_LIB'] = '/stub_rt.a' build_directory = os.environ['OUT'] cfg_file = build_directory + '/afl_cfg.bin' @@ -76,7 +79,7 @@ def fuzz(input_corpus, output_corpus, target_binary): command += (['-c', cfg_file]) else: sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '1.0']) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) fuzzer_env = os.environ.copy() fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' print(command) diff --git a/fuzzers/prescientfuzz_depth_squared/patch b/fuzzers/prescientfuzz_depth_squared/patch new file mode 100644 index 000000000..8e2974b31 --- /dev/null +++ b/fuzzers/prescientfuzz_depth_squared/patch @@ -0,0 +1,13 @@ +diff --git a/libafl/src/schedulers/probabilistic_sampling.rs b/libafl/src/schedulers/probabilistic_sampling.rs +index fd552a3d..af70e4cf 100644 +--- a/libafl/src/schedulers/probabilistic_sampling.rs ++++ b/libafl/src/schedulers/probabilistic_sampling.rs +@@ -294,7 +294,7 @@ where + let rarity = 1f64 / *freq.unwrap() as f64; + let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); + if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } +- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; ++ neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / (reachability.depth as f64).powi(2); + reachability_favored |= favored_filled.insert(reachability.index); + } + } diff --git a/fuzzers/prescientfuzz_0_9999_backoff/builder.Dockerfile b/fuzzers/prescientfuzz_depth_squared/prescientfuzz/builder.Dockerfile similarity index 95% rename from fuzzers/prescientfuzz_0_9999_backoff/builder.Dockerfile rename to fuzzers/prescientfuzz_depth_squared/prescientfuzz/builder.Dockerfile index 4fc30402f..2449a3b14 100644 --- a/fuzzers/prescientfuzz_0_9999_backoff/builder.Dockerfile +++ b/fuzzers/prescientfuzz_depth_squared/prescientfuzz/builder.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 9f61f245be96f705279d1bc48057ccc4c6e763ba +RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz_no_filter/description.md b/fuzzers/prescientfuzz_depth_squared/prescientfuzz/description.md similarity index 100% rename from fuzzers/prescientfuzz_no_filter/description.md rename to fuzzers/prescientfuzz_depth_squared/prescientfuzz/description.md diff --git a/fuzzers/prescientfuzz_depth_squared/prescientfuzz/fuzzer.py b/fuzzers/prescientfuzz_depth_squared/prescientfuzz/fuzzer.py new file mode 100755 index 000000000..4f4601c91 --- /dev/null +++ b/fuzzers/prescientfuzz_depth_squared/prescientfuzz/fuzzer.py @@ -0,0 +1,86 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import sys +import subprocess +from pathlib import Path + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): + """Build benchmark.""" + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['RANLIB'] = 'llvm-ranlib' + os.environ['AR'] = 'llvm-ar' + os.environ['AS'] = 'llvm-as' + os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_no_backoff/runner.Dockerfile b/fuzzers/prescientfuzz_depth_squared/prescientfuzz/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_no_backoff/runner.Dockerfile rename to fuzzers/prescientfuzz_depth_squared/prescientfuzz/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_no_filter/runner.Dockerfile b/fuzzers/prescientfuzz_depth_squared/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_no_filter/runner.Dockerfile rename to fuzzers/prescientfuzz_depth_squared/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_nn/builder.Dockerfile b/fuzzers/prescientfuzz_nn/builder.Dockerfile new file mode 100644 index 000000000..954583e89 --- /dev/null +++ b/fuzzers/prescientfuzz_nn/builder.Dockerfile @@ -0,0 +1,50 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ + rm /rustup.sh + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + cargo && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +COPY ./patch /PrescientFuzz/patch +RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 && git apply patch + +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_nn/description.md b/fuzzers/prescientfuzz_nn/description.md new file mode 100644 index 000000000..452b0e374 --- /dev/null +++ b/fuzzers/prescientfuzz_nn/description.md @@ -0,0 +1,8 @@ +# PrescientFuzz + +based on libafl fuzzer instance + - persistent mode + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_nn/fuzzer.py b/fuzzers/prescientfuzz_nn/fuzzer.py new file mode 100755 index 000000000..4f4601c91 --- /dev/null +++ b/fuzzers/prescientfuzz_nn/fuzzer.py @@ -0,0 +1,86 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import sys +import subprocess +from pathlib import Path + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): + """Build benchmark.""" + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['RANLIB'] = 'llvm-ranlib' + os.environ['AR'] = 'llvm-ar' + os.environ['AS'] = 'llvm-as' + os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_nn/patch b/fuzzers/prescientfuzz_nn/patch new file mode 100644 index 000000000..71e6dc7d6 --- /dev/null +++ b/fuzzers/prescientfuzz_nn/patch @@ -0,0 +1,13 @@ +diff --git a/libafl/src/schedulers/probabilistic_sampling.rs b/libafl/src/schedulers/probabilistic_sampling.rs +index fd552a3d..cbb1169b 100644 +--- a/libafl/src/schedulers/probabilistic_sampling.rs ++++ b/libafl/src/schedulers/probabilistic_sampling.rs +@@ -288,7 +288,7 @@ where + let idx_meta = tc.metadata::().unwrap(); + for reachability in reachabilities { + // Only keep this if it's the best depth we've seen for this edge +- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { ++ if reachability.depth == 1 { + let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); + if freq.is_none() { println!("frequency is none for {:?}", reachability); } + let rarity = 1f64 / *freq.unwrap() as f64; diff --git a/fuzzers/prescientfuzz_no_backoff/builder.Dockerfile b/fuzzers/prescientfuzz_nn/prescientfuzz/builder.Dockerfile similarity index 95% rename from fuzzers/prescientfuzz_no_backoff/builder.Dockerfile rename to fuzzers/prescientfuzz_nn/prescientfuzz/builder.Dockerfile index 4fc30402f..2449a3b14 100644 --- a/fuzzers/prescientfuzz_no_backoff/builder.Dockerfile +++ b/fuzzers/prescientfuzz_nn/prescientfuzz/builder.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 9f61f245be96f705279d1bc48057ccc4c6e763ba +RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz_nn/prescientfuzz/description.md b/fuzzers/prescientfuzz_nn/prescientfuzz/description.md new file mode 100644 index 000000000..452b0e374 --- /dev/null +++ b/fuzzers/prescientfuzz_nn/prescientfuzz/description.md @@ -0,0 +1,8 @@ +# PrescientFuzz + +based on libafl fuzzer instance + - persistent mode + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_nn/prescientfuzz/fuzzer.py b/fuzzers/prescientfuzz_nn/prescientfuzz/fuzzer.py new file mode 100755 index 000000000..4f4601c91 --- /dev/null +++ b/fuzzers/prescientfuzz_nn/prescientfuzz/fuzzer.py @@ -0,0 +1,86 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import sys +import subprocess +from pathlib import Path + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): + """Build benchmark.""" + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['RANLIB'] = 'llvm-ranlib' + os.environ['AR'] = 'llvm-ar' + os.environ['AS'] = 'llvm-as' + os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_nn/prescientfuzz/runner.Dockerfile b/fuzzers/prescientfuzz_nn/prescientfuzz/runner.Dockerfile new file mode 100644 index 000000000..1a023b81e --- /dev/null +++ b/fuzzers/prescientfuzz_nn/prescientfuzz/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_nn/runner.Dockerfile b/fuzzers/prescientfuzz_nn/runner.Dockerfile new file mode 100644 index 000000000..1a023b81e --- /dev/null +++ b/fuzzers/prescientfuzz_nn/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_no_filter/builder.Dockerfile b/fuzzers/prescientfuzz_no_filter/builder.Dockerfile deleted file mode 100644 index e8536717a..000000000 --- a/fuzzers/prescientfuzz_no_filter/builder.Dockerfile +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ARG parent_image -FROM $parent_image - -# Uninstall old Rust & Install the latest one. -RUN if which rustup; then rustup self uninstall -y; fi && \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh -y && \ - /root/.cargo/bin/rustup toolchain install nightly && \ - rm /rustup.sh - -RUN apt-get update && \ - apt-get install -y \ - build-essential \ - cargo && \ - apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ - libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ - apt-utils apt-transport-https ca-certificates joe curl && \ - PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make - -# Download PrescientFuzz -RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 8ae1b88b8509eb9395351badca557705e5ec5619 - -# Compile PrescientFuzz. -RUN cd /PrescientFuzz && \ - unset CFLAGS CXXFLAGS && \ - export CC=clang AFL_NO_X86 && \ - export LIBAFL_EDGES_MAP_SIZE=2621440 && \ - cd ./fuzzers/fuzzbench && \ - PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main - -# Auxiliary weak references. -RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ - clang -c stub_rt.c && \ - ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_no_filter/fuzzer.py b/fuzzers/prescientfuzz_no_filter/fuzzer.py deleted file mode 100755 index fdf942217..000000000 --- a/fuzzers/prescientfuzz_no_filter/fuzzer.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -"""Integration code for a LibAFL-based fuzzer.""" - -import os -import sys -import subprocess -from pathlib import Path - -from fuzzers import utils - - -def prepare_fuzz_environment(input_corpus): - """Prepare to fuzz with a LibAFL-based fuzzer.""" - os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ - 'malloc_context_size=0:symbolize=0:'\ - 'allocator_may_return_null=1:'\ - 'detect_odr_violation=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_abort=0:'\ - 'handle_sigfpe=0:handle_sigill=0' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ - 'allocator_release_to_os_interval_ms=500:'\ - 'handle_abort=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_sigfpe=0:'\ - 'handle_sigill=0:print_stacktrace=0:'\ - 'symbolize=0:symbolize_inline_frames=0' - # Create at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def build(): - """Build benchmark.""" - os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') - os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cxx') - - os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' - - cflags = ['--libafl'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - utils.append_flags('LDFLAGS', cflags) - - os.environ['FUZZER_LIB'] = '/stub_rt.a' - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - Path(cfg_file).touch() - os.environ['AFL_LLVM_CFG_FILE'] = cfg_file - utils.build_benchmark() - - -def fuzz(input_corpus, output_corpus, target_binary): - """Run fuzzer.""" - prepare_fuzz_environment(input_corpus) - dictionary_path = utils.get_dictionary_path(target_binary) - command = [target_binary] - if dictionary_path: - command += (['-x', dictionary_path]) - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - if os.path.exists(cfg_file): - command += (['-c', cfg_file]) - else: - sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus]) - fuzzer_env = os.environ.copy() - fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' - print(command) - subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) From 71d12dd87803875e553b9e950051456fab8bf33d Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Wed, 22 May 2024 14:08:51 +0100 Subject: [PATCH 11/25] use libafl_cc as LD also (to fix build issues) --- fuzzers/prescientfuzz/fuzzer.py | 2 ++ fuzzers/prescientfuzz_depth_const_1/fuzzer.py | 2 ++ fuzzers/prescientfuzz_depth_squared/fuzzer.py | 2 ++ fuzzers/prescientfuzz_nn/fuzzer.py | 2 ++ 4 files changed, 8 insertions(+) diff --git a/fuzzers/prescientfuzz/fuzzer.py b/fuzzers/prescientfuzz/fuzzer.py index 4f4601c91..0d91dd1ed 100755 --- a/fuzzers/prescientfuzz/fuzzer.py +++ b/fuzzers/prescientfuzz/fuzzer.py @@ -46,6 +46,8 @@ def build(): 'release-fuzzbench/libafl_cc') os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' 'release-fuzzbench/libafl_cxx') + os.environ['LD'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' diff --git a/fuzzers/prescientfuzz_depth_const_1/fuzzer.py b/fuzzers/prescientfuzz_depth_const_1/fuzzer.py index 4f4601c91..0d91dd1ed 100755 --- a/fuzzers/prescientfuzz_depth_const_1/fuzzer.py +++ b/fuzzers/prescientfuzz_depth_const_1/fuzzer.py @@ -46,6 +46,8 @@ def build(): 'release-fuzzbench/libafl_cc') os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' 'release-fuzzbench/libafl_cxx') + os.environ['LD'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' diff --git a/fuzzers/prescientfuzz_depth_squared/fuzzer.py b/fuzzers/prescientfuzz_depth_squared/fuzzer.py index 4f4601c91..0d91dd1ed 100755 --- a/fuzzers/prescientfuzz_depth_squared/fuzzer.py +++ b/fuzzers/prescientfuzz_depth_squared/fuzzer.py @@ -46,6 +46,8 @@ def build(): 'release-fuzzbench/libafl_cc') os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' 'release-fuzzbench/libafl_cxx') + os.environ['LD'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' diff --git a/fuzzers/prescientfuzz_nn/fuzzer.py b/fuzzers/prescientfuzz_nn/fuzzer.py index 4f4601c91..0d91dd1ed 100755 --- a/fuzzers/prescientfuzz_nn/fuzzer.py +++ b/fuzzers/prescientfuzz_nn/fuzzer.py @@ -46,6 +46,8 @@ def build(): 'release-fuzzbench/libafl_cc') os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' 'release-fuzzbench/libafl_cxx') + os.environ['LD'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' From 9bda1e3ed7c5e2ebbffbe2aaa21e9cb3a3b8c0ef Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Thu, 23 May 2024 11:49:04 +0100 Subject: [PATCH 12/25] Revert LTO, and reset for depth weighting experiment --- fuzzers/prescientfuzz/builder.Dockerfile | 2 +- fuzzers/prescientfuzz/fuzzer.py | 5 ----- fuzzers/prescientfuzz_depth_const_1/builder.Dockerfile | 2 +- fuzzers/prescientfuzz_depth_const_1/fuzzer.py | 5 ----- fuzzers/prescientfuzz_depth_const_1/patch | 4 ++-- fuzzers/prescientfuzz_depth_squared/builder.Dockerfile | 2 +- fuzzers/prescientfuzz_depth_squared/fuzzer.py | 5 ----- fuzzers/prescientfuzz_nn/builder.Dockerfile | 2 +- fuzzers/prescientfuzz_nn/fuzzer.py | 5 ----- fuzzers/prescientfuzz_nn/patch | 4 ++-- 10 files changed, 8 insertions(+), 28 deletions(-) diff --git a/fuzzers/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz/builder.Dockerfile index 2449a3b14..d3cdb8d21 100644 --- a/fuzzers/prescientfuzz/builder.Dockerfile +++ b/fuzzers/prescientfuzz/builder.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 +RUN cd /PrescientFuzz && git fetch && git 543074581cdd98d747c7e625745dab7ade5799d3 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz/fuzzer.py b/fuzzers/prescientfuzz/fuzzer.py index 0d91dd1ed..5f2dfa95f 100755 --- a/fuzzers/prescientfuzz/fuzzer.py +++ b/fuzzers/prescientfuzz/fuzzer.py @@ -46,8 +46,6 @@ def build(): 'release-fuzzbench/libafl_cc') os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' 'release-fuzzbench/libafl_cxx') - os.environ['LD'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' @@ -57,9 +55,6 @@ def build(): utils.append_flags('CXXFLAGS', cflags) utils.append_flags('LDFLAGS', cflags) - os.environ['RANLIB'] = 'llvm-ranlib' - os.environ['AR'] = 'llvm-ar' - os.environ['AS'] = 'llvm-as' os.environ['FUZZER_LIB'] = '/stub_rt.a' build_directory = os.environ['OUT'] cfg_file = build_directory + '/afl_cfg.bin' diff --git a/fuzzers/prescientfuzz_depth_const_1/builder.Dockerfile b/fuzzers/prescientfuzz_depth_const_1/builder.Dockerfile index 954583e89..2c5acf685 100644 --- a/fuzzers/prescientfuzz_depth_const_1/builder.Dockerfile +++ b/fuzzers/prescientfuzz_depth_const_1/builder.Dockerfile @@ -34,7 +34,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz COPY ./patch /PrescientFuzz/patch -RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 && git apply patch +RUN cd /PrescientFuzz && git fetch && git checkout 543074581cdd98d747c7e625745dab7ade5799d3 && git apply patch # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz_depth_const_1/fuzzer.py b/fuzzers/prescientfuzz_depth_const_1/fuzzer.py index 0d91dd1ed..5f2dfa95f 100755 --- a/fuzzers/prescientfuzz_depth_const_1/fuzzer.py +++ b/fuzzers/prescientfuzz_depth_const_1/fuzzer.py @@ -46,8 +46,6 @@ def build(): 'release-fuzzbench/libafl_cc') os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' 'release-fuzzbench/libafl_cxx') - os.environ['LD'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' @@ -57,9 +55,6 @@ def build(): utils.append_flags('CXXFLAGS', cflags) utils.append_flags('LDFLAGS', cflags) - os.environ['RANLIB'] = 'llvm-ranlib' - os.environ['AR'] = 'llvm-ar' - os.environ['AS'] = 'llvm-as' os.environ['FUZZER_LIB'] = '/stub_rt.a' build_directory = os.environ['OUT'] cfg_file = build_directory + '/afl_cfg.bin' diff --git a/fuzzers/prescientfuzz_depth_const_1/patch b/fuzzers/prescientfuzz_depth_const_1/patch index 1ba9ef931..908ebf208 100644 --- a/fuzzers/prescientfuzz_depth_const_1/patch +++ b/fuzzers/prescientfuzz_depth_const_1/patch @@ -1,5 +1,5 @@ diff --git a/libafl/src/schedulers/probabilistic_sampling.rs b/libafl/src/schedulers/probabilistic_sampling.rs -index fd552a3d..c275d211 100644 +index fd552a3d..b9cfc10d 100644 --- a/libafl/src/schedulers/probabilistic_sampling.rs +++ b/libafl/src/schedulers/probabilistic_sampling.rs @@ -294,7 +294,7 @@ where @@ -7,7 +7,7 @@ index fd552a3d..c275d211 100644 let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } - neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; -+ neighbour_score += backoff_weighting.unwrap() * rarity; ++ neighbour_score += backoff_weighting.unwrap() * rarity; // * 1f64 / reachability.depth as f64; reachability_favored |= favored_filled.insert(reachability.index); } } diff --git a/fuzzers/prescientfuzz_depth_squared/builder.Dockerfile b/fuzzers/prescientfuzz_depth_squared/builder.Dockerfile index 954583e89..2c5acf685 100644 --- a/fuzzers/prescientfuzz_depth_squared/builder.Dockerfile +++ b/fuzzers/prescientfuzz_depth_squared/builder.Dockerfile @@ -34,7 +34,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz COPY ./patch /PrescientFuzz/patch -RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 && git apply patch +RUN cd /PrescientFuzz && git fetch && git checkout 543074581cdd98d747c7e625745dab7ade5799d3 && git apply patch # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz_depth_squared/fuzzer.py b/fuzzers/prescientfuzz_depth_squared/fuzzer.py index 0d91dd1ed..5f2dfa95f 100755 --- a/fuzzers/prescientfuzz_depth_squared/fuzzer.py +++ b/fuzzers/prescientfuzz_depth_squared/fuzzer.py @@ -46,8 +46,6 @@ def build(): 'release-fuzzbench/libafl_cc') os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' 'release-fuzzbench/libafl_cxx') - os.environ['LD'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' @@ -57,9 +55,6 @@ def build(): utils.append_flags('CXXFLAGS', cflags) utils.append_flags('LDFLAGS', cflags) - os.environ['RANLIB'] = 'llvm-ranlib' - os.environ['AR'] = 'llvm-ar' - os.environ['AS'] = 'llvm-as' os.environ['FUZZER_LIB'] = '/stub_rt.a' build_directory = os.environ['OUT'] cfg_file = build_directory + '/afl_cfg.bin' diff --git a/fuzzers/prescientfuzz_nn/builder.Dockerfile b/fuzzers/prescientfuzz_nn/builder.Dockerfile index 954583e89..2c5acf685 100644 --- a/fuzzers/prescientfuzz_nn/builder.Dockerfile +++ b/fuzzers/prescientfuzz_nn/builder.Dockerfile @@ -34,7 +34,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz COPY ./patch /PrescientFuzz/patch -RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 && git apply patch +RUN cd /PrescientFuzz && git fetch && git checkout 543074581cdd98d747c7e625745dab7ade5799d3 && git apply patch # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz_nn/fuzzer.py b/fuzzers/prescientfuzz_nn/fuzzer.py index 0d91dd1ed..5f2dfa95f 100755 --- a/fuzzers/prescientfuzz_nn/fuzzer.py +++ b/fuzzers/prescientfuzz_nn/fuzzer.py @@ -46,8 +46,6 @@ def build(): 'release-fuzzbench/libafl_cc') os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' 'release-fuzzbench/libafl_cxx') - os.environ['LD'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' @@ -57,9 +55,6 @@ def build(): utils.append_flags('CXXFLAGS', cflags) utils.append_flags('LDFLAGS', cflags) - os.environ['RANLIB'] = 'llvm-ranlib' - os.environ['AR'] = 'llvm-ar' - os.environ['AS'] = 'llvm-as' os.environ['FUZZER_LIB'] = '/stub_rt.a' build_directory = os.environ['OUT'] cfg_file = build_directory + '/afl_cfg.bin' diff --git a/fuzzers/prescientfuzz_nn/patch b/fuzzers/prescientfuzz_nn/patch index 71e6dc7d6..bd29686d2 100644 --- a/fuzzers/prescientfuzz_nn/patch +++ b/fuzzers/prescientfuzz_nn/patch @@ -1,5 +1,5 @@ diff --git a/libafl/src/schedulers/probabilistic_sampling.rs b/libafl/src/schedulers/probabilistic_sampling.rs -index fd552a3d..cbb1169b 100644 +index fd552a3d..08f92646 100644 --- a/libafl/src/schedulers/probabilistic_sampling.rs +++ b/libafl/src/schedulers/probabilistic_sampling.rs @@ -288,7 +288,7 @@ where @@ -7,7 +7,7 @@ index fd552a3d..cbb1169b 100644 for reachability in reachabilities { // Only keep this if it's the best depth we've seen for this edge - if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { -+ if reachability.depth == 1 { ++ if reachability.depth == 1 { //reachable_blocks_result.least_depth_for_index[&reachability.index] { let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); if freq.is_none() { println!("frequency is none for {:?}", reachability); } let rarity = 1f64 / *freq.unwrap() as f64; From e6db0bb1cd7b388b70b57ea710e9acce44d884c4 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Thu, 23 May 2024 13:46:52 +0100 Subject: [PATCH 13/25] Missing checkout git argument --- fuzzers/prescientfuzz/builder.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuzzers/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz/builder.Dockerfile index d3cdb8d21..a46e7eb60 100644 --- a/fuzzers/prescientfuzz/builder.Dockerfile +++ b/fuzzers/prescientfuzz/builder.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git 543074581cdd98d747c7e625745dab7ade5799d3 +RUN cd /PrescientFuzz && git fetch && git checkout 543074581cdd98d747c7e625745dab7ade5799d3 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ From cc22d63e8927fd9e7116649d06c45335c39ae010 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Fri, 24 May 2024 12:54:49 +0100 Subject: [PATCH 14/25] Pin to base libafl version for true comparison --- fuzzers/libafl/builder.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuzzers/libafl/builder.Dockerfile b/fuzzers/libafl/builder.Dockerfile index 3f726cfec..af323c564 100644 --- a/fuzzers/libafl/builder.Dockerfile +++ b/fuzzers/libafl/builder.Dockerfile @@ -44,7 +44,7 @@ RUN if which rustup; then rustup self uninstall -y; fi && \ RUN git clone https://github.com/AFLplusplus/LibAFL /libafl # Checkout a current commit -RUN cd /libafl && git pull && git checkout b4efb6151550a37f61a869acf2957a1b07894a93 || true +RUN cd /libafl && git pull && git checkout 19f5081bd8ce0c043642b6075501988cdd2c6691 || true # Note that due a nightly bug it is currently fixed to a known version on top! # Compile libafl. From 4ccb721c7365f3ebbbc6c57bdce2fdf796a94d8c Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Fri, 24 May 2024 16:50:09 +0100 Subject: [PATCH 15/25] Updated PrescientFuzz to head of libafl and added alt older setups --- fuzzers/libafl/builder.Dockerfile | 2 +- .../builder.Dockerfile | 35 +- fuzzers/libafl_19f5081/description.md | 11 + .../fuzzer.py | 27 +- fuzzers/libafl_19f5081/patch | 55 ++ .../runner.Dockerfile | 2 +- fuzzers/prescientfuzz/builder.Dockerfile | 2 +- fuzzers/prescientfuzz/patch | 569 ++++++++++++++++++ .../builder.Dockerfile | 3 +- .../description.md | 0 .../fuzzer.py | 0 fuzzers/prescientfuzz_19f5081/patch | 569 ++++++++++++++++++ .../runner.Dockerfile | 0 fuzzers/prescientfuzz_depth_const_1/patch | 13 - .../prescientfuzz/builder.Dockerfile | 49 -- .../prescientfuzz/description.md | 8 - .../prescientfuzz/fuzzer.py | 86 --- .../builder.Dockerfile | 50 -- .../description.md | 8 - fuzzers/prescientfuzz_depth_squared/patch | 13 - .../prescientfuzz/description.md | 8 - .../prescientfuzz/fuzzer.py | 86 --- .../prescientfuzz/runner.Dockerfile | 25 - .../runner.Dockerfile | 25 - fuzzers/prescientfuzz_nn/builder.Dockerfile | 50 -- fuzzers/prescientfuzz_nn/description.md | 8 - fuzzers/prescientfuzz_nn/fuzzer.py | 83 --- fuzzers/prescientfuzz_nn/patch | 13 - .../prescientfuzz/builder.Dockerfile | 49 -- .../prescientfuzz/description.md | 8 - .../prescientfuzz_nn/prescientfuzz/fuzzer.py | 86 --- .../prescientfuzz/runner.Dockerfile | 25 - fuzzers/prescientfuzz_nn/runner.Dockerfile | 25 - 33 files changed, 1239 insertions(+), 754 deletions(-) rename fuzzers/{prescientfuzz_depth_squared/prescientfuzz => libafl_19f5081}/builder.Dockerfile (52%) create mode 100644 fuzzers/libafl_19f5081/description.md rename fuzzers/{prescientfuzz_depth_squared => libafl_19f5081}/fuzzer.py (76%) create mode 100644 fuzzers/libafl_19f5081/patch rename fuzzers/{prescientfuzz_depth_const_1 => libafl_19f5081}/runner.Dockerfile (96%) create mode 100644 fuzzers/prescientfuzz/patch rename fuzzers/{prescientfuzz_depth_const_1 => prescientfuzz_19f5081}/builder.Dockerfile (95%) rename fuzzers/{prescientfuzz_depth_const_1 => prescientfuzz_19f5081}/description.md (100%) rename fuzzers/{prescientfuzz_depth_const_1 => prescientfuzz_19f5081}/fuzzer.py (100%) create mode 100644 fuzzers/prescientfuzz_19f5081/patch rename fuzzers/{prescientfuzz_depth_const_1/prescientfuzz => prescientfuzz_19f5081}/runner.Dockerfile (100%) delete mode 100644 fuzzers/prescientfuzz_depth_const_1/patch delete mode 100644 fuzzers/prescientfuzz_depth_const_1/prescientfuzz/builder.Dockerfile delete mode 100644 fuzzers/prescientfuzz_depth_const_1/prescientfuzz/description.md delete mode 100755 fuzzers/prescientfuzz_depth_const_1/prescientfuzz/fuzzer.py delete mode 100644 fuzzers/prescientfuzz_depth_squared/builder.Dockerfile delete mode 100644 fuzzers/prescientfuzz_depth_squared/description.md delete mode 100644 fuzzers/prescientfuzz_depth_squared/patch delete mode 100644 fuzzers/prescientfuzz_depth_squared/prescientfuzz/description.md delete mode 100755 fuzzers/prescientfuzz_depth_squared/prescientfuzz/fuzzer.py delete mode 100644 fuzzers/prescientfuzz_depth_squared/prescientfuzz/runner.Dockerfile delete mode 100644 fuzzers/prescientfuzz_depth_squared/runner.Dockerfile delete mode 100644 fuzzers/prescientfuzz_nn/builder.Dockerfile delete mode 100644 fuzzers/prescientfuzz_nn/description.md delete mode 100755 fuzzers/prescientfuzz_nn/fuzzer.py delete mode 100644 fuzzers/prescientfuzz_nn/patch delete mode 100644 fuzzers/prescientfuzz_nn/prescientfuzz/builder.Dockerfile delete mode 100644 fuzzers/prescientfuzz_nn/prescientfuzz/description.md delete mode 100755 fuzzers/prescientfuzz_nn/prescientfuzz/fuzzer.py delete mode 100644 fuzzers/prescientfuzz_nn/prescientfuzz/runner.Dockerfile delete mode 100644 fuzzers/prescientfuzz_nn/runner.Dockerfile diff --git a/fuzzers/libafl/builder.Dockerfile b/fuzzers/libafl/builder.Dockerfile index af323c564..3f726cfec 100644 --- a/fuzzers/libafl/builder.Dockerfile +++ b/fuzzers/libafl/builder.Dockerfile @@ -44,7 +44,7 @@ RUN if which rustup; then rustup self uninstall -y; fi && \ RUN git clone https://github.com/AFLplusplus/LibAFL /libafl # Checkout a current commit -RUN cd /libafl && git pull && git checkout 19f5081bd8ce0c043642b6075501988cdd2c6691 || true +RUN cd /libafl && git pull && git checkout b4efb6151550a37f61a869acf2957a1b07894a93 || true # Note that due a nightly bug it is currently fixed to a known version on top! # Compile libafl. diff --git a/fuzzers/prescientfuzz_depth_squared/prescientfuzz/builder.Dockerfile b/fuzzers/libafl_19f5081/builder.Dockerfile similarity index 52% rename from fuzzers/prescientfuzz_depth_squared/prescientfuzz/builder.Dockerfile rename to fuzzers/libafl_19f5081/builder.Dockerfile index 2449a3b14..af323c564 100644 --- a/fuzzers/prescientfuzz_depth_squared/prescientfuzz/builder.Dockerfile +++ b/fuzzers/libafl_19f5081/builder.Dockerfile @@ -18,32 +18,43 @@ FROM $parent_image # Uninstall old Rust & Install the latest one. RUN if which rustup; then rustup self uninstall -y; fi && \ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh -y && \ - /root/.cargo/bin/rustup toolchain install nightly && \ + sh /rustup.sh --default-toolchain nightly-2023-09-21 -y && \ rm /rustup.sh +# Install dependencies. RUN apt-get update && \ + apt-get remove -y llvm-10 && \ apt-get install -y \ build-essential \ - cargo && \ + lsb-release wget software-properties-common gnupg && \ apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ apt-utils apt-transport-https ca-certificates joe curl && \ - PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 17 -# Download PrescientFuzz -RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 +RUN wget https://gist.githubusercontent.com/tokatoka/26f4ba95991c6e33139999976332aa8e/raw/698ac2087d58ce5c7a6ad59adce58dbfdc32bd46/createAliases.sh && chmod u+x ./createAliases.sh && ./createAliases.sh -# Compile PrescientFuzz. -RUN cd /PrescientFuzz && \ +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh --default-toolchain nightly-2024-03-12 -y && \ + rm /rustup.sh + +# Download libafl. +RUN git clone https://github.com/AFLplusplus/LibAFL /libafl + +# Checkout a current commit +RUN cd /libafl && git pull && git checkout 19f5081bd8ce0c043642b6075501988cdd2c6691 || true +# Note that due a nightly bug it is currently fixed to a known version on top! + +# Compile libafl. +RUN cd /libafl && \ unset CFLAGS CXXFLAGS && \ - export CC=clang AFL_NO_X86 && \ export LIBAFL_EDGES_MAP_SIZE=2621440 && \ cd ./fuzzers/fuzzbench && \ - PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + PATH="/root/.cargo/bin/:$PATH" cargo build --profile release-fuzzbench --features no_link_main # Auxiliary weak references. -RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ +RUN cd /libafl/fuzzers/fuzzbench && \ clang -c stub_rt.c && \ ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/libafl_19f5081/description.md b/fuzzers/libafl_19f5081/description.md new file mode 100644 index 000000000..ea9b947d6 --- /dev/null +++ b/fuzzers/libafl_19f5081/description.md @@ -0,0 +1,11 @@ +# libafl + +libafl fuzzer instance + - cmplog feature + - persistent mode + +Repository: [https://github.com/AFLplusplus/libafl/](https://github.com/AFLplusplus/libafl/) + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_depth_squared/fuzzer.py b/fuzzers/libafl_19f5081/fuzzer.py similarity index 76% rename from fuzzers/prescientfuzz_depth_squared/fuzzer.py rename to fuzzers/libafl_19f5081/fuzzer.py index 5f2dfa95f..0f191a744 100755 --- a/fuzzers/prescientfuzz_depth_squared/fuzzer.py +++ b/fuzzers/libafl_19f5081/fuzzer.py @@ -15,9 +15,7 @@ """Integration code for a LibAFL-based fuzzer.""" import os -import sys import subprocess -from pathlib import Path from fuzzers import utils @@ -40,26 +38,23 @@ def prepare_fuzz_environment(input_corpus): utils.create_seed_file_for_empty_corpus(input_corpus) -def build(): +def build(): # pylint: disable=too-many-branches,too-many-statements """Build benchmark.""" - os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') - os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cxx') + os.environ[ + 'CC'] = '/libafl/fuzzers/fuzzbench/target/release-fuzzbench/libafl_cc' + os.environ[ + 'CXX'] = '/libafl/fuzzers/fuzzbench/target/release-fuzzbench/libafl_cxx' os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' cflags = ['--libafl'] + cxxflags = ['--libafl', '--std=c++14'] utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('CXXFLAGS', cxxflags) utils.append_flags('LDFLAGS', cflags) os.environ['FUZZER_LIB'] = '/stub_rt.a' - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - Path(cfg_file).touch() - os.environ['AFL_LLVM_CFG_FILE'] = cfg_file utils.build_benchmark() @@ -70,13 +65,7 @@ def fuzz(input_corpus, output_corpus, target_binary): command = [target_binary] if dictionary_path: command += (['-x', dictionary_path]) - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - if os.path.exists(cfg_file): - command += (['-c', cfg_file]) - else: - sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) + command += (['-o', output_corpus, '-i', input_corpus]) fuzzer_env = os.environ.copy() fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' print(command) diff --git a/fuzzers/libafl_19f5081/patch b/fuzzers/libafl_19f5081/patch new file mode 100644 index 000000000..48e99fddf --- /dev/null +++ b/fuzzers/libafl_19f5081/patch @@ -0,0 +1,55 @@ +diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs +index 9b162a48..f1dc0d7b 100644 +--- a/fuzzers/fuzzbench/src/lib.rs ++++ b/fuzzers/fuzzbench/src/lib.rs +@@ -23,7 +23,7 @@ use libafl::{ + feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, + fuzzer::{Fuzzer, StdFuzzer}, + inputs::{BytesInput, HasTargetBytes}, +- monitors::SimpleMonitor, ++ monitors::SimplePrintingMonitor, + mutators::{ + scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, + StdMOptMutator, StdScheduledMutator, Tokens, +@@ -214,13 +214,7 @@ fn fuzz( + let file_null = File::open("/dev/null")?; + + // 'While the monitor are state, they are usually used in the broker - which is likely never restarted +- let monitor = SimpleMonitor::new(|s| { +- #[cfg(unix)] +- writeln!(&mut stdout_cpy, "{s}").unwrap(); +- #[cfg(windows)] +- println!("{s}"); +- writeln!(log.borrow_mut(), "{:?} {s}", current_time()).unwrap(); +- }); ++ let monitor = SimplePrintingMonitor::new(); + + // We need a shared map to store our state before a crash. + // This way, we are able to continue fuzzing afterwards. +@@ -380,16 +374,16 @@ fn fuzz( + } + + // Remove target output (logs still survive) +- #[cfg(unix)] +- { +- let null_fd = file_null.as_raw_fd(); +- dup2(null_fd, io::stdout().as_raw_fd())?; +- if std::env::var("LIBAFL_FUZZBENCH_DEBUG").is_err() { +- dup2(null_fd, io::stderr().as_raw_fd())?; +- } +- } +- // reopen file to make sure we're at the end +- log.replace(OpenOptions::new().append(true).create(true).open(logfile)?); ++ // #[cfg(unix)] ++ // { ++ // let null_fd = file_null.as_raw_fd(); ++ // dup2(null_fd, io::stdout().as_raw_fd())?; ++ // if std::env::var("LIBAFL_FUZZBENCH_DEBUG").is_err() { ++ // dup2(null_fd, io::stderr().as_raw_fd())?; ++ // } ++ // } ++ // // reopen file to make sure we're at the end ++ // log.replace(OpenOptions::new().append(true).create(true).open(logfile)?); + + fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)?; + diff --git a/fuzzers/prescientfuzz_depth_const_1/runner.Dockerfile b/fuzzers/libafl_19f5081/runner.Dockerfile similarity index 96% rename from fuzzers/prescientfuzz_depth_const_1/runner.Dockerfile rename to fuzzers/libafl_19f5081/runner.Dockerfile index 1a023b81e..f0c5eb6cc 100644 --- a/fuzzers/prescientfuzz_depth_const_1/runner.Dockerfile +++ b/fuzzers/libafl_19f5081/runner.Dockerfile @@ -18,7 +18,7 @@ RUN apt install libjemalloc2 # This makes interactive docker runs painless: ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" -ENV AFL_MAP_SIZE=2621440 +#ENV AFL_MAP_SIZE=2621440 ENV PATH="$PATH:/out" ENV AFL_SKIP_CPUFREQ=1 ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 diff --git a/fuzzers/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz/builder.Dockerfile index a46e7eb60..396820bef 100644 --- a/fuzzers/prescientfuzz/builder.Dockerfile +++ b/fuzzers/prescientfuzz/builder.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 543074581cdd98d747c7e625745dab7ade5799d3 +RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz/patch b/fuzzers/prescientfuzz/patch new file mode 100644 index 000000000..9a5bd5205 --- /dev/null +++ b/fuzzers/prescientfuzz/patch @@ -0,0 +1,569 @@ +diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs +index 0c40b942..e63325d8 100644 +--- a/fuzzers/fuzzbench/src/lib.rs ++++ b/fuzzers/fuzzbench/src/lib.rs +@@ -31,7 +31,7 @@ use libafl::{ + observers::{CanTrack, HitcountsMapObserver, TimeObserver}, + schedulers::{ + powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, +- probabilistic_sampling::UncoveredNeighboursProbabilitySamplingScheduler, ++ prescient_weighted::PrescientProbabilitySamplingScheduler, + }, + stages::{ + calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage, +@@ -243,7 +243,7 @@ fn fuzz( + #[cfg(windows)] + println!("{s}"); + writeln!(log.borrow_mut(), "{:?} {s}", current_time()).unwrap(); +- }, true); ++ }); + + // We need a shared map to store our state before a crash. + // This way, we are able to continue fuzzing afterwards. +@@ -332,7 +332,7 @@ fn fuzz( + + let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); + +- let scheduler = UncoveredNeighboursProbabilitySamplingScheduler::new_with_backoff(backoff_factor); ++ let scheduler = PrescientProbabilitySamplingScheduler::new_with_backoff(backoff_factor); + + // A fuzzer with feedbacks and a corpus scheduler + let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); +diff --git a/libafl/src/feedbacks/map.rs b/libafl/src/feedbacks/map.rs +index 5d4158a2..82e70d61 100644 +--- a/libafl/src/feedbacks/map.rs ++++ b/libafl/src/feedbacks/map.rs +@@ -14,7 +14,7 @@ use core::{ + use libafl_bolts::AsSlice; + use libafl_bolts::{ + tuples::{Handle, Handled, MatchNameRef}, +- AsIter, AsSlice, HasRefCnt, Named, ++ AsIter, HasRefCnt, Named, + }; + use num_traits::PrimInt; + use serde::{de::DeserializeOwned, Deserialize, Serialize}; +@@ -848,32 +848,32 @@ where + N: IsNovel, + C: CanTrack + AsRef + Named, + { +- // /// Create new `MapFeedback` +- // #[must_use] +- // pub fn new(map_observer: &C) -> Self { +- // Self { +- // novelties: if C::NOVELTIES { Some(vec![]) } else { None }, +- // name: map_observer.name().clone(), +- // map_ref: map_observer.handle(), +- // stats_name: create_stats_name(map_observer.name()), +- // phantom: PhantomData, +- // } +- // } +- +- // /// Creating a new `MapFeedback` with a specific name. This is usefully whenever the same +- // /// feedback is needed twice, but with a different history. Using `new()` always results in the +- // /// same name and therefore also the same history. +- // #[must_use] +- // pub fn with_name(name: &'static str, map_observer: &C) -> Self { +- // let name = Cow::from(name); +- // Self { +- // novelties: if C::NOVELTIES { Some(vec![]) } else { None }, +- // map_ref: map_observer.handle(), +- // stats_name: create_stats_name(&name), +- // name, +- // phantom: PhantomData, +- // } +- // } ++ /// Create new `MapFeedback` ++ #[must_use] ++ pub fn new(map_observer: &C) -> Self { ++ Self { ++ novelties: if C::NOVELTIES { Some(vec![]) } else { None }, ++ name: map_observer.name().clone(), ++ map_ref: map_observer.handle(), ++ stats_name: create_stats_name(map_observer.name()), ++ phantom: PhantomData, ++ } ++ } ++ ++ /// Creating a new `MapFeedback` with a specific name. This is usefully whenever the same ++ /// feedback is needed twice, but with a different history. Using `new()` always results in the ++ /// same name and therefore also the same history. ++ #[must_use] ++ pub fn with_name(name: &'static str, map_observer: &C) -> Self { ++ let name = Cow::from(name); ++ Self { ++ novelties: if C::NOVELTIES { Some(vec![]) } else { None }, ++ map_ref: map_observer.handle(), ++ stats_name: create_stats_name(&name), ++ name, ++ phantom: PhantomData, ++ } ++ } + + #[allow(clippy::wrong_self_convention)] + #[allow(clippy::needless_range_loop)] +diff --git a/libafl/src/schedulers/mod.rs b/libafl/src/schedulers/mod.rs +index 2a0b65df..2c829953 100644 +--- a/libafl/src/schedulers/mod.rs ++++ b/libafl/src/schedulers/mod.rs +@@ -26,6 +26,9 @@ pub use accounting::CoverageAccountingScheduler; + pub mod weighted; + pub use weighted::{StdWeightedScheduler, WeightedScheduler}; + ++pub mod prescient_weighted; ++pub use prescient_weighted::{PrescientProbabilitySamplingScheduler, ProbabilityMetadata}; ++ + pub mod tuneable; + use libafl_bolts::{ + rands::Rand, +diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs +new file mode 100644 +index 00000000..6761c534 +--- /dev/null ++++ b/libafl/src/schedulers/prescient_weighted.rs +@@ -0,0 +1,428 @@ ++//! Prescient Weighted sampling scheduler is a corpus scheduler that feeds the fuzzer ++ ++use std::vec::Vec; ++use hashbrown::HashSet; ++use alloc::string::String; ++use core::{marker::PhantomData, fmt::Debug}; ++ ++use hashbrown::HashMap; ++use libafl_bolts::rands::Rand; ++use libafl_bolts::HasLen; ++use serde::{Deserialize, Serialize}; ++use std::time::{Instant, SystemTime, UNIX_EPOCH}; ++ ++use crate::{ ++ HasMetadata, HasNamedMetadata, ++ corpus::{testcase::TestcaseMutationsMetadata, Corpus, CorpusId, HasTestcase}, ++ feedbacks::{cfg_prescience::{ControlFlowGraph, Reachability}, ++ MapIndexesMetadata, ++ MapNeighboursFeedbackMetadata, ++ MapNoveltiesMetadata}, ++ inputs::UsesInput, ++ schedulers::Scheduler, ++ state::{HasCorpus, HasRand, State, UsesState}, Error ++}; ++ ++/// Calculate Testcase probabilities using prescience ++#[derive(Debug, Clone)] ++pub struct PrescientProbabilitySamplingScheduler ++where ++ S: UsesInput, ++{ ++ backoff_factor: f64, ++ phantom: PhantomData, ++} ++ ++/// A state metadata holding a map of probability of corpus elements. ++#[derive(Debug, Serialize, Deserialize)] ++#[cfg_attr( ++ any(not(feature = "serdeany_autoreg"), miri), ++ allow(clippy::unsafe_derive_deserialize) ++)] // for SerdeAny ++pub struct ProbabilityMetadata { ++ /// corpus index -> probability ++ pub map: HashMap, ++ /// total probability of all items in the map ++ pub total_probability: f64, ++ /// Do we need to recalculate the scores? ++ pub needs_recalc: bool, ++ /// The time that we last recalculated all the scores (in millis) ++ pub last_recalc_time: u128, ++ /// The amount of time the last recalc took ++ pub last_recalc_duration: u128, ++} ++ ++libafl_bolts::impl_serdeany!(ProbabilityMetadata); ++ ++impl ProbabilityMetadata { ++ /// Creates a new [`struct@ProbabilityMetadata`] ++ #[must_use] ++ pub fn new() -> Self { ++ Self { ++ map: HashMap::default(), ++ total_probability: 0.0, ++ needs_recalc: false, ++ last_recalc_time: 0, ++ last_recalc_duration: 0, ++ } ++ } ++} ++ ++impl Default for ProbabilityMetadata { ++ fn default() -> Self { ++ Self::new() ++ } ++} ++ ++struct ReachableBlocksResult { ++ /// Number of corpus entries this reachability appears in ++ frequency_for_reachability: HashMap, ++ /// Cumulative number of times corpus entries directly neighbouring (ie depth 1) ++ /// this coverage map index have been mutated ++ direct_neighbour_mutations_for_index: HashMap, ++ /// Lowest depth observed for the given index ++ least_depth_for_index: HashMap, ++} ++ ++ ++impl PrescientProbabilitySamplingScheduler ++where ++ S: HasCorpus + HasMetadata + HasNamedMetadata + HasRand, ++ S::Input: HasLen, ++{ ++ /// Creates a new [`struct@ProbabilitySamplingScheduler`] ++ #[must_use] ++ pub fn new_with_backoff(backoff_factor: f64) -> Self { ++ Self { ++ backoff_factor, ++ phantom: PhantomData, ++ } ++ } ++ ++ /// Calculate the score and store in `ProbabilityMetadata` ++ #[allow(clippy::cast_precision_loss)] ++ #[allow(clippy::unused_self)] ++ pub fn store_probability(&self, _state: &mut S, _idx: CorpusId) -> Result<(), Error> { ++ assert!(false, "Should not use anymore"); ++ ++ Ok(()) ++ } ++ ++ /// return a map of {(index, depth): frequency}, where frequency is the number of testcases ++ /// with this index being reachable at the given depth ++ fn recalculate_reachable_blocks(&self, state: &mut S) -> ReachableBlocksResult { ++ let mut result = ReachableBlocksResult { ++ frequency_for_reachability: HashMap::new(), ++ direct_neighbour_mutations_for_index: HashMap::new(), ++ least_depth_for_index: HashMap::new(), ++ }; ++ let start = Instant::now(); ++ ++ let all_ids = state.corpus().ids().collect::>(); ++ ++ let full_neighbours_meta = state ++ .metadata_mut::() ++ .unwrap(); ++ ++ let covered_blocks = full_neighbours_meta.covered_blocks.clone(); ++ let last_recalc_corpus_ids = full_neighbours_meta.corpus_ids_present_at_recalc.clone(); ++ full_neighbours_meta.corpus_ids_present_at_recalc = all_ids.clone(); ++ ++ let mut recalcs = 0; ++ for &idx in &all_ids { ++ recalcs += 1; ++ ++ let tc = state.corpus().get(idx).unwrap().borrow(); ++ let covered_meta = tc.metadata::().unwrap(); ++ let covered_indexes = covered_meta.list.clone(); ++ let num_mutations = if let Ok(meta) = tc.metadata::() { ++ meta.num_mutations_executed ++ } else { ++ 0 ++ }; ++ drop(tc); ++ ++ let reachabilities = { ++ let cfg_metadata = state.metadata_mut::().unwrap(); ++ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) ++ }; ++ ++ if !last_recalc_corpus_ids.contains(&idx) { ++ let tc = state.corpus().get(idx).unwrap().borrow(); ++ let novelties_meta = tc.metadata::().unwrap(); ++ let novelties = novelties_meta.list.clone(); ++ drop(tc); ++ ++ let full_neighbours_meta = state ++ .metadata_mut::() ++ .unwrap(); ++ ++ for novelty in novelties { ++ full_neighbours_meta.reachable_blocks.remove(&novelty); ++ } ++ ++ for reachability in &reachabilities { ++ full_neighbours_meta.reachable_blocks.insert(reachability.index); ++ } ++ } ++ ++ for reachability in reachabilities { ++ // update reachability frequencies ++ let new = if let Some(freq) = result.frequency_for_reachability.get(&reachability) { ++ freq + 1 ++ } else { ++ 1 ++ }; ++ result.frequency_for_reachability.insert(reachability.clone(), new); ++ ++ // update number of mutations of direct neighbours (if appropriate) ++ if reachability.depth == 1 { ++ let updated = if let Some(freq) = result.direct_neighbour_mutations_for_index.get(&reachability.index) { ++ freq + num_mutations ++ } else { ++ num_mutations ++ }; ++ result.direct_neighbour_mutations_for_index.insert(reachability.index, updated); ++ } ++ ++ // update least depth for index (if we beat the previous depth) ++ if let Some(cur_min) = result.least_depth_for_index.get(&reachability.index) { ++ if reachability.depth < *cur_min { ++ result.least_depth_for_index.insert(reachability.index, reachability.depth); ++ } ++ } else { ++ result.least_depth_for_index.insert(reachability.index, reachability.depth); ++ } ++ } ++ } ++ ++ println!("Whew, recalced all neighbours for {recalcs} entries (out of a possible {}); took: {:.2?}", all_ids.len(), start.elapsed()); ++ ++ result ++ } ++ ++ /// Recalculate the probability of each testcase being selected for mutation ++ pub fn recalc_all_probabilities(&self, state: &mut S) -> Result<(), Error> { ++ let reachable_blocks_result = self.recalculate_reachable_blocks(state); ++ ++ let full_neighbours_meta = state ++ .metadata::() ++ .unwrap(); ++ let _reachable_all = full_neighbours_meta.reachable_blocks.clone(); ++ let covered_blocks = full_neighbours_meta.covered_blocks.clone(); ++ ++ let mut total_score = 0.0; ++ ++ let ids = state.corpus().ids().collect::>(); ++ let corpus_size = ids.len(); ++ let mut min_time = f64::MAX; ++ ++ // sort entries by time ++ let mut time_ordered = vec![]; ++ let mut min_len = 99999999f64; ++ let mut len_for_id = HashMap::new(); ++ for &id in &ids { ++ let mut tc = state.corpus().get(id)?.borrow_mut(); ++ let len = tc.load_len(state.corpus()).unwrap() as f64; ++ if len < min_len { min_len = len; } ++ len_for_id.insert(id, len); ++ let exec_time_ns = tc.exec_time().unwrap().as_nanos() as f64; ++ if exec_time_ns < min_time { min_time = exec_time_ns; } ++ time_ordered.push((id, exec_time_ns * len)); ++ } ++ time_ordered.sort_by(|(_id, score1), (_id2, score2)| score1.partial_cmp(score2).unwrap()); ++ ++ // The more this neighbour has been fuzzed, the less we'll prioritise it (maybe it's hard or infeasible) ++ let backoff_weighting_for_direct_neighbour = { ++ let mut weighting = HashMap::new(); ++ for (&index, &mutations) in &reachable_blocks_result.direct_neighbour_mutations_for_index { ++ let decrements = mutations / 1_000; ++ weighting.insert(index, self.backoff_factor.powi(decrements as i32)); ++ } ++ weighting ++ }; ++ ++ let mut favored_filled = HashSet::with_capacity(65536); ++ let mut reachability_favored_ids = HashSet::new(); ++ let mut coverage_favored_ids = HashSet::new(); ++ let mut favored_edges = HashSet::new(); ++ let mut all_covered = HashSet::new(); ++ let mut neighbour_score_for_idx = HashMap::new(); ++ ++ // greedily select a minimal subset of testcases that cover all neighbours (based on runtime) ++ for &(entry, _runtime) in &time_ordered { ++ let tc = state.corpus().get(entry)?.borrow(); ++ let idx_meta = tc.metadata::().unwrap(); ++ for &edge in &idx_meta.list { all_covered.insert(edge); } ++ ++ let mut neighbour_score = 0f64; ++ let mut reachability_favored = false; ++ ++ let covered_indexes = idx_meta.list.clone(); ++ drop(tc); ++ ++ let reachabilities = { ++ let cfg_metadata = state.metadata_mut::().unwrap(); ++ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) ++ }; ++ ++ let tc = state.corpus().get(entry)?.borrow(); ++ let idx_meta = tc.metadata::().unwrap(); ++ for reachability in reachabilities { ++ // Only keep this if it's the best depth we've seen for this edge ++ if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { ++ let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); ++ if freq.is_none() { println!("frequency is none for {:?}", reachability); } ++ let rarity = 1f64 / *freq.unwrap() as f64; ++ let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); ++ if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } ++ neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; ++ reachability_favored |= favored_filled.insert(reachability.index); ++ } ++ } ++ neighbour_score_for_idx.insert(entry, neighbour_score); ++ ++ let mut coverage_favored = false; ++ for &edge in &idx_meta.list { ++ coverage_favored |= favored_edges.insert(edge); ++ } ++ ++ if reachability_favored { ++ reachability_favored_ids.insert(entry); ++ } else if coverage_favored { ++ coverage_favored_ids.insert(entry); ++ } ++ } ++ ++ let skipped = all_covered.difference(&favored_edges).copied().collect::>(); ++ println!("Minimised the testset from {corpus_size} down to {} favored entries - and {} somewhat favored (favored edges: {}, missed out {} entries: {:?})", ++ reachability_favored_ids.len(), coverage_favored_ids.len(), ++ favored_edges.len(), skipped.len(), skipped); ++ ++ let mut all_scores = vec![]; ++ for entry in ids { ++ let tc = state.corpus().get(entry)?.borrow(); ++ let mut score = neighbour_score_for_idx[&entry]; ++ ++ let exec_time_us = tc.exec_time().unwrap().as_nanos() as f64; ++ let time_weighting = min_time / exec_time_us; ++ score *= time_weighting; ++ ++ all_scores.push((entry, score)); ++ ++ total_score += score; ++ ++ drop(tc); ++ let meta = state ++ .metadata_map_mut() ++ .get_mut::() ++ .unwrap(); ++ meta.map.insert(entry, score); ++ } ++ ++ // all_scores.sort_by(|(_, score1), (_, score2)| score1.partial_cmp(score2).unwrap()); ++ // println!("Scores: {:?}", all_scores); ++ ++ let meta = state ++ .metadata_map_mut() ++ .get_mut::() ++ .unwrap(); ++ meta.total_probability = total_score; ++ ++ Ok(()) ++ } ++} ++ ++impl UsesState for PrescientProbabilitySamplingScheduler ++where ++ S: State + HasTestcase, ++{ ++ type State = S; ++} ++ ++impl Scheduler for PrescientProbabilitySamplingScheduler ++where ++ S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand + HasTestcase + State, ++ S::Input: HasLen, ++{ ++ fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> { ++ let current_idx = *state.corpus().current(); ++ state ++ .corpus() ++ .get(idx)? ++ .borrow_mut() ++ .set_parent_id_optional(current_idx); ++ ++ if state.metadata_map().get::().is_none() { ++ state.add_metadata(ProbabilityMetadata::new()); ++ } ++ ++ let prob_meta = state.metadata_map_mut().get_mut::().unwrap(); ++ prob_meta.needs_recalc = true; ++ let avg = prob_meta.total_probability / prob_meta.map.len() as f64; ++ prob_meta.map.insert(idx, avg); ++ prob_meta.total_probability += avg; ++ ++ // let max = prob_meta.map.values().fold(0f64, |max, &v| if v > max { v } else { max }); ++ // prob_meta.map.insert(idx, max); ++ // prob_meta.total_probability += max; ++ ++ Ok(()) ++ } ++ ++ /// Gets the next entry ++ #[allow(clippy::cast_precision_loss)] ++ fn next(&mut self, state: &mut Self::State) -> Result { ++ if state.corpus().count() == 0 { ++ Err(Error::empty(String::from("No entries in corpus"))) ++ } else { ++ const MAX_RAND: u64 = 1_000_000; ++ let rand_prob: f64 = (state.rand_mut().below(MAX_RAND as usize) as f64) / MAX_RAND as f64; ++ ++ let meta = state.metadata_map_mut().get_mut::().unwrap(); ++ if meta.needs_recalc { ++ let ts_now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(); ++ let time_since_recalc = ts_now - meta.last_recalc_time; ++ let last_duration = meta.last_recalc_duration; ++ // Don't spend more than 10% of the fuzzer time recalculating these stats - sure ++ // this feels like we're not using the neighbours prescient power much at the start ++ // of the campaign, but fuzzing campaigns last hours... ++ if time_since_recalc >= (10 * last_duration) { ++ println!("Last recalc took {last_duration}ms, now recalcing as it has been {time_since_recalc}"); ++ let start = Instant::now(); ++ self.recalculate_reachable_blocks(state); ++ self.recalc_all_probabilities(state).unwrap(); ++ ++ let meta = state.metadata_map_mut().get_mut::().unwrap(); ++ meta.needs_recalc = false; ++ meta.last_recalc_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(); ++ meta.last_recalc_duration = start.elapsed().as_millis(); ++ } ++ } ++ ++ let meta = state.metadata_map().get::().unwrap(); ++ let threshold = meta.total_probability * rand_prob; ++ let mut k: f64 = 0.0; ++ let mut ret = *meta.map.keys().last().unwrap(); ++ for (idx, prob) in &meta.map { ++ k += prob; ++ if k >= threshold { ++ ret = *idx; ++ break; ++ } ++ } ++ self.set_current_scheduled(state, Some(ret))?; ++ Ok(ret) ++ } ++ } ++} ++ ++impl Default for PrescientProbabilitySamplingScheduler ++where ++ S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand, ++ S::Input: HasLen, ++{ ++ fn default() -> Self { ++ Self::new_with_backoff(0.9999) ++ } ++} +\ No newline at end of file +diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs +index 69781524..9d097043 100644 +--- a/libafl/src/stages/mutational.rs ++++ b/libafl/src/stages/mutational.rs +@@ -117,10 +117,10 @@ where + let num = self.iterations(state)?; + let mut testcase = state.current_testcase_mut()?; + if let Ok(meta) = testcase.metadata_mut::() { +- meta.num_mutations_executed += num as usize; ++ meta.num_mutations_executed += num; + } else { + testcase.add_metadata( +- TestcaseMutationsMetadata { num_mutations_executed: num as usize } ++ TestcaseMutationsMetadata { num_mutations_executed: num } + ); + } + diff --git a/fuzzers/prescientfuzz_depth_const_1/builder.Dockerfile b/fuzzers/prescientfuzz_19f5081/builder.Dockerfile similarity index 95% rename from fuzzers/prescientfuzz_depth_const_1/builder.Dockerfile rename to fuzzers/prescientfuzz_19f5081/builder.Dockerfile index 2c5acf685..a46e7eb60 100644 --- a/fuzzers/prescientfuzz_depth_const_1/builder.Dockerfile +++ b/fuzzers/prescientfuzz_19f5081/builder.Dockerfile @@ -33,8 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -COPY ./patch /PrescientFuzz/patch -RUN cd /PrescientFuzz && git fetch && git checkout 543074581cdd98d747c7e625745dab7ade5799d3 && git apply patch +RUN cd /PrescientFuzz && git fetch && git checkout 543074581cdd98d747c7e625745dab7ade5799d3 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz_depth_const_1/description.md b/fuzzers/prescientfuzz_19f5081/description.md similarity index 100% rename from fuzzers/prescientfuzz_depth_const_1/description.md rename to fuzzers/prescientfuzz_19f5081/description.md diff --git a/fuzzers/prescientfuzz_depth_const_1/fuzzer.py b/fuzzers/prescientfuzz_19f5081/fuzzer.py similarity index 100% rename from fuzzers/prescientfuzz_depth_const_1/fuzzer.py rename to fuzzers/prescientfuzz_19f5081/fuzzer.py diff --git a/fuzzers/prescientfuzz_19f5081/patch b/fuzzers/prescientfuzz_19f5081/patch new file mode 100644 index 000000000..9a5bd5205 --- /dev/null +++ b/fuzzers/prescientfuzz_19f5081/patch @@ -0,0 +1,569 @@ +diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs +index 0c40b942..e63325d8 100644 +--- a/fuzzers/fuzzbench/src/lib.rs ++++ b/fuzzers/fuzzbench/src/lib.rs +@@ -31,7 +31,7 @@ use libafl::{ + observers::{CanTrack, HitcountsMapObserver, TimeObserver}, + schedulers::{ + powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, +- probabilistic_sampling::UncoveredNeighboursProbabilitySamplingScheduler, ++ prescient_weighted::PrescientProbabilitySamplingScheduler, + }, + stages::{ + calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage, +@@ -243,7 +243,7 @@ fn fuzz( + #[cfg(windows)] + println!("{s}"); + writeln!(log.borrow_mut(), "{:?} {s}", current_time()).unwrap(); +- }, true); ++ }); + + // We need a shared map to store our state before a crash. + // This way, we are able to continue fuzzing afterwards. +@@ -332,7 +332,7 @@ fn fuzz( + + let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); + +- let scheduler = UncoveredNeighboursProbabilitySamplingScheduler::new_with_backoff(backoff_factor); ++ let scheduler = PrescientProbabilitySamplingScheduler::new_with_backoff(backoff_factor); + + // A fuzzer with feedbacks and a corpus scheduler + let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); +diff --git a/libafl/src/feedbacks/map.rs b/libafl/src/feedbacks/map.rs +index 5d4158a2..82e70d61 100644 +--- a/libafl/src/feedbacks/map.rs ++++ b/libafl/src/feedbacks/map.rs +@@ -14,7 +14,7 @@ use core::{ + use libafl_bolts::AsSlice; + use libafl_bolts::{ + tuples::{Handle, Handled, MatchNameRef}, +- AsIter, AsSlice, HasRefCnt, Named, ++ AsIter, HasRefCnt, Named, + }; + use num_traits::PrimInt; + use serde::{de::DeserializeOwned, Deserialize, Serialize}; +@@ -848,32 +848,32 @@ where + N: IsNovel, + C: CanTrack + AsRef + Named, + { +- // /// Create new `MapFeedback` +- // #[must_use] +- // pub fn new(map_observer: &C) -> Self { +- // Self { +- // novelties: if C::NOVELTIES { Some(vec![]) } else { None }, +- // name: map_observer.name().clone(), +- // map_ref: map_observer.handle(), +- // stats_name: create_stats_name(map_observer.name()), +- // phantom: PhantomData, +- // } +- // } +- +- // /// Creating a new `MapFeedback` with a specific name. This is usefully whenever the same +- // /// feedback is needed twice, but with a different history. Using `new()` always results in the +- // /// same name and therefore also the same history. +- // #[must_use] +- // pub fn with_name(name: &'static str, map_observer: &C) -> Self { +- // let name = Cow::from(name); +- // Self { +- // novelties: if C::NOVELTIES { Some(vec![]) } else { None }, +- // map_ref: map_observer.handle(), +- // stats_name: create_stats_name(&name), +- // name, +- // phantom: PhantomData, +- // } +- // } ++ /// Create new `MapFeedback` ++ #[must_use] ++ pub fn new(map_observer: &C) -> Self { ++ Self { ++ novelties: if C::NOVELTIES { Some(vec![]) } else { None }, ++ name: map_observer.name().clone(), ++ map_ref: map_observer.handle(), ++ stats_name: create_stats_name(map_observer.name()), ++ phantom: PhantomData, ++ } ++ } ++ ++ /// Creating a new `MapFeedback` with a specific name. This is usefully whenever the same ++ /// feedback is needed twice, but with a different history. Using `new()` always results in the ++ /// same name and therefore also the same history. ++ #[must_use] ++ pub fn with_name(name: &'static str, map_observer: &C) -> Self { ++ let name = Cow::from(name); ++ Self { ++ novelties: if C::NOVELTIES { Some(vec![]) } else { None }, ++ map_ref: map_observer.handle(), ++ stats_name: create_stats_name(&name), ++ name, ++ phantom: PhantomData, ++ } ++ } + + #[allow(clippy::wrong_self_convention)] + #[allow(clippy::needless_range_loop)] +diff --git a/libafl/src/schedulers/mod.rs b/libafl/src/schedulers/mod.rs +index 2a0b65df..2c829953 100644 +--- a/libafl/src/schedulers/mod.rs ++++ b/libafl/src/schedulers/mod.rs +@@ -26,6 +26,9 @@ pub use accounting::CoverageAccountingScheduler; + pub mod weighted; + pub use weighted::{StdWeightedScheduler, WeightedScheduler}; + ++pub mod prescient_weighted; ++pub use prescient_weighted::{PrescientProbabilitySamplingScheduler, ProbabilityMetadata}; ++ + pub mod tuneable; + use libafl_bolts::{ + rands::Rand, +diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs +new file mode 100644 +index 00000000..6761c534 +--- /dev/null ++++ b/libafl/src/schedulers/prescient_weighted.rs +@@ -0,0 +1,428 @@ ++//! Prescient Weighted sampling scheduler is a corpus scheduler that feeds the fuzzer ++ ++use std::vec::Vec; ++use hashbrown::HashSet; ++use alloc::string::String; ++use core::{marker::PhantomData, fmt::Debug}; ++ ++use hashbrown::HashMap; ++use libafl_bolts::rands::Rand; ++use libafl_bolts::HasLen; ++use serde::{Deserialize, Serialize}; ++use std::time::{Instant, SystemTime, UNIX_EPOCH}; ++ ++use crate::{ ++ HasMetadata, HasNamedMetadata, ++ corpus::{testcase::TestcaseMutationsMetadata, Corpus, CorpusId, HasTestcase}, ++ feedbacks::{cfg_prescience::{ControlFlowGraph, Reachability}, ++ MapIndexesMetadata, ++ MapNeighboursFeedbackMetadata, ++ MapNoveltiesMetadata}, ++ inputs::UsesInput, ++ schedulers::Scheduler, ++ state::{HasCorpus, HasRand, State, UsesState}, Error ++}; ++ ++/// Calculate Testcase probabilities using prescience ++#[derive(Debug, Clone)] ++pub struct PrescientProbabilitySamplingScheduler ++where ++ S: UsesInput, ++{ ++ backoff_factor: f64, ++ phantom: PhantomData, ++} ++ ++/// A state metadata holding a map of probability of corpus elements. ++#[derive(Debug, Serialize, Deserialize)] ++#[cfg_attr( ++ any(not(feature = "serdeany_autoreg"), miri), ++ allow(clippy::unsafe_derive_deserialize) ++)] // for SerdeAny ++pub struct ProbabilityMetadata { ++ /// corpus index -> probability ++ pub map: HashMap, ++ /// total probability of all items in the map ++ pub total_probability: f64, ++ /// Do we need to recalculate the scores? ++ pub needs_recalc: bool, ++ /// The time that we last recalculated all the scores (in millis) ++ pub last_recalc_time: u128, ++ /// The amount of time the last recalc took ++ pub last_recalc_duration: u128, ++} ++ ++libafl_bolts::impl_serdeany!(ProbabilityMetadata); ++ ++impl ProbabilityMetadata { ++ /// Creates a new [`struct@ProbabilityMetadata`] ++ #[must_use] ++ pub fn new() -> Self { ++ Self { ++ map: HashMap::default(), ++ total_probability: 0.0, ++ needs_recalc: false, ++ last_recalc_time: 0, ++ last_recalc_duration: 0, ++ } ++ } ++} ++ ++impl Default for ProbabilityMetadata { ++ fn default() -> Self { ++ Self::new() ++ } ++} ++ ++struct ReachableBlocksResult { ++ /// Number of corpus entries this reachability appears in ++ frequency_for_reachability: HashMap, ++ /// Cumulative number of times corpus entries directly neighbouring (ie depth 1) ++ /// this coverage map index have been mutated ++ direct_neighbour_mutations_for_index: HashMap, ++ /// Lowest depth observed for the given index ++ least_depth_for_index: HashMap, ++} ++ ++ ++impl PrescientProbabilitySamplingScheduler ++where ++ S: HasCorpus + HasMetadata + HasNamedMetadata + HasRand, ++ S::Input: HasLen, ++{ ++ /// Creates a new [`struct@ProbabilitySamplingScheduler`] ++ #[must_use] ++ pub fn new_with_backoff(backoff_factor: f64) -> Self { ++ Self { ++ backoff_factor, ++ phantom: PhantomData, ++ } ++ } ++ ++ /// Calculate the score and store in `ProbabilityMetadata` ++ #[allow(clippy::cast_precision_loss)] ++ #[allow(clippy::unused_self)] ++ pub fn store_probability(&self, _state: &mut S, _idx: CorpusId) -> Result<(), Error> { ++ assert!(false, "Should not use anymore"); ++ ++ Ok(()) ++ } ++ ++ /// return a map of {(index, depth): frequency}, where frequency is the number of testcases ++ /// with this index being reachable at the given depth ++ fn recalculate_reachable_blocks(&self, state: &mut S) -> ReachableBlocksResult { ++ let mut result = ReachableBlocksResult { ++ frequency_for_reachability: HashMap::new(), ++ direct_neighbour_mutations_for_index: HashMap::new(), ++ least_depth_for_index: HashMap::new(), ++ }; ++ let start = Instant::now(); ++ ++ let all_ids = state.corpus().ids().collect::>(); ++ ++ let full_neighbours_meta = state ++ .metadata_mut::() ++ .unwrap(); ++ ++ let covered_blocks = full_neighbours_meta.covered_blocks.clone(); ++ let last_recalc_corpus_ids = full_neighbours_meta.corpus_ids_present_at_recalc.clone(); ++ full_neighbours_meta.corpus_ids_present_at_recalc = all_ids.clone(); ++ ++ let mut recalcs = 0; ++ for &idx in &all_ids { ++ recalcs += 1; ++ ++ let tc = state.corpus().get(idx).unwrap().borrow(); ++ let covered_meta = tc.metadata::().unwrap(); ++ let covered_indexes = covered_meta.list.clone(); ++ let num_mutations = if let Ok(meta) = tc.metadata::() { ++ meta.num_mutations_executed ++ } else { ++ 0 ++ }; ++ drop(tc); ++ ++ let reachabilities = { ++ let cfg_metadata = state.metadata_mut::().unwrap(); ++ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) ++ }; ++ ++ if !last_recalc_corpus_ids.contains(&idx) { ++ let tc = state.corpus().get(idx).unwrap().borrow(); ++ let novelties_meta = tc.metadata::().unwrap(); ++ let novelties = novelties_meta.list.clone(); ++ drop(tc); ++ ++ let full_neighbours_meta = state ++ .metadata_mut::() ++ .unwrap(); ++ ++ for novelty in novelties { ++ full_neighbours_meta.reachable_blocks.remove(&novelty); ++ } ++ ++ for reachability in &reachabilities { ++ full_neighbours_meta.reachable_blocks.insert(reachability.index); ++ } ++ } ++ ++ for reachability in reachabilities { ++ // update reachability frequencies ++ let new = if let Some(freq) = result.frequency_for_reachability.get(&reachability) { ++ freq + 1 ++ } else { ++ 1 ++ }; ++ result.frequency_for_reachability.insert(reachability.clone(), new); ++ ++ // update number of mutations of direct neighbours (if appropriate) ++ if reachability.depth == 1 { ++ let updated = if let Some(freq) = result.direct_neighbour_mutations_for_index.get(&reachability.index) { ++ freq + num_mutations ++ } else { ++ num_mutations ++ }; ++ result.direct_neighbour_mutations_for_index.insert(reachability.index, updated); ++ } ++ ++ // update least depth for index (if we beat the previous depth) ++ if let Some(cur_min) = result.least_depth_for_index.get(&reachability.index) { ++ if reachability.depth < *cur_min { ++ result.least_depth_for_index.insert(reachability.index, reachability.depth); ++ } ++ } else { ++ result.least_depth_for_index.insert(reachability.index, reachability.depth); ++ } ++ } ++ } ++ ++ println!("Whew, recalced all neighbours for {recalcs} entries (out of a possible {}); took: {:.2?}", all_ids.len(), start.elapsed()); ++ ++ result ++ } ++ ++ /// Recalculate the probability of each testcase being selected for mutation ++ pub fn recalc_all_probabilities(&self, state: &mut S) -> Result<(), Error> { ++ let reachable_blocks_result = self.recalculate_reachable_blocks(state); ++ ++ let full_neighbours_meta = state ++ .metadata::() ++ .unwrap(); ++ let _reachable_all = full_neighbours_meta.reachable_blocks.clone(); ++ let covered_blocks = full_neighbours_meta.covered_blocks.clone(); ++ ++ let mut total_score = 0.0; ++ ++ let ids = state.corpus().ids().collect::>(); ++ let corpus_size = ids.len(); ++ let mut min_time = f64::MAX; ++ ++ // sort entries by time ++ let mut time_ordered = vec![]; ++ let mut min_len = 99999999f64; ++ let mut len_for_id = HashMap::new(); ++ for &id in &ids { ++ let mut tc = state.corpus().get(id)?.borrow_mut(); ++ let len = tc.load_len(state.corpus()).unwrap() as f64; ++ if len < min_len { min_len = len; } ++ len_for_id.insert(id, len); ++ let exec_time_ns = tc.exec_time().unwrap().as_nanos() as f64; ++ if exec_time_ns < min_time { min_time = exec_time_ns; } ++ time_ordered.push((id, exec_time_ns * len)); ++ } ++ time_ordered.sort_by(|(_id, score1), (_id2, score2)| score1.partial_cmp(score2).unwrap()); ++ ++ // The more this neighbour has been fuzzed, the less we'll prioritise it (maybe it's hard or infeasible) ++ let backoff_weighting_for_direct_neighbour = { ++ let mut weighting = HashMap::new(); ++ for (&index, &mutations) in &reachable_blocks_result.direct_neighbour_mutations_for_index { ++ let decrements = mutations / 1_000; ++ weighting.insert(index, self.backoff_factor.powi(decrements as i32)); ++ } ++ weighting ++ }; ++ ++ let mut favored_filled = HashSet::with_capacity(65536); ++ let mut reachability_favored_ids = HashSet::new(); ++ let mut coverage_favored_ids = HashSet::new(); ++ let mut favored_edges = HashSet::new(); ++ let mut all_covered = HashSet::new(); ++ let mut neighbour_score_for_idx = HashMap::new(); ++ ++ // greedily select a minimal subset of testcases that cover all neighbours (based on runtime) ++ for &(entry, _runtime) in &time_ordered { ++ let tc = state.corpus().get(entry)?.borrow(); ++ let idx_meta = tc.metadata::().unwrap(); ++ for &edge in &idx_meta.list { all_covered.insert(edge); } ++ ++ let mut neighbour_score = 0f64; ++ let mut reachability_favored = false; ++ ++ let covered_indexes = idx_meta.list.clone(); ++ drop(tc); ++ ++ let reachabilities = { ++ let cfg_metadata = state.metadata_mut::().unwrap(); ++ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) ++ }; ++ ++ let tc = state.corpus().get(entry)?.borrow(); ++ let idx_meta = tc.metadata::().unwrap(); ++ for reachability in reachabilities { ++ // Only keep this if it's the best depth we've seen for this edge ++ if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { ++ let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); ++ if freq.is_none() { println!("frequency is none for {:?}", reachability); } ++ let rarity = 1f64 / *freq.unwrap() as f64; ++ let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); ++ if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } ++ neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; ++ reachability_favored |= favored_filled.insert(reachability.index); ++ } ++ } ++ neighbour_score_for_idx.insert(entry, neighbour_score); ++ ++ let mut coverage_favored = false; ++ for &edge in &idx_meta.list { ++ coverage_favored |= favored_edges.insert(edge); ++ } ++ ++ if reachability_favored { ++ reachability_favored_ids.insert(entry); ++ } else if coverage_favored { ++ coverage_favored_ids.insert(entry); ++ } ++ } ++ ++ let skipped = all_covered.difference(&favored_edges).copied().collect::>(); ++ println!("Minimised the testset from {corpus_size} down to {} favored entries - and {} somewhat favored (favored edges: {}, missed out {} entries: {:?})", ++ reachability_favored_ids.len(), coverage_favored_ids.len(), ++ favored_edges.len(), skipped.len(), skipped); ++ ++ let mut all_scores = vec![]; ++ for entry in ids { ++ let tc = state.corpus().get(entry)?.borrow(); ++ let mut score = neighbour_score_for_idx[&entry]; ++ ++ let exec_time_us = tc.exec_time().unwrap().as_nanos() as f64; ++ let time_weighting = min_time / exec_time_us; ++ score *= time_weighting; ++ ++ all_scores.push((entry, score)); ++ ++ total_score += score; ++ ++ drop(tc); ++ let meta = state ++ .metadata_map_mut() ++ .get_mut::() ++ .unwrap(); ++ meta.map.insert(entry, score); ++ } ++ ++ // all_scores.sort_by(|(_, score1), (_, score2)| score1.partial_cmp(score2).unwrap()); ++ // println!("Scores: {:?}", all_scores); ++ ++ let meta = state ++ .metadata_map_mut() ++ .get_mut::() ++ .unwrap(); ++ meta.total_probability = total_score; ++ ++ Ok(()) ++ } ++} ++ ++impl UsesState for PrescientProbabilitySamplingScheduler ++where ++ S: State + HasTestcase, ++{ ++ type State = S; ++} ++ ++impl Scheduler for PrescientProbabilitySamplingScheduler ++where ++ S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand + HasTestcase + State, ++ S::Input: HasLen, ++{ ++ fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> { ++ let current_idx = *state.corpus().current(); ++ state ++ .corpus() ++ .get(idx)? ++ .borrow_mut() ++ .set_parent_id_optional(current_idx); ++ ++ if state.metadata_map().get::().is_none() { ++ state.add_metadata(ProbabilityMetadata::new()); ++ } ++ ++ let prob_meta = state.metadata_map_mut().get_mut::().unwrap(); ++ prob_meta.needs_recalc = true; ++ let avg = prob_meta.total_probability / prob_meta.map.len() as f64; ++ prob_meta.map.insert(idx, avg); ++ prob_meta.total_probability += avg; ++ ++ // let max = prob_meta.map.values().fold(0f64, |max, &v| if v > max { v } else { max }); ++ // prob_meta.map.insert(idx, max); ++ // prob_meta.total_probability += max; ++ ++ Ok(()) ++ } ++ ++ /// Gets the next entry ++ #[allow(clippy::cast_precision_loss)] ++ fn next(&mut self, state: &mut Self::State) -> Result { ++ if state.corpus().count() == 0 { ++ Err(Error::empty(String::from("No entries in corpus"))) ++ } else { ++ const MAX_RAND: u64 = 1_000_000; ++ let rand_prob: f64 = (state.rand_mut().below(MAX_RAND as usize) as f64) / MAX_RAND as f64; ++ ++ let meta = state.metadata_map_mut().get_mut::().unwrap(); ++ if meta.needs_recalc { ++ let ts_now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(); ++ let time_since_recalc = ts_now - meta.last_recalc_time; ++ let last_duration = meta.last_recalc_duration; ++ // Don't spend more than 10% of the fuzzer time recalculating these stats - sure ++ // this feels like we're not using the neighbours prescient power much at the start ++ // of the campaign, but fuzzing campaigns last hours... ++ if time_since_recalc >= (10 * last_duration) { ++ println!("Last recalc took {last_duration}ms, now recalcing as it has been {time_since_recalc}"); ++ let start = Instant::now(); ++ self.recalculate_reachable_blocks(state); ++ self.recalc_all_probabilities(state).unwrap(); ++ ++ let meta = state.metadata_map_mut().get_mut::().unwrap(); ++ meta.needs_recalc = false; ++ meta.last_recalc_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(); ++ meta.last_recalc_duration = start.elapsed().as_millis(); ++ } ++ } ++ ++ let meta = state.metadata_map().get::().unwrap(); ++ let threshold = meta.total_probability * rand_prob; ++ let mut k: f64 = 0.0; ++ let mut ret = *meta.map.keys().last().unwrap(); ++ for (idx, prob) in &meta.map { ++ k += prob; ++ if k >= threshold { ++ ret = *idx; ++ break; ++ } ++ } ++ self.set_current_scheduled(state, Some(ret))?; ++ Ok(ret) ++ } ++ } ++} ++ ++impl Default for PrescientProbabilitySamplingScheduler ++where ++ S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand, ++ S::Input: HasLen, ++{ ++ fn default() -> Self { ++ Self::new_with_backoff(0.9999) ++ } ++} +\ No newline at end of file +diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs +index 69781524..9d097043 100644 +--- a/libafl/src/stages/mutational.rs ++++ b/libafl/src/stages/mutational.rs +@@ -117,10 +117,10 @@ where + let num = self.iterations(state)?; + let mut testcase = state.current_testcase_mut()?; + if let Ok(meta) = testcase.metadata_mut::() { +- meta.num_mutations_executed += num as usize; ++ meta.num_mutations_executed += num; + } else { + testcase.add_metadata( +- TestcaseMutationsMetadata { num_mutations_executed: num as usize } ++ TestcaseMutationsMetadata { num_mutations_executed: num } + ); + } + diff --git a/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/runner.Dockerfile b/fuzzers/prescientfuzz_19f5081/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_depth_const_1/prescientfuzz/runner.Dockerfile rename to fuzzers/prescientfuzz_19f5081/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_depth_const_1/patch b/fuzzers/prescientfuzz_depth_const_1/patch deleted file mode 100644 index 908ebf208..000000000 --- a/fuzzers/prescientfuzz_depth_const_1/patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/libafl/src/schedulers/probabilistic_sampling.rs b/libafl/src/schedulers/probabilistic_sampling.rs -index fd552a3d..b9cfc10d 100644 ---- a/libafl/src/schedulers/probabilistic_sampling.rs -+++ b/libafl/src/schedulers/probabilistic_sampling.rs -@@ -294,7 +294,7 @@ where - let rarity = 1f64 / *freq.unwrap() as f64; - let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); - if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } -- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; -+ neighbour_score += backoff_weighting.unwrap() * rarity; // * 1f64 / reachability.depth as f64; - reachability_favored |= favored_filled.insert(reachability.index); - } - } diff --git a/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/builder.Dockerfile deleted file mode 100644 index 2449a3b14..000000000 --- a/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/builder.Dockerfile +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ARG parent_image -FROM $parent_image - -# Uninstall old Rust & Install the latest one. -RUN if which rustup; then rustup self uninstall -y; fi && \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh -y && \ - /root/.cargo/bin/rustup toolchain install nightly && \ - rm /rustup.sh - -RUN apt-get update && \ - apt-get install -y \ - build-essential \ - cargo && \ - apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ - libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ - apt-utils apt-transport-https ca-certificates joe curl && \ - PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make - -# Download PrescientFuzz -RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 - -# Compile PrescientFuzz. -RUN cd /PrescientFuzz && \ - unset CFLAGS CXXFLAGS && \ - export CC=clang AFL_NO_X86 && \ - export LIBAFL_EDGES_MAP_SIZE=2621440 && \ - cd ./fuzzers/fuzzbench && \ - PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main - -# Auxiliary weak references. -RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ - clang -c stub_rt.c && \ - ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/description.md b/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/description.md deleted file mode 100644 index 452b0e374..000000000 --- a/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/description.md +++ /dev/null @@ -1,8 +0,0 @@ -# PrescientFuzz - -based on libafl fuzzer instance - - persistent mode - -[builder.Dockerfile](builder.Dockerfile) -[fuzzer.py](fuzzer.py) -[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/fuzzer.py b/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/fuzzer.py deleted file mode 100755 index 4f4601c91..000000000 --- a/fuzzers/prescientfuzz_depth_const_1/prescientfuzz/fuzzer.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -"""Integration code for a LibAFL-based fuzzer.""" - -import os -import sys -import subprocess -from pathlib import Path - -from fuzzers import utils - - -def prepare_fuzz_environment(input_corpus): - """Prepare to fuzz with a LibAFL-based fuzzer.""" - os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ - 'malloc_context_size=0:symbolize=0:'\ - 'allocator_may_return_null=1:'\ - 'detect_odr_violation=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_abort=0:'\ - 'handle_sigfpe=0:handle_sigill=0' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ - 'allocator_release_to_os_interval_ms=500:'\ - 'handle_abort=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_sigfpe=0:'\ - 'handle_sigill=0:print_stacktrace=0:'\ - 'symbolize=0:symbolize_inline_frames=0' - # Create at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def build(): - """Build benchmark.""" - os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') - os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cxx') - - os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' - - cflags = ['--libafl'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - utils.append_flags('LDFLAGS', cflags) - - os.environ['RANLIB'] = 'llvm-ranlib' - os.environ['AR'] = 'llvm-ar' - os.environ['AS'] = 'llvm-as' - os.environ['FUZZER_LIB'] = '/stub_rt.a' - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - Path(cfg_file).touch() - os.environ['AFL_LLVM_CFG_FILE'] = cfg_file - utils.build_benchmark() - - -def fuzz(input_corpus, output_corpus, target_binary): - """Run fuzzer.""" - prepare_fuzz_environment(input_corpus) - dictionary_path = utils.get_dictionary_path(target_binary) - command = [target_binary] - if dictionary_path: - command += (['-x', dictionary_path]) - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - if os.path.exists(cfg_file): - command += (['-c', cfg_file]) - else: - sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) - fuzzer_env = os.environ.copy() - fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' - print(command) - subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_depth_squared/builder.Dockerfile b/fuzzers/prescientfuzz_depth_squared/builder.Dockerfile deleted file mode 100644 index 2c5acf685..000000000 --- a/fuzzers/prescientfuzz_depth_squared/builder.Dockerfile +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ARG parent_image -FROM $parent_image - -# Uninstall old Rust & Install the latest one. -RUN if which rustup; then rustup self uninstall -y; fi && \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh -y && \ - /root/.cargo/bin/rustup toolchain install nightly && \ - rm /rustup.sh - -RUN apt-get update && \ - apt-get install -y \ - build-essential \ - cargo && \ - apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ - libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ - apt-utils apt-transport-https ca-certificates joe curl && \ - PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make - -# Download PrescientFuzz -RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -COPY ./patch /PrescientFuzz/patch -RUN cd /PrescientFuzz && git fetch && git checkout 543074581cdd98d747c7e625745dab7ade5799d3 && git apply patch - -# Compile PrescientFuzz. -RUN cd /PrescientFuzz && \ - unset CFLAGS CXXFLAGS && \ - export CC=clang AFL_NO_X86 && \ - export LIBAFL_EDGES_MAP_SIZE=2621440 && \ - cd ./fuzzers/fuzzbench && \ - PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main - -# Auxiliary weak references. -RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ - clang -c stub_rt.c && \ - ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_depth_squared/description.md b/fuzzers/prescientfuzz_depth_squared/description.md deleted file mode 100644 index 452b0e374..000000000 --- a/fuzzers/prescientfuzz_depth_squared/description.md +++ /dev/null @@ -1,8 +0,0 @@ -# PrescientFuzz - -based on libafl fuzzer instance - - persistent mode - -[builder.Dockerfile](builder.Dockerfile) -[fuzzer.py](fuzzer.py) -[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_depth_squared/patch b/fuzzers/prescientfuzz_depth_squared/patch deleted file mode 100644 index 8e2974b31..000000000 --- a/fuzzers/prescientfuzz_depth_squared/patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/libafl/src/schedulers/probabilistic_sampling.rs b/libafl/src/schedulers/probabilistic_sampling.rs -index fd552a3d..af70e4cf 100644 ---- a/libafl/src/schedulers/probabilistic_sampling.rs -+++ b/libafl/src/schedulers/probabilistic_sampling.rs -@@ -294,7 +294,7 @@ where - let rarity = 1f64 / *freq.unwrap() as f64; - let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); - if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } -- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; -+ neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / (reachability.depth as f64).powi(2); - reachability_favored |= favored_filled.insert(reachability.index); - } - } diff --git a/fuzzers/prescientfuzz_depth_squared/prescientfuzz/description.md b/fuzzers/prescientfuzz_depth_squared/prescientfuzz/description.md deleted file mode 100644 index 452b0e374..000000000 --- a/fuzzers/prescientfuzz_depth_squared/prescientfuzz/description.md +++ /dev/null @@ -1,8 +0,0 @@ -# PrescientFuzz - -based on libafl fuzzer instance - - persistent mode - -[builder.Dockerfile](builder.Dockerfile) -[fuzzer.py](fuzzer.py) -[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_depth_squared/prescientfuzz/fuzzer.py b/fuzzers/prescientfuzz_depth_squared/prescientfuzz/fuzzer.py deleted file mode 100755 index 4f4601c91..000000000 --- a/fuzzers/prescientfuzz_depth_squared/prescientfuzz/fuzzer.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -"""Integration code for a LibAFL-based fuzzer.""" - -import os -import sys -import subprocess -from pathlib import Path - -from fuzzers import utils - - -def prepare_fuzz_environment(input_corpus): - """Prepare to fuzz with a LibAFL-based fuzzer.""" - os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ - 'malloc_context_size=0:symbolize=0:'\ - 'allocator_may_return_null=1:'\ - 'detect_odr_violation=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_abort=0:'\ - 'handle_sigfpe=0:handle_sigill=0' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ - 'allocator_release_to_os_interval_ms=500:'\ - 'handle_abort=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_sigfpe=0:'\ - 'handle_sigill=0:print_stacktrace=0:'\ - 'symbolize=0:symbolize_inline_frames=0' - # Create at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def build(): - """Build benchmark.""" - os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') - os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cxx') - - os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' - - cflags = ['--libafl'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - utils.append_flags('LDFLAGS', cflags) - - os.environ['RANLIB'] = 'llvm-ranlib' - os.environ['AR'] = 'llvm-ar' - os.environ['AS'] = 'llvm-as' - os.environ['FUZZER_LIB'] = '/stub_rt.a' - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - Path(cfg_file).touch() - os.environ['AFL_LLVM_CFG_FILE'] = cfg_file - utils.build_benchmark() - - -def fuzz(input_corpus, output_corpus, target_binary): - """Run fuzzer.""" - prepare_fuzz_environment(input_corpus) - dictionary_path = utils.get_dictionary_path(target_binary) - command = [target_binary] - if dictionary_path: - command += (['-x', dictionary_path]) - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - if os.path.exists(cfg_file): - command += (['-c', cfg_file]) - else: - sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) - fuzzer_env = os.environ.copy() - fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' - print(command) - subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_depth_squared/prescientfuzz/runner.Dockerfile b/fuzzers/prescientfuzz_depth_squared/prescientfuzz/runner.Dockerfile deleted file mode 100644 index 1a023b81e..000000000 --- a/fuzzers/prescientfuzz_depth_squared/prescientfuzz/runner.Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FROM gcr.io/fuzzbench/base-image - -RUN apt install libjemalloc2 - -# This makes interactive docker runs painless: -ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" -ENV AFL_MAP_SIZE=2621440 -ENV PATH="$PATH:/out" -ENV AFL_SKIP_CPUFREQ=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 -ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_depth_squared/runner.Dockerfile b/fuzzers/prescientfuzz_depth_squared/runner.Dockerfile deleted file mode 100644 index 1a023b81e..000000000 --- a/fuzzers/prescientfuzz_depth_squared/runner.Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FROM gcr.io/fuzzbench/base-image - -RUN apt install libjemalloc2 - -# This makes interactive docker runs painless: -ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" -ENV AFL_MAP_SIZE=2621440 -ENV PATH="$PATH:/out" -ENV AFL_SKIP_CPUFREQ=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 -ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_nn/builder.Dockerfile b/fuzzers/prescientfuzz_nn/builder.Dockerfile deleted file mode 100644 index 2c5acf685..000000000 --- a/fuzzers/prescientfuzz_nn/builder.Dockerfile +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ARG parent_image -FROM $parent_image - -# Uninstall old Rust & Install the latest one. -RUN if which rustup; then rustup self uninstall -y; fi && \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh -y && \ - /root/.cargo/bin/rustup toolchain install nightly && \ - rm /rustup.sh - -RUN apt-get update && \ - apt-get install -y \ - build-essential \ - cargo && \ - apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ - libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ - apt-utils apt-transport-https ca-certificates joe curl && \ - PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make - -# Download PrescientFuzz -RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -COPY ./patch /PrescientFuzz/patch -RUN cd /PrescientFuzz && git fetch && git checkout 543074581cdd98d747c7e625745dab7ade5799d3 && git apply patch - -# Compile PrescientFuzz. -RUN cd /PrescientFuzz && \ - unset CFLAGS CXXFLAGS && \ - export CC=clang AFL_NO_X86 && \ - export LIBAFL_EDGES_MAP_SIZE=2621440 && \ - cd ./fuzzers/fuzzbench && \ - PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main - -# Auxiliary weak references. -RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ - clang -c stub_rt.c && \ - ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_nn/description.md b/fuzzers/prescientfuzz_nn/description.md deleted file mode 100644 index 452b0e374..000000000 --- a/fuzzers/prescientfuzz_nn/description.md +++ /dev/null @@ -1,8 +0,0 @@ -# PrescientFuzz - -based on libafl fuzzer instance - - persistent mode - -[builder.Dockerfile](builder.Dockerfile) -[fuzzer.py](fuzzer.py) -[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_nn/fuzzer.py b/fuzzers/prescientfuzz_nn/fuzzer.py deleted file mode 100755 index 5f2dfa95f..000000000 --- a/fuzzers/prescientfuzz_nn/fuzzer.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -"""Integration code for a LibAFL-based fuzzer.""" - -import os -import sys -import subprocess -from pathlib import Path - -from fuzzers import utils - - -def prepare_fuzz_environment(input_corpus): - """Prepare to fuzz with a LibAFL-based fuzzer.""" - os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ - 'malloc_context_size=0:symbolize=0:'\ - 'allocator_may_return_null=1:'\ - 'detect_odr_violation=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_abort=0:'\ - 'handle_sigfpe=0:handle_sigill=0' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ - 'allocator_release_to_os_interval_ms=500:'\ - 'handle_abort=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_sigfpe=0:'\ - 'handle_sigill=0:print_stacktrace=0:'\ - 'symbolize=0:symbolize_inline_frames=0' - # Create at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def build(): - """Build benchmark.""" - os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') - os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cxx') - - os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' - - cflags = ['--libafl'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - utils.append_flags('LDFLAGS', cflags) - - os.environ['FUZZER_LIB'] = '/stub_rt.a' - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - Path(cfg_file).touch() - os.environ['AFL_LLVM_CFG_FILE'] = cfg_file - utils.build_benchmark() - - -def fuzz(input_corpus, output_corpus, target_binary): - """Run fuzzer.""" - prepare_fuzz_environment(input_corpus) - dictionary_path = utils.get_dictionary_path(target_binary) - command = [target_binary] - if dictionary_path: - command += (['-x', dictionary_path]) - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - if os.path.exists(cfg_file): - command += (['-c', cfg_file]) - else: - sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) - fuzzer_env = os.environ.copy() - fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' - print(command) - subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_nn/patch b/fuzzers/prescientfuzz_nn/patch deleted file mode 100644 index bd29686d2..000000000 --- a/fuzzers/prescientfuzz_nn/patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/libafl/src/schedulers/probabilistic_sampling.rs b/libafl/src/schedulers/probabilistic_sampling.rs -index fd552a3d..08f92646 100644 ---- a/libafl/src/schedulers/probabilistic_sampling.rs -+++ b/libafl/src/schedulers/probabilistic_sampling.rs -@@ -288,7 +288,7 @@ where - let idx_meta = tc.metadata::().unwrap(); - for reachability in reachabilities { - // Only keep this if it's the best depth we've seen for this edge -- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { -+ if reachability.depth == 1 { //reachable_blocks_result.least_depth_for_index[&reachability.index] { - let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); - if freq.is_none() { println!("frequency is none for {:?}", reachability); } - let rarity = 1f64 / *freq.unwrap() as f64; diff --git a/fuzzers/prescientfuzz_nn/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz_nn/prescientfuzz/builder.Dockerfile deleted file mode 100644 index 2449a3b14..000000000 --- a/fuzzers/prescientfuzz_nn/prescientfuzz/builder.Dockerfile +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ARG parent_image -FROM $parent_image - -# Uninstall old Rust & Install the latest one. -RUN if which rustup; then rustup self uninstall -y; fi && \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh -y && \ - /root/.cargo/bin/rustup toolchain install nightly && \ - rm /rustup.sh - -RUN apt-get update && \ - apt-get install -y \ - build-essential \ - cargo && \ - apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ - libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ - apt-utils apt-transport-https ca-certificates joe curl && \ - PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make - -# Download PrescientFuzz -RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 814bcd19628ef994a36228d78f1bc002a70d1260 - -# Compile PrescientFuzz. -RUN cd /PrescientFuzz && \ - unset CFLAGS CXXFLAGS && \ - export CC=clang AFL_NO_X86 && \ - export LIBAFL_EDGES_MAP_SIZE=2621440 && \ - cd ./fuzzers/fuzzbench && \ - PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main - -# Auxiliary weak references. -RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ - clang -c stub_rt.c && \ - ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_nn/prescientfuzz/description.md b/fuzzers/prescientfuzz_nn/prescientfuzz/description.md deleted file mode 100644 index 452b0e374..000000000 --- a/fuzzers/prescientfuzz_nn/prescientfuzz/description.md +++ /dev/null @@ -1,8 +0,0 @@ -# PrescientFuzz - -based on libafl fuzzer instance - - persistent mode - -[builder.Dockerfile](builder.Dockerfile) -[fuzzer.py](fuzzer.py) -[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_nn/prescientfuzz/fuzzer.py b/fuzzers/prescientfuzz_nn/prescientfuzz/fuzzer.py deleted file mode 100755 index 4f4601c91..000000000 --- a/fuzzers/prescientfuzz_nn/prescientfuzz/fuzzer.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -"""Integration code for a LibAFL-based fuzzer.""" - -import os -import sys -import subprocess -from pathlib import Path - -from fuzzers import utils - - -def prepare_fuzz_environment(input_corpus): - """Prepare to fuzz with a LibAFL-based fuzzer.""" - os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ - 'malloc_context_size=0:symbolize=0:'\ - 'allocator_may_return_null=1:'\ - 'detect_odr_violation=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_abort=0:'\ - 'handle_sigfpe=0:handle_sigill=0' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ - 'allocator_release_to_os_interval_ms=500:'\ - 'handle_abort=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_sigfpe=0:'\ - 'handle_sigill=0:print_stacktrace=0:'\ - 'symbolize=0:symbolize_inline_frames=0' - # Create at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def build(): - """Build benchmark.""" - os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') - os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cxx') - - os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' - - cflags = ['--libafl'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - utils.append_flags('LDFLAGS', cflags) - - os.environ['RANLIB'] = 'llvm-ranlib' - os.environ['AR'] = 'llvm-ar' - os.environ['AS'] = 'llvm-as' - os.environ['FUZZER_LIB'] = '/stub_rt.a' - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - Path(cfg_file).touch() - os.environ['AFL_LLVM_CFG_FILE'] = cfg_file - utils.build_benchmark() - - -def fuzz(input_corpus, output_corpus, target_binary): - """Run fuzzer.""" - prepare_fuzz_environment(input_corpus) - dictionary_path = utils.get_dictionary_path(target_binary) - command = [target_binary] - if dictionary_path: - command += (['-x', dictionary_path]) - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - if os.path.exists(cfg_file): - command += (['-c', cfg_file]) - else: - sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) - fuzzer_env = os.environ.copy() - fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' - print(command) - subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_nn/prescientfuzz/runner.Dockerfile b/fuzzers/prescientfuzz_nn/prescientfuzz/runner.Dockerfile deleted file mode 100644 index 1a023b81e..000000000 --- a/fuzzers/prescientfuzz_nn/prescientfuzz/runner.Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FROM gcr.io/fuzzbench/base-image - -RUN apt install libjemalloc2 - -# This makes interactive docker runs painless: -ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" -ENV AFL_MAP_SIZE=2621440 -ENV PATH="$PATH:/out" -ENV AFL_SKIP_CPUFREQ=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 -ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_nn/runner.Dockerfile b/fuzzers/prescientfuzz_nn/runner.Dockerfile deleted file mode 100644 index 1a023b81e..000000000 --- a/fuzzers/prescientfuzz_nn/runner.Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FROM gcr.io/fuzzbench/base-image - -RUN apt install libjemalloc2 - -# This makes interactive docker runs painless: -ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" -ENV AFL_MAP_SIZE=2621440 -ENV PATH="$PATH:/out" -ENV AFL_SKIP_CPUFREQ=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 -ENV AFL_TESTCACHE_SIZE=2 From 9aa3c81b6f0dddec7911c8b000ed2b057468aa12 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Fri, 24 May 2024 16:52:49 +0100 Subject: [PATCH 16/25] Set to merge with the other fuzzers --- service/experiment-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/experiment-config.yaml b/service/experiment-config.yaml index 9ed2887d0..bd829361b 100644 --- a/service/experiment-config.yaml +++ b/service/experiment-config.yaml @@ -15,7 +15,7 @@ preemptible_runners: true # This experiment should generate a report that is combined with other public # "production" experiments. -merge_with_nonprivate: false +merge_with_nonprivate: true # This experiment should be merged with other reports in later experiments. private: false From 3cb14a612264add3745d6b9f1eed8504ee50393e Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Mon, 3 Jun 2024 21:25:04 +0100 Subject: [PATCH 17/25] Setup to test features with new libafl version --- fuzzers/libafl_19f5081/description.md | 11 - fuzzers/libafl_19f5081/patch | 55 -- fuzzers/prescientfuzz/patch | 569 ------------------ fuzzers/prescientfuzz_19f5081/patch | 569 ------------------ .../builder.Dockerfile | 3 +- .../description.md | 0 .../fuzzer.py | 0 fuzzers/prescientfuzz_all_no_mopt/patch | 27 + .../runner.Dockerfile | 0 .../builder.Dockerfile | 3 +- .../description.md | 0 .../fuzzer.py | 0 fuzzers/prescientfuzz_direct_neighbours/patch | 22 + .../runner.Dockerfile | 0 .../builder.Dockerfile | 36 +- .../prescientfuzz_reachable/description.md | 8 + .../fuzzer.py | 27 +- fuzzers/prescientfuzz_reachable/patch | 18 + .../runner.Dockerfile | 2 +- .../builder.Dockerfile | 50 ++ .../description.md | 8 + .../prescientfuzz_reachable_rarity/fuzzer.py | 83 +++ fuzzers/prescientfuzz_reachable_rarity/patch | 16 + .../runner.Dockerfile | 25 + .../builder.Dockerfile | 50 ++ .../description.md | 8 + .../fuzzer.py | 83 +++ .../patch | 13 + .../runner.Dockerfile | 25 + .../builder.Dockerfile | 50 ++ .../description.md | 8 + .../fuzzer.py | 83 +++ .../patch | 0 .../runner.Dockerfile | 25 + 34 files changed, 639 insertions(+), 1238 deletions(-) delete mode 100644 fuzzers/libafl_19f5081/description.md delete mode 100644 fuzzers/libafl_19f5081/patch delete mode 100644 fuzzers/prescientfuzz/patch delete mode 100644 fuzzers/prescientfuzz_19f5081/patch rename fuzzers/{prescientfuzz => prescientfuzz_all_no_mopt}/builder.Dockerfile (95%) rename fuzzers/{prescientfuzz => prescientfuzz_all_no_mopt}/description.md (100%) rename fuzzers/{prescientfuzz => prescientfuzz_all_no_mopt}/fuzzer.py (100%) create mode 100644 fuzzers/prescientfuzz_all_no_mopt/patch rename fuzzers/{prescientfuzz => prescientfuzz_all_no_mopt}/runner.Dockerfile (100%) rename fuzzers/{prescientfuzz_19f5081 => prescientfuzz_direct_neighbours}/builder.Dockerfile (92%) rename fuzzers/{prescientfuzz_19f5081 => prescientfuzz_direct_neighbours}/description.md (100%) rename fuzzers/{prescientfuzz_19f5081 => prescientfuzz_direct_neighbours}/fuzzer.py (100%) create mode 100644 fuzzers/prescientfuzz_direct_neighbours/patch rename fuzzers/{prescientfuzz_19f5081 => prescientfuzz_direct_neighbours}/runner.Dockerfile (100%) rename fuzzers/{libafl_19f5081 => prescientfuzz_reachable}/builder.Dockerfile (52%) create mode 100644 fuzzers/prescientfuzz_reachable/description.md rename fuzzers/{libafl_19f5081 => prescientfuzz_reachable}/fuzzer.py (76%) create mode 100644 fuzzers/prescientfuzz_reachable/patch rename fuzzers/{libafl_19f5081 => prescientfuzz_reachable}/runner.Dockerfile (96%) create mode 100644 fuzzers/prescientfuzz_reachable_rarity/builder.Dockerfile create mode 100644 fuzzers/prescientfuzz_reachable_rarity/description.md create mode 100755 fuzzers/prescientfuzz_reachable_rarity/fuzzer.py create mode 100644 fuzzers/prescientfuzz_reachable_rarity/patch create mode 100644 fuzzers/prescientfuzz_reachable_rarity/runner.Dockerfile create mode 100644 fuzzers/prescientfuzz_reachable_rarity_depth/builder.Dockerfile create mode 100644 fuzzers/prescientfuzz_reachable_rarity_depth/description.md create mode 100755 fuzzers/prescientfuzz_reachable_rarity_depth/fuzzer.py create mode 100644 fuzzers/prescientfuzz_reachable_rarity_depth/patch create mode 100644 fuzzers/prescientfuzz_reachable_rarity_depth/runner.Dockerfile create mode 100644 fuzzers/prescientfuzz_reachable_rarity_depth_backoff/builder.Dockerfile create mode 100644 fuzzers/prescientfuzz_reachable_rarity_depth_backoff/description.md create mode 100755 fuzzers/prescientfuzz_reachable_rarity_depth_backoff/fuzzer.py create mode 100644 fuzzers/prescientfuzz_reachable_rarity_depth_backoff/patch create mode 100644 fuzzers/prescientfuzz_reachable_rarity_depth_backoff/runner.Dockerfile diff --git a/fuzzers/libafl_19f5081/description.md b/fuzzers/libafl_19f5081/description.md deleted file mode 100644 index ea9b947d6..000000000 --- a/fuzzers/libafl_19f5081/description.md +++ /dev/null @@ -1,11 +0,0 @@ -# libafl - -libafl fuzzer instance - - cmplog feature - - persistent mode - -Repository: [https://github.com/AFLplusplus/libafl/](https://github.com/AFLplusplus/libafl/) - -[builder.Dockerfile](builder.Dockerfile) -[fuzzer.py](fuzzer.py) -[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/libafl_19f5081/patch b/fuzzers/libafl_19f5081/patch deleted file mode 100644 index 48e99fddf..000000000 --- a/fuzzers/libafl_19f5081/patch +++ /dev/null @@ -1,55 +0,0 @@ -diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs -index 9b162a48..f1dc0d7b 100644 ---- a/fuzzers/fuzzbench/src/lib.rs -+++ b/fuzzers/fuzzbench/src/lib.rs -@@ -23,7 +23,7 @@ use libafl::{ - feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, - fuzzer::{Fuzzer, StdFuzzer}, - inputs::{BytesInput, HasTargetBytes}, -- monitors::SimpleMonitor, -+ monitors::SimplePrintingMonitor, - mutators::{ - scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, - StdMOptMutator, StdScheduledMutator, Tokens, -@@ -214,13 +214,7 @@ fn fuzz( - let file_null = File::open("/dev/null")?; - - // 'While the monitor are state, they are usually used in the broker - which is likely never restarted -- let monitor = SimpleMonitor::new(|s| { -- #[cfg(unix)] -- writeln!(&mut stdout_cpy, "{s}").unwrap(); -- #[cfg(windows)] -- println!("{s}"); -- writeln!(log.borrow_mut(), "{:?} {s}", current_time()).unwrap(); -- }); -+ let monitor = SimplePrintingMonitor::new(); - - // We need a shared map to store our state before a crash. - // This way, we are able to continue fuzzing afterwards. -@@ -380,16 +374,16 @@ fn fuzz( - } - - // Remove target output (logs still survive) -- #[cfg(unix)] -- { -- let null_fd = file_null.as_raw_fd(); -- dup2(null_fd, io::stdout().as_raw_fd())?; -- if std::env::var("LIBAFL_FUZZBENCH_DEBUG").is_err() { -- dup2(null_fd, io::stderr().as_raw_fd())?; -- } -- } -- // reopen file to make sure we're at the end -- log.replace(OpenOptions::new().append(true).create(true).open(logfile)?); -+ // #[cfg(unix)] -+ // { -+ // let null_fd = file_null.as_raw_fd(); -+ // dup2(null_fd, io::stdout().as_raw_fd())?; -+ // if std::env::var("LIBAFL_FUZZBENCH_DEBUG").is_err() { -+ // dup2(null_fd, io::stderr().as_raw_fd())?; -+ // } -+ // } -+ // // reopen file to make sure we're at the end -+ // log.replace(OpenOptions::new().append(true).create(true).open(logfile)?); - - fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)?; - diff --git a/fuzzers/prescientfuzz/patch b/fuzzers/prescientfuzz/patch deleted file mode 100644 index 9a5bd5205..000000000 --- a/fuzzers/prescientfuzz/patch +++ /dev/null @@ -1,569 +0,0 @@ -diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs -index 0c40b942..e63325d8 100644 ---- a/fuzzers/fuzzbench/src/lib.rs -+++ b/fuzzers/fuzzbench/src/lib.rs -@@ -31,7 +31,7 @@ use libafl::{ - observers::{CanTrack, HitcountsMapObserver, TimeObserver}, - schedulers::{ - powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, -- probabilistic_sampling::UncoveredNeighboursProbabilitySamplingScheduler, -+ prescient_weighted::PrescientProbabilitySamplingScheduler, - }, - stages::{ - calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage, -@@ -243,7 +243,7 @@ fn fuzz( - #[cfg(windows)] - println!("{s}"); - writeln!(log.borrow_mut(), "{:?} {s}", current_time()).unwrap(); -- }, true); -+ }); - - // We need a shared map to store our state before a crash. - // This way, we are able to continue fuzzing afterwards. -@@ -332,7 +332,7 @@ fn fuzz( - - let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); - -- let scheduler = UncoveredNeighboursProbabilitySamplingScheduler::new_with_backoff(backoff_factor); -+ let scheduler = PrescientProbabilitySamplingScheduler::new_with_backoff(backoff_factor); - - // A fuzzer with feedbacks and a corpus scheduler - let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); -diff --git a/libafl/src/feedbacks/map.rs b/libafl/src/feedbacks/map.rs -index 5d4158a2..82e70d61 100644 ---- a/libafl/src/feedbacks/map.rs -+++ b/libafl/src/feedbacks/map.rs -@@ -14,7 +14,7 @@ use core::{ - use libafl_bolts::AsSlice; - use libafl_bolts::{ - tuples::{Handle, Handled, MatchNameRef}, -- AsIter, AsSlice, HasRefCnt, Named, -+ AsIter, HasRefCnt, Named, - }; - use num_traits::PrimInt; - use serde::{de::DeserializeOwned, Deserialize, Serialize}; -@@ -848,32 +848,32 @@ where - N: IsNovel, - C: CanTrack + AsRef + Named, - { -- // /// Create new `MapFeedback` -- // #[must_use] -- // pub fn new(map_observer: &C) -> Self { -- // Self { -- // novelties: if C::NOVELTIES { Some(vec![]) } else { None }, -- // name: map_observer.name().clone(), -- // map_ref: map_observer.handle(), -- // stats_name: create_stats_name(map_observer.name()), -- // phantom: PhantomData, -- // } -- // } -- -- // /// Creating a new `MapFeedback` with a specific name. This is usefully whenever the same -- // /// feedback is needed twice, but with a different history. Using `new()` always results in the -- // /// same name and therefore also the same history. -- // #[must_use] -- // pub fn with_name(name: &'static str, map_observer: &C) -> Self { -- // let name = Cow::from(name); -- // Self { -- // novelties: if C::NOVELTIES { Some(vec![]) } else { None }, -- // map_ref: map_observer.handle(), -- // stats_name: create_stats_name(&name), -- // name, -- // phantom: PhantomData, -- // } -- // } -+ /// Create new `MapFeedback` -+ #[must_use] -+ pub fn new(map_observer: &C) -> Self { -+ Self { -+ novelties: if C::NOVELTIES { Some(vec![]) } else { None }, -+ name: map_observer.name().clone(), -+ map_ref: map_observer.handle(), -+ stats_name: create_stats_name(map_observer.name()), -+ phantom: PhantomData, -+ } -+ } -+ -+ /// Creating a new `MapFeedback` with a specific name. This is usefully whenever the same -+ /// feedback is needed twice, but with a different history. Using `new()` always results in the -+ /// same name and therefore also the same history. -+ #[must_use] -+ pub fn with_name(name: &'static str, map_observer: &C) -> Self { -+ let name = Cow::from(name); -+ Self { -+ novelties: if C::NOVELTIES { Some(vec![]) } else { None }, -+ map_ref: map_observer.handle(), -+ stats_name: create_stats_name(&name), -+ name, -+ phantom: PhantomData, -+ } -+ } - - #[allow(clippy::wrong_self_convention)] - #[allow(clippy::needless_range_loop)] -diff --git a/libafl/src/schedulers/mod.rs b/libafl/src/schedulers/mod.rs -index 2a0b65df..2c829953 100644 ---- a/libafl/src/schedulers/mod.rs -+++ b/libafl/src/schedulers/mod.rs -@@ -26,6 +26,9 @@ pub use accounting::CoverageAccountingScheduler; - pub mod weighted; - pub use weighted::{StdWeightedScheduler, WeightedScheduler}; - -+pub mod prescient_weighted; -+pub use prescient_weighted::{PrescientProbabilitySamplingScheduler, ProbabilityMetadata}; -+ - pub mod tuneable; - use libafl_bolts::{ - rands::Rand, -diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs -new file mode 100644 -index 00000000..6761c534 ---- /dev/null -+++ b/libafl/src/schedulers/prescient_weighted.rs -@@ -0,0 +1,428 @@ -+//! Prescient Weighted sampling scheduler is a corpus scheduler that feeds the fuzzer -+ -+use std::vec::Vec; -+use hashbrown::HashSet; -+use alloc::string::String; -+use core::{marker::PhantomData, fmt::Debug}; -+ -+use hashbrown::HashMap; -+use libafl_bolts::rands::Rand; -+use libafl_bolts::HasLen; -+use serde::{Deserialize, Serialize}; -+use std::time::{Instant, SystemTime, UNIX_EPOCH}; -+ -+use crate::{ -+ HasMetadata, HasNamedMetadata, -+ corpus::{testcase::TestcaseMutationsMetadata, Corpus, CorpusId, HasTestcase}, -+ feedbacks::{cfg_prescience::{ControlFlowGraph, Reachability}, -+ MapIndexesMetadata, -+ MapNeighboursFeedbackMetadata, -+ MapNoveltiesMetadata}, -+ inputs::UsesInput, -+ schedulers::Scheduler, -+ state::{HasCorpus, HasRand, State, UsesState}, Error -+}; -+ -+/// Calculate Testcase probabilities using prescience -+#[derive(Debug, Clone)] -+pub struct PrescientProbabilitySamplingScheduler -+where -+ S: UsesInput, -+{ -+ backoff_factor: f64, -+ phantom: PhantomData, -+} -+ -+/// A state metadata holding a map of probability of corpus elements. -+#[derive(Debug, Serialize, Deserialize)] -+#[cfg_attr( -+ any(not(feature = "serdeany_autoreg"), miri), -+ allow(clippy::unsafe_derive_deserialize) -+)] // for SerdeAny -+pub struct ProbabilityMetadata { -+ /// corpus index -> probability -+ pub map: HashMap, -+ /// total probability of all items in the map -+ pub total_probability: f64, -+ /// Do we need to recalculate the scores? -+ pub needs_recalc: bool, -+ /// The time that we last recalculated all the scores (in millis) -+ pub last_recalc_time: u128, -+ /// The amount of time the last recalc took -+ pub last_recalc_duration: u128, -+} -+ -+libafl_bolts::impl_serdeany!(ProbabilityMetadata); -+ -+impl ProbabilityMetadata { -+ /// Creates a new [`struct@ProbabilityMetadata`] -+ #[must_use] -+ pub fn new() -> Self { -+ Self { -+ map: HashMap::default(), -+ total_probability: 0.0, -+ needs_recalc: false, -+ last_recalc_time: 0, -+ last_recalc_duration: 0, -+ } -+ } -+} -+ -+impl Default for ProbabilityMetadata { -+ fn default() -> Self { -+ Self::new() -+ } -+} -+ -+struct ReachableBlocksResult { -+ /// Number of corpus entries this reachability appears in -+ frequency_for_reachability: HashMap, -+ /// Cumulative number of times corpus entries directly neighbouring (ie depth 1) -+ /// this coverage map index have been mutated -+ direct_neighbour_mutations_for_index: HashMap, -+ /// Lowest depth observed for the given index -+ least_depth_for_index: HashMap, -+} -+ -+ -+impl PrescientProbabilitySamplingScheduler -+where -+ S: HasCorpus + HasMetadata + HasNamedMetadata + HasRand, -+ S::Input: HasLen, -+{ -+ /// Creates a new [`struct@ProbabilitySamplingScheduler`] -+ #[must_use] -+ pub fn new_with_backoff(backoff_factor: f64) -> Self { -+ Self { -+ backoff_factor, -+ phantom: PhantomData, -+ } -+ } -+ -+ /// Calculate the score and store in `ProbabilityMetadata` -+ #[allow(clippy::cast_precision_loss)] -+ #[allow(clippy::unused_self)] -+ pub fn store_probability(&self, _state: &mut S, _idx: CorpusId) -> Result<(), Error> { -+ assert!(false, "Should not use anymore"); -+ -+ Ok(()) -+ } -+ -+ /// return a map of {(index, depth): frequency}, where frequency is the number of testcases -+ /// with this index being reachable at the given depth -+ fn recalculate_reachable_blocks(&self, state: &mut S) -> ReachableBlocksResult { -+ let mut result = ReachableBlocksResult { -+ frequency_for_reachability: HashMap::new(), -+ direct_neighbour_mutations_for_index: HashMap::new(), -+ least_depth_for_index: HashMap::new(), -+ }; -+ let start = Instant::now(); -+ -+ let all_ids = state.corpus().ids().collect::>(); -+ -+ let full_neighbours_meta = state -+ .metadata_mut::() -+ .unwrap(); -+ -+ let covered_blocks = full_neighbours_meta.covered_blocks.clone(); -+ let last_recalc_corpus_ids = full_neighbours_meta.corpus_ids_present_at_recalc.clone(); -+ full_neighbours_meta.corpus_ids_present_at_recalc = all_ids.clone(); -+ -+ let mut recalcs = 0; -+ for &idx in &all_ids { -+ recalcs += 1; -+ -+ let tc = state.corpus().get(idx).unwrap().borrow(); -+ let covered_meta = tc.metadata::().unwrap(); -+ let covered_indexes = covered_meta.list.clone(); -+ let num_mutations = if let Ok(meta) = tc.metadata::() { -+ meta.num_mutations_executed -+ } else { -+ 0 -+ }; -+ drop(tc); -+ -+ let reachabilities = { -+ let cfg_metadata = state.metadata_mut::().unwrap(); -+ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) -+ }; -+ -+ if !last_recalc_corpus_ids.contains(&idx) { -+ let tc = state.corpus().get(idx).unwrap().borrow(); -+ let novelties_meta = tc.metadata::().unwrap(); -+ let novelties = novelties_meta.list.clone(); -+ drop(tc); -+ -+ let full_neighbours_meta = state -+ .metadata_mut::() -+ .unwrap(); -+ -+ for novelty in novelties { -+ full_neighbours_meta.reachable_blocks.remove(&novelty); -+ } -+ -+ for reachability in &reachabilities { -+ full_neighbours_meta.reachable_blocks.insert(reachability.index); -+ } -+ } -+ -+ for reachability in reachabilities { -+ // update reachability frequencies -+ let new = if let Some(freq) = result.frequency_for_reachability.get(&reachability) { -+ freq + 1 -+ } else { -+ 1 -+ }; -+ result.frequency_for_reachability.insert(reachability.clone(), new); -+ -+ // update number of mutations of direct neighbours (if appropriate) -+ if reachability.depth == 1 { -+ let updated = if let Some(freq) = result.direct_neighbour_mutations_for_index.get(&reachability.index) { -+ freq + num_mutations -+ } else { -+ num_mutations -+ }; -+ result.direct_neighbour_mutations_for_index.insert(reachability.index, updated); -+ } -+ -+ // update least depth for index (if we beat the previous depth) -+ if let Some(cur_min) = result.least_depth_for_index.get(&reachability.index) { -+ if reachability.depth < *cur_min { -+ result.least_depth_for_index.insert(reachability.index, reachability.depth); -+ } -+ } else { -+ result.least_depth_for_index.insert(reachability.index, reachability.depth); -+ } -+ } -+ } -+ -+ println!("Whew, recalced all neighbours for {recalcs} entries (out of a possible {}); took: {:.2?}", all_ids.len(), start.elapsed()); -+ -+ result -+ } -+ -+ /// Recalculate the probability of each testcase being selected for mutation -+ pub fn recalc_all_probabilities(&self, state: &mut S) -> Result<(), Error> { -+ let reachable_blocks_result = self.recalculate_reachable_blocks(state); -+ -+ let full_neighbours_meta = state -+ .metadata::() -+ .unwrap(); -+ let _reachable_all = full_neighbours_meta.reachable_blocks.clone(); -+ let covered_blocks = full_neighbours_meta.covered_blocks.clone(); -+ -+ let mut total_score = 0.0; -+ -+ let ids = state.corpus().ids().collect::>(); -+ let corpus_size = ids.len(); -+ let mut min_time = f64::MAX; -+ -+ // sort entries by time -+ let mut time_ordered = vec![]; -+ let mut min_len = 99999999f64; -+ let mut len_for_id = HashMap::new(); -+ for &id in &ids { -+ let mut tc = state.corpus().get(id)?.borrow_mut(); -+ let len = tc.load_len(state.corpus()).unwrap() as f64; -+ if len < min_len { min_len = len; } -+ len_for_id.insert(id, len); -+ let exec_time_ns = tc.exec_time().unwrap().as_nanos() as f64; -+ if exec_time_ns < min_time { min_time = exec_time_ns; } -+ time_ordered.push((id, exec_time_ns * len)); -+ } -+ time_ordered.sort_by(|(_id, score1), (_id2, score2)| score1.partial_cmp(score2).unwrap()); -+ -+ // The more this neighbour has been fuzzed, the less we'll prioritise it (maybe it's hard or infeasible) -+ let backoff_weighting_for_direct_neighbour = { -+ let mut weighting = HashMap::new(); -+ for (&index, &mutations) in &reachable_blocks_result.direct_neighbour_mutations_for_index { -+ let decrements = mutations / 1_000; -+ weighting.insert(index, self.backoff_factor.powi(decrements as i32)); -+ } -+ weighting -+ }; -+ -+ let mut favored_filled = HashSet::with_capacity(65536); -+ let mut reachability_favored_ids = HashSet::new(); -+ let mut coverage_favored_ids = HashSet::new(); -+ let mut favored_edges = HashSet::new(); -+ let mut all_covered = HashSet::new(); -+ let mut neighbour_score_for_idx = HashMap::new(); -+ -+ // greedily select a minimal subset of testcases that cover all neighbours (based on runtime) -+ for &(entry, _runtime) in &time_ordered { -+ let tc = state.corpus().get(entry)?.borrow(); -+ let idx_meta = tc.metadata::().unwrap(); -+ for &edge in &idx_meta.list { all_covered.insert(edge); } -+ -+ let mut neighbour_score = 0f64; -+ let mut reachability_favored = false; -+ -+ let covered_indexes = idx_meta.list.clone(); -+ drop(tc); -+ -+ let reachabilities = { -+ let cfg_metadata = state.metadata_mut::().unwrap(); -+ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) -+ }; -+ -+ let tc = state.corpus().get(entry)?.borrow(); -+ let idx_meta = tc.metadata::().unwrap(); -+ for reachability in reachabilities { -+ // Only keep this if it's the best depth we've seen for this edge -+ if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { -+ let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); -+ if freq.is_none() { println!("frequency is none for {:?}", reachability); } -+ let rarity = 1f64 / *freq.unwrap() as f64; -+ let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); -+ if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } -+ neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; -+ reachability_favored |= favored_filled.insert(reachability.index); -+ } -+ } -+ neighbour_score_for_idx.insert(entry, neighbour_score); -+ -+ let mut coverage_favored = false; -+ for &edge in &idx_meta.list { -+ coverage_favored |= favored_edges.insert(edge); -+ } -+ -+ if reachability_favored { -+ reachability_favored_ids.insert(entry); -+ } else if coverage_favored { -+ coverage_favored_ids.insert(entry); -+ } -+ } -+ -+ let skipped = all_covered.difference(&favored_edges).copied().collect::>(); -+ println!("Minimised the testset from {corpus_size} down to {} favored entries - and {} somewhat favored (favored edges: {}, missed out {} entries: {:?})", -+ reachability_favored_ids.len(), coverage_favored_ids.len(), -+ favored_edges.len(), skipped.len(), skipped); -+ -+ let mut all_scores = vec![]; -+ for entry in ids { -+ let tc = state.corpus().get(entry)?.borrow(); -+ let mut score = neighbour_score_for_idx[&entry]; -+ -+ let exec_time_us = tc.exec_time().unwrap().as_nanos() as f64; -+ let time_weighting = min_time / exec_time_us; -+ score *= time_weighting; -+ -+ all_scores.push((entry, score)); -+ -+ total_score += score; -+ -+ drop(tc); -+ let meta = state -+ .metadata_map_mut() -+ .get_mut::() -+ .unwrap(); -+ meta.map.insert(entry, score); -+ } -+ -+ // all_scores.sort_by(|(_, score1), (_, score2)| score1.partial_cmp(score2).unwrap()); -+ // println!("Scores: {:?}", all_scores); -+ -+ let meta = state -+ .metadata_map_mut() -+ .get_mut::() -+ .unwrap(); -+ meta.total_probability = total_score; -+ -+ Ok(()) -+ } -+} -+ -+impl UsesState for PrescientProbabilitySamplingScheduler -+where -+ S: State + HasTestcase, -+{ -+ type State = S; -+} -+ -+impl Scheduler for PrescientProbabilitySamplingScheduler -+where -+ S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand + HasTestcase + State, -+ S::Input: HasLen, -+{ -+ fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> { -+ let current_idx = *state.corpus().current(); -+ state -+ .corpus() -+ .get(idx)? -+ .borrow_mut() -+ .set_parent_id_optional(current_idx); -+ -+ if state.metadata_map().get::().is_none() { -+ state.add_metadata(ProbabilityMetadata::new()); -+ } -+ -+ let prob_meta = state.metadata_map_mut().get_mut::().unwrap(); -+ prob_meta.needs_recalc = true; -+ let avg = prob_meta.total_probability / prob_meta.map.len() as f64; -+ prob_meta.map.insert(idx, avg); -+ prob_meta.total_probability += avg; -+ -+ // let max = prob_meta.map.values().fold(0f64, |max, &v| if v > max { v } else { max }); -+ // prob_meta.map.insert(idx, max); -+ // prob_meta.total_probability += max; -+ -+ Ok(()) -+ } -+ -+ /// Gets the next entry -+ #[allow(clippy::cast_precision_loss)] -+ fn next(&mut self, state: &mut Self::State) -> Result { -+ if state.corpus().count() == 0 { -+ Err(Error::empty(String::from("No entries in corpus"))) -+ } else { -+ const MAX_RAND: u64 = 1_000_000; -+ let rand_prob: f64 = (state.rand_mut().below(MAX_RAND as usize) as f64) / MAX_RAND as f64; -+ -+ let meta = state.metadata_map_mut().get_mut::().unwrap(); -+ if meta.needs_recalc { -+ let ts_now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(); -+ let time_since_recalc = ts_now - meta.last_recalc_time; -+ let last_duration = meta.last_recalc_duration; -+ // Don't spend more than 10% of the fuzzer time recalculating these stats - sure -+ // this feels like we're not using the neighbours prescient power much at the start -+ // of the campaign, but fuzzing campaigns last hours... -+ if time_since_recalc >= (10 * last_duration) { -+ println!("Last recalc took {last_duration}ms, now recalcing as it has been {time_since_recalc}"); -+ let start = Instant::now(); -+ self.recalculate_reachable_blocks(state); -+ self.recalc_all_probabilities(state).unwrap(); -+ -+ let meta = state.metadata_map_mut().get_mut::().unwrap(); -+ meta.needs_recalc = false; -+ meta.last_recalc_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(); -+ meta.last_recalc_duration = start.elapsed().as_millis(); -+ } -+ } -+ -+ let meta = state.metadata_map().get::().unwrap(); -+ let threshold = meta.total_probability * rand_prob; -+ let mut k: f64 = 0.0; -+ let mut ret = *meta.map.keys().last().unwrap(); -+ for (idx, prob) in &meta.map { -+ k += prob; -+ if k >= threshold { -+ ret = *idx; -+ break; -+ } -+ } -+ self.set_current_scheduled(state, Some(ret))?; -+ Ok(ret) -+ } -+ } -+} -+ -+impl Default for PrescientProbabilitySamplingScheduler -+where -+ S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand, -+ S::Input: HasLen, -+{ -+ fn default() -> Self { -+ Self::new_with_backoff(0.9999) -+ } -+} -\ No newline at end of file -diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs -index 69781524..9d097043 100644 ---- a/libafl/src/stages/mutational.rs -+++ b/libafl/src/stages/mutational.rs -@@ -117,10 +117,10 @@ where - let num = self.iterations(state)?; - let mut testcase = state.current_testcase_mut()?; - if let Ok(meta) = testcase.metadata_mut::() { -- meta.num_mutations_executed += num as usize; -+ meta.num_mutations_executed += num; - } else { - testcase.add_metadata( -- TestcaseMutationsMetadata { num_mutations_executed: num as usize } -+ TestcaseMutationsMetadata { num_mutations_executed: num } - ); - } - diff --git a/fuzzers/prescientfuzz_19f5081/patch b/fuzzers/prescientfuzz_19f5081/patch deleted file mode 100644 index 9a5bd5205..000000000 --- a/fuzzers/prescientfuzz_19f5081/patch +++ /dev/null @@ -1,569 +0,0 @@ -diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs -index 0c40b942..e63325d8 100644 ---- a/fuzzers/fuzzbench/src/lib.rs -+++ b/fuzzers/fuzzbench/src/lib.rs -@@ -31,7 +31,7 @@ use libafl::{ - observers::{CanTrack, HitcountsMapObserver, TimeObserver}, - schedulers::{ - powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, -- probabilistic_sampling::UncoveredNeighboursProbabilitySamplingScheduler, -+ prescient_weighted::PrescientProbabilitySamplingScheduler, - }, - stages::{ - calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage, -@@ -243,7 +243,7 @@ fn fuzz( - #[cfg(windows)] - println!("{s}"); - writeln!(log.borrow_mut(), "{:?} {s}", current_time()).unwrap(); -- }, true); -+ }); - - // We need a shared map to store our state before a crash. - // This way, we are able to continue fuzzing afterwards. -@@ -332,7 +332,7 @@ fn fuzz( - - let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); - -- let scheduler = UncoveredNeighboursProbabilitySamplingScheduler::new_with_backoff(backoff_factor); -+ let scheduler = PrescientProbabilitySamplingScheduler::new_with_backoff(backoff_factor); - - // A fuzzer with feedbacks and a corpus scheduler - let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); -diff --git a/libafl/src/feedbacks/map.rs b/libafl/src/feedbacks/map.rs -index 5d4158a2..82e70d61 100644 ---- a/libafl/src/feedbacks/map.rs -+++ b/libafl/src/feedbacks/map.rs -@@ -14,7 +14,7 @@ use core::{ - use libafl_bolts::AsSlice; - use libafl_bolts::{ - tuples::{Handle, Handled, MatchNameRef}, -- AsIter, AsSlice, HasRefCnt, Named, -+ AsIter, HasRefCnt, Named, - }; - use num_traits::PrimInt; - use serde::{de::DeserializeOwned, Deserialize, Serialize}; -@@ -848,32 +848,32 @@ where - N: IsNovel, - C: CanTrack + AsRef + Named, - { -- // /// Create new `MapFeedback` -- // #[must_use] -- // pub fn new(map_observer: &C) -> Self { -- // Self { -- // novelties: if C::NOVELTIES { Some(vec![]) } else { None }, -- // name: map_observer.name().clone(), -- // map_ref: map_observer.handle(), -- // stats_name: create_stats_name(map_observer.name()), -- // phantom: PhantomData, -- // } -- // } -- -- // /// Creating a new `MapFeedback` with a specific name. This is usefully whenever the same -- // /// feedback is needed twice, but with a different history. Using `new()` always results in the -- // /// same name and therefore also the same history. -- // #[must_use] -- // pub fn with_name(name: &'static str, map_observer: &C) -> Self { -- // let name = Cow::from(name); -- // Self { -- // novelties: if C::NOVELTIES { Some(vec![]) } else { None }, -- // map_ref: map_observer.handle(), -- // stats_name: create_stats_name(&name), -- // name, -- // phantom: PhantomData, -- // } -- // } -+ /// Create new `MapFeedback` -+ #[must_use] -+ pub fn new(map_observer: &C) -> Self { -+ Self { -+ novelties: if C::NOVELTIES { Some(vec![]) } else { None }, -+ name: map_observer.name().clone(), -+ map_ref: map_observer.handle(), -+ stats_name: create_stats_name(map_observer.name()), -+ phantom: PhantomData, -+ } -+ } -+ -+ /// Creating a new `MapFeedback` with a specific name. This is usefully whenever the same -+ /// feedback is needed twice, but with a different history. Using `new()` always results in the -+ /// same name and therefore also the same history. -+ #[must_use] -+ pub fn with_name(name: &'static str, map_observer: &C) -> Self { -+ let name = Cow::from(name); -+ Self { -+ novelties: if C::NOVELTIES { Some(vec![]) } else { None }, -+ map_ref: map_observer.handle(), -+ stats_name: create_stats_name(&name), -+ name, -+ phantom: PhantomData, -+ } -+ } - - #[allow(clippy::wrong_self_convention)] - #[allow(clippy::needless_range_loop)] -diff --git a/libafl/src/schedulers/mod.rs b/libafl/src/schedulers/mod.rs -index 2a0b65df..2c829953 100644 ---- a/libafl/src/schedulers/mod.rs -+++ b/libafl/src/schedulers/mod.rs -@@ -26,6 +26,9 @@ pub use accounting::CoverageAccountingScheduler; - pub mod weighted; - pub use weighted::{StdWeightedScheduler, WeightedScheduler}; - -+pub mod prescient_weighted; -+pub use prescient_weighted::{PrescientProbabilitySamplingScheduler, ProbabilityMetadata}; -+ - pub mod tuneable; - use libafl_bolts::{ - rands::Rand, -diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs -new file mode 100644 -index 00000000..6761c534 ---- /dev/null -+++ b/libafl/src/schedulers/prescient_weighted.rs -@@ -0,0 +1,428 @@ -+//! Prescient Weighted sampling scheduler is a corpus scheduler that feeds the fuzzer -+ -+use std::vec::Vec; -+use hashbrown::HashSet; -+use alloc::string::String; -+use core::{marker::PhantomData, fmt::Debug}; -+ -+use hashbrown::HashMap; -+use libafl_bolts::rands::Rand; -+use libafl_bolts::HasLen; -+use serde::{Deserialize, Serialize}; -+use std::time::{Instant, SystemTime, UNIX_EPOCH}; -+ -+use crate::{ -+ HasMetadata, HasNamedMetadata, -+ corpus::{testcase::TestcaseMutationsMetadata, Corpus, CorpusId, HasTestcase}, -+ feedbacks::{cfg_prescience::{ControlFlowGraph, Reachability}, -+ MapIndexesMetadata, -+ MapNeighboursFeedbackMetadata, -+ MapNoveltiesMetadata}, -+ inputs::UsesInput, -+ schedulers::Scheduler, -+ state::{HasCorpus, HasRand, State, UsesState}, Error -+}; -+ -+/// Calculate Testcase probabilities using prescience -+#[derive(Debug, Clone)] -+pub struct PrescientProbabilitySamplingScheduler -+where -+ S: UsesInput, -+{ -+ backoff_factor: f64, -+ phantom: PhantomData, -+} -+ -+/// A state metadata holding a map of probability of corpus elements. -+#[derive(Debug, Serialize, Deserialize)] -+#[cfg_attr( -+ any(not(feature = "serdeany_autoreg"), miri), -+ allow(clippy::unsafe_derive_deserialize) -+)] // for SerdeAny -+pub struct ProbabilityMetadata { -+ /// corpus index -> probability -+ pub map: HashMap, -+ /// total probability of all items in the map -+ pub total_probability: f64, -+ /// Do we need to recalculate the scores? -+ pub needs_recalc: bool, -+ /// The time that we last recalculated all the scores (in millis) -+ pub last_recalc_time: u128, -+ /// The amount of time the last recalc took -+ pub last_recalc_duration: u128, -+} -+ -+libafl_bolts::impl_serdeany!(ProbabilityMetadata); -+ -+impl ProbabilityMetadata { -+ /// Creates a new [`struct@ProbabilityMetadata`] -+ #[must_use] -+ pub fn new() -> Self { -+ Self { -+ map: HashMap::default(), -+ total_probability: 0.0, -+ needs_recalc: false, -+ last_recalc_time: 0, -+ last_recalc_duration: 0, -+ } -+ } -+} -+ -+impl Default for ProbabilityMetadata { -+ fn default() -> Self { -+ Self::new() -+ } -+} -+ -+struct ReachableBlocksResult { -+ /// Number of corpus entries this reachability appears in -+ frequency_for_reachability: HashMap, -+ /// Cumulative number of times corpus entries directly neighbouring (ie depth 1) -+ /// this coverage map index have been mutated -+ direct_neighbour_mutations_for_index: HashMap, -+ /// Lowest depth observed for the given index -+ least_depth_for_index: HashMap, -+} -+ -+ -+impl PrescientProbabilitySamplingScheduler -+where -+ S: HasCorpus + HasMetadata + HasNamedMetadata + HasRand, -+ S::Input: HasLen, -+{ -+ /// Creates a new [`struct@ProbabilitySamplingScheduler`] -+ #[must_use] -+ pub fn new_with_backoff(backoff_factor: f64) -> Self { -+ Self { -+ backoff_factor, -+ phantom: PhantomData, -+ } -+ } -+ -+ /// Calculate the score and store in `ProbabilityMetadata` -+ #[allow(clippy::cast_precision_loss)] -+ #[allow(clippy::unused_self)] -+ pub fn store_probability(&self, _state: &mut S, _idx: CorpusId) -> Result<(), Error> { -+ assert!(false, "Should not use anymore"); -+ -+ Ok(()) -+ } -+ -+ /// return a map of {(index, depth): frequency}, where frequency is the number of testcases -+ /// with this index being reachable at the given depth -+ fn recalculate_reachable_blocks(&self, state: &mut S) -> ReachableBlocksResult { -+ let mut result = ReachableBlocksResult { -+ frequency_for_reachability: HashMap::new(), -+ direct_neighbour_mutations_for_index: HashMap::new(), -+ least_depth_for_index: HashMap::new(), -+ }; -+ let start = Instant::now(); -+ -+ let all_ids = state.corpus().ids().collect::>(); -+ -+ let full_neighbours_meta = state -+ .metadata_mut::() -+ .unwrap(); -+ -+ let covered_blocks = full_neighbours_meta.covered_blocks.clone(); -+ let last_recalc_corpus_ids = full_neighbours_meta.corpus_ids_present_at_recalc.clone(); -+ full_neighbours_meta.corpus_ids_present_at_recalc = all_ids.clone(); -+ -+ let mut recalcs = 0; -+ for &idx in &all_ids { -+ recalcs += 1; -+ -+ let tc = state.corpus().get(idx).unwrap().borrow(); -+ let covered_meta = tc.metadata::().unwrap(); -+ let covered_indexes = covered_meta.list.clone(); -+ let num_mutations = if let Ok(meta) = tc.metadata::() { -+ meta.num_mutations_executed -+ } else { -+ 0 -+ }; -+ drop(tc); -+ -+ let reachabilities = { -+ let cfg_metadata = state.metadata_mut::().unwrap(); -+ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) -+ }; -+ -+ if !last_recalc_corpus_ids.contains(&idx) { -+ let tc = state.corpus().get(idx).unwrap().borrow(); -+ let novelties_meta = tc.metadata::().unwrap(); -+ let novelties = novelties_meta.list.clone(); -+ drop(tc); -+ -+ let full_neighbours_meta = state -+ .metadata_mut::() -+ .unwrap(); -+ -+ for novelty in novelties { -+ full_neighbours_meta.reachable_blocks.remove(&novelty); -+ } -+ -+ for reachability in &reachabilities { -+ full_neighbours_meta.reachable_blocks.insert(reachability.index); -+ } -+ } -+ -+ for reachability in reachabilities { -+ // update reachability frequencies -+ let new = if let Some(freq) = result.frequency_for_reachability.get(&reachability) { -+ freq + 1 -+ } else { -+ 1 -+ }; -+ result.frequency_for_reachability.insert(reachability.clone(), new); -+ -+ // update number of mutations of direct neighbours (if appropriate) -+ if reachability.depth == 1 { -+ let updated = if let Some(freq) = result.direct_neighbour_mutations_for_index.get(&reachability.index) { -+ freq + num_mutations -+ } else { -+ num_mutations -+ }; -+ result.direct_neighbour_mutations_for_index.insert(reachability.index, updated); -+ } -+ -+ // update least depth for index (if we beat the previous depth) -+ if let Some(cur_min) = result.least_depth_for_index.get(&reachability.index) { -+ if reachability.depth < *cur_min { -+ result.least_depth_for_index.insert(reachability.index, reachability.depth); -+ } -+ } else { -+ result.least_depth_for_index.insert(reachability.index, reachability.depth); -+ } -+ } -+ } -+ -+ println!("Whew, recalced all neighbours for {recalcs} entries (out of a possible {}); took: {:.2?}", all_ids.len(), start.elapsed()); -+ -+ result -+ } -+ -+ /// Recalculate the probability of each testcase being selected for mutation -+ pub fn recalc_all_probabilities(&self, state: &mut S) -> Result<(), Error> { -+ let reachable_blocks_result = self.recalculate_reachable_blocks(state); -+ -+ let full_neighbours_meta = state -+ .metadata::() -+ .unwrap(); -+ let _reachable_all = full_neighbours_meta.reachable_blocks.clone(); -+ let covered_blocks = full_neighbours_meta.covered_blocks.clone(); -+ -+ let mut total_score = 0.0; -+ -+ let ids = state.corpus().ids().collect::>(); -+ let corpus_size = ids.len(); -+ let mut min_time = f64::MAX; -+ -+ // sort entries by time -+ let mut time_ordered = vec![]; -+ let mut min_len = 99999999f64; -+ let mut len_for_id = HashMap::new(); -+ for &id in &ids { -+ let mut tc = state.corpus().get(id)?.borrow_mut(); -+ let len = tc.load_len(state.corpus()).unwrap() as f64; -+ if len < min_len { min_len = len; } -+ len_for_id.insert(id, len); -+ let exec_time_ns = tc.exec_time().unwrap().as_nanos() as f64; -+ if exec_time_ns < min_time { min_time = exec_time_ns; } -+ time_ordered.push((id, exec_time_ns * len)); -+ } -+ time_ordered.sort_by(|(_id, score1), (_id2, score2)| score1.partial_cmp(score2).unwrap()); -+ -+ // The more this neighbour has been fuzzed, the less we'll prioritise it (maybe it's hard or infeasible) -+ let backoff_weighting_for_direct_neighbour = { -+ let mut weighting = HashMap::new(); -+ for (&index, &mutations) in &reachable_blocks_result.direct_neighbour_mutations_for_index { -+ let decrements = mutations / 1_000; -+ weighting.insert(index, self.backoff_factor.powi(decrements as i32)); -+ } -+ weighting -+ }; -+ -+ let mut favored_filled = HashSet::with_capacity(65536); -+ let mut reachability_favored_ids = HashSet::new(); -+ let mut coverage_favored_ids = HashSet::new(); -+ let mut favored_edges = HashSet::new(); -+ let mut all_covered = HashSet::new(); -+ let mut neighbour_score_for_idx = HashMap::new(); -+ -+ // greedily select a minimal subset of testcases that cover all neighbours (based on runtime) -+ for &(entry, _runtime) in &time_ordered { -+ let tc = state.corpus().get(entry)?.borrow(); -+ let idx_meta = tc.metadata::().unwrap(); -+ for &edge in &idx_meta.list { all_covered.insert(edge); } -+ -+ let mut neighbour_score = 0f64; -+ let mut reachability_favored = false; -+ -+ let covered_indexes = idx_meta.list.clone(); -+ drop(tc); -+ -+ let reachabilities = { -+ let cfg_metadata = state.metadata_mut::().unwrap(); -+ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) -+ }; -+ -+ let tc = state.corpus().get(entry)?.borrow(); -+ let idx_meta = tc.metadata::().unwrap(); -+ for reachability in reachabilities { -+ // Only keep this if it's the best depth we've seen for this edge -+ if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { -+ let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); -+ if freq.is_none() { println!("frequency is none for {:?}", reachability); } -+ let rarity = 1f64 / *freq.unwrap() as f64; -+ let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); -+ if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } -+ neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; -+ reachability_favored |= favored_filled.insert(reachability.index); -+ } -+ } -+ neighbour_score_for_idx.insert(entry, neighbour_score); -+ -+ let mut coverage_favored = false; -+ for &edge in &idx_meta.list { -+ coverage_favored |= favored_edges.insert(edge); -+ } -+ -+ if reachability_favored { -+ reachability_favored_ids.insert(entry); -+ } else if coverage_favored { -+ coverage_favored_ids.insert(entry); -+ } -+ } -+ -+ let skipped = all_covered.difference(&favored_edges).copied().collect::>(); -+ println!("Minimised the testset from {corpus_size} down to {} favored entries - and {} somewhat favored (favored edges: {}, missed out {} entries: {:?})", -+ reachability_favored_ids.len(), coverage_favored_ids.len(), -+ favored_edges.len(), skipped.len(), skipped); -+ -+ let mut all_scores = vec![]; -+ for entry in ids { -+ let tc = state.corpus().get(entry)?.borrow(); -+ let mut score = neighbour_score_for_idx[&entry]; -+ -+ let exec_time_us = tc.exec_time().unwrap().as_nanos() as f64; -+ let time_weighting = min_time / exec_time_us; -+ score *= time_weighting; -+ -+ all_scores.push((entry, score)); -+ -+ total_score += score; -+ -+ drop(tc); -+ let meta = state -+ .metadata_map_mut() -+ .get_mut::() -+ .unwrap(); -+ meta.map.insert(entry, score); -+ } -+ -+ // all_scores.sort_by(|(_, score1), (_, score2)| score1.partial_cmp(score2).unwrap()); -+ // println!("Scores: {:?}", all_scores); -+ -+ let meta = state -+ .metadata_map_mut() -+ .get_mut::() -+ .unwrap(); -+ meta.total_probability = total_score; -+ -+ Ok(()) -+ } -+} -+ -+impl UsesState for PrescientProbabilitySamplingScheduler -+where -+ S: State + HasTestcase, -+{ -+ type State = S; -+} -+ -+impl Scheduler for PrescientProbabilitySamplingScheduler -+where -+ S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand + HasTestcase + State, -+ S::Input: HasLen, -+{ -+ fn on_add(&mut self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> { -+ let current_idx = *state.corpus().current(); -+ state -+ .corpus() -+ .get(idx)? -+ .borrow_mut() -+ .set_parent_id_optional(current_idx); -+ -+ if state.metadata_map().get::().is_none() { -+ state.add_metadata(ProbabilityMetadata::new()); -+ } -+ -+ let prob_meta = state.metadata_map_mut().get_mut::().unwrap(); -+ prob_meta.needs_recalc = true; -+ let avg = prob_meta.total_probability / prob_meta.map.len() as f64; -+ prob_meta.map.insert(idx, avg); -+ prob_meta.total_probability += avg; -+ -+ // let max = prob_meta.map.values().fold(0f64, |max, &v| if v > max { v } else { max }); -+ // prob_meta.map.insert(idx, max); -+ // prob_meta.total_probability += max; -+ -+ Ok(()) -+ } -+ -+ /// Gets the next entry -+ #[allow(clippy::cast_precision_loss)] -+ fn next(&mut self, state: &mut Self::State) -> Result { -+ if state.corpus().count() == 0 { -+ Err(Error::empty(String::from("No entries in corpus"))) -+ } else { -+ const MAX_RAND: u64 = 1_000_000; -+ let rand_prob: f64 = (state.rand_mut().below(MAX_RAND as usize) as f64) / MAX_RAND as f64; -+ -+ let meta = state.metadata_map_mut().get_mut::().unwrap(); -+ if meta.needs_recalc { -+ let ts_now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(); -+ let time_since_recalc = ts_now - meta.last_recalc_time; -+ let last_duration = meta.last_recalc_duration; -+ // Don't spend more than 10% of the fuzzer time recalculating these stats - sure -+ // this feels like we're not using the neighbours prescient power much at the start -+ // of the campaign, but fuzzing campaigns last hours... -+ if time_since_recalc >= (10 * last_duration) { -+ println!("Last recalc took {last_duration}ms, now recalcing as it has been {time_since_recalc}"); -+ let start = Instant::now(); -+ self.recalculate_reachable_blocks(state); -+ self.recalc_all_probabilities(state).unwrap(); -+ -+ let meta = state.metadata_map_mut().get_mut::().unwrap(); -+ meta.needs_recalc = false; -+ meta.last_recalc_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(); -+ meta.last_recalc_duration = start.elapsed().as_millis(); -+ } -+ } -+ -+ let meta = state.metadata_map().get::().unwrap(); -+ let threshold = meta.total_probability * rand_prob; -+ let mut k: f64 = 0.0; -+ let mut ret = *meta.map.keys().last().unwrap(); -+ for (idx, prob) in &meta.map { -+ k += prob; -+ if k >= threshold { -+ ret = *idx; -+ break; -+ } -+ } -+ self.set_current_scheduled(state, Some(ret))?; -+ Ok(ret) -+ } -+ } -+} -+ -+impl Default for PrescientProbabilitySamplingScheduler -+where -+ S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand, -+ S::Input: HasLen, -+{ -+ fn default() -> Self { -+ Self::new_with_backoff(0.9999) -+ } -+} -\ No newline at end of file -diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs -index 69781524..9d097043 100644 ---- a/libafl/src/stages/mutational.rs -+++ b/libafl/src/stages/mutational.rs -@@ -117,10 +117,10 @@ where - let num = self.iterations(state)?; - let mut testcase = state.current_testcase_mut()?; - if let Ok(meta) = testcase.metadata_mut::() { -- meta.num_mutations_executed += num as usize; -+ meta.num_mutations_executed += num; - } else { - testcase.add_metadata( -- TestcaseMutationsMetadata { num_mutations_executed: num as usize } -+ TestcaseMutationsMetadata { num_mutations_executed: num } - ); - } - diff --git a/fuzzers/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz_all_no_mopt/builder.Dockerfile similarity index 95% rename from fuzzers/prescientfuzz/builder.Dockerfile rename to fuzzers/prescientfuzz_all_no_mopt/builder.Dockerfile index 396820bef..4762c742f 100644 --- a/fuzzers/prescientfuzz/builder.Dockerfile +++ b/fuzzers/prescientfuzz_all_no_mopt/builder.Dockerfile @@ -33,7 +33,8 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 +COPY ./patch /PrescientFuzz/patch +RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 && git apply patch # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz/description.md b/fuzzers/prescientfuzz_all_no_mopt/description.md similarity index 100% rename from fuzzers/prescientfuzz/description.md rename to fuzzers/prescientfuzz_all_no_mopt/description.md diff --git a/fuzzers/prescientfuzz/fuzzer.py b/fuzzers/prescientfuzz_all_no_mopt/fuzzer.py similarity index 100% rename from fuzzers/prescientfuzz/fuzzer.py rename to fuzzers/prescientfuzz_all_no_mopt/fuzzer.py diff --git a/fuzzers/prescientfuzz_all_no_mopt/patch b/fuzzers/prescientfuzz_all_no_mopt/patch new file mode 100644 index 000000000..dff74d9d2 --- /dev/null +++ b/fuzzers/prescientfuzz_all_no_mopt/patch @@ -0,0 +1,27 @@ +diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs +index e63325d8..5e00b8ed 100644 +--- a/fuzzers/fuzzbench/src/lib.rs ++++ b/fuzzers/fuzzbench/src/lib.rs +@@ -322,13 +322,15 @@ fn fuzz( + // Setup a randomic Input2State stage + let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); + +- // Setup a MOPT mutator +- let mutator = StdMOptMutator::new( +- &mut state, +- havoc_mutations().merge(tokens_mutations()), +- 7, +- 5, +- )?; ++ // // Setup a MOPT mutator ++ // let mutator = StdMOptMutator::new( ++ // &mut state, ++ // havoc_mutations().merge(tokens_mutations()), ++ // 7, ++ // 5, ++ // )?; ++ // Setup a mutational stage with a basic bytes mutator ++ let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6); + + let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); + diff --git a/fuzzers/prescientfuzz/runner.Dockerfile b/fuzzers/prescientfuzz_all_no_mopt/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz/runner.Dockerfile rename to fuzzers/prescientfuzz_all_no_mopt/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_19f5081/builder.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours/builder.Dockerfile similarity index 92% rename from fuzzers/prescientfuzz_19f5081/builder.Dockerfile rename to fuzzers/prescientfuzz_direct_neighbours/builder.Dockerfile index a46e7eb60..4762c742f 100644 --- a/fuzzers/prescientfuzz_19f5081/builder.Dockerfile +++ b/fuzzers/prescientfuzz_direct_neighbours/builder.Dockerfile @@ -33,7 +33,8 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 543074581cdd98d747c7e625745dab7ade5799d3 +COPY ./patch /PrescientFuzz/patch +RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 && git apply patch # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz_19f5081/description.md b/fuzzers/prescientfuzz_direct_neighbours/description.md similarity index 100% rename from fuzzers/prescientfuzz_19f5081/description.md rename to fuzzers/prescientfuzz_direct_neighbours/description.md diff --git a/fuzzers/prescientfuzz_19f5081/fuzzer.py b/fuzzers/prescientfuzz_direct_neighbours/fuzzer.py similarity index 100% rename from fuzzers/prescientfuzz_19f5081/fuzzer.py rename to fuzzers/prescientfuzz_direct_neighbours/fuzzer.py diff --git a/fuzzers/prescientfuzz_direct_neighbours/patch b/fuzzers/prescientfuzz_direct_neighbours/patch new file mode 100644 index 000000000..0d88780f3 --- /dev/null +++ b/fuzzers/prescientfuzz_direct_neighbours/patch @@ -0,0 +1,22 @@ +diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs +index 6761c534..316d5038 100644 +--- a/libafl/src/schedulers/prescient_weighted.rs ++++ b/libafl/src/schedulers/prescient_weighted.rs +@@ -270,13 +270,13 @@ where + let idx_meta = tc.metadata::().unwrap(); + for reachability in reachabilities { + // Only keep this if it's the best depth we've seen for this edge +- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { ++ if reachability.depth == 1 { // reachable_blocks_result.least_depth_for_index[&reachability.index] { + let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); + if freq.is_none() { println!("frequency is none for {:?}", reachability); } +- let rarity = 1f64 / *freq.unwrap() as f64; +- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); ++ let rarity = 1f64; // / *freq.unwrap() as f64; ++ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); + if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } +- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; ++ neighbour_score += backoff_weighting.unwrap() * rarity; // * 1f64 / reachability.depth as f64; + reachability_favored |= favored_filled.insert(reachability.index); + } + } diff --git a/fuzzers/prescientfuzz_19f5081/runner.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_19f5081/runner.Dockerfile rename to fuzzers/prescientfuzz_direct_neighbours/runner.Dockerfile diff --git a/fuzzers/libafl_19f5081/builder.Dockerfile b/fuzzers/prescientfuzz_reachable/builder.Dockerfile similarity index 52% rename from fuzzers/libafl_19f5081/builder.Dockerfile rename to fuzzers/prescientfuzz_reachable/builder.Dockerfile index af323c564..4762c742f 100644 --- a/fuzzers/libafl_19f5081/builder.Dockerfile +++ b/fuzzers/prescientfuzz_reachable/builder.Dockerfile @@ -18,43 +18,33 @@ FROM $parent_image # Uninstall old Rust & Install the latest one. RUN if which rustup; then rustup self uninstall -y; fi && \ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh --default-toolchain nightly-2023-09-21 -y && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ rm /rustup.sh -# Install dependencies. RUN apt-get update && \ - apt-get remove -y llvm-10 && \ apt-get install -y \ build-essential \ - lsb-release wget software-properties-common gnupg && \ + cargo && \ apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ apt-utils apt-transport-https ca-certificates joe curl && \ - wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 17 + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make -RUN wget https://gist.githubusercontent.com/tokatoka/26f4ba95991c6e33139999976332aa8e/raw/698ac2087d58ce5c7a6ad59adce58dbfdc32bd46/createAliases.sh && chmod u+x ./createAliases.sh && ./createAliases.sh +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +COPY ./patch /PrescientFuzz/patch +RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 && git apply patch -# Uninstall old Rust & Install the latest one. -RUN if which rustup; then rustup self uninstall -y; fi && \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh --default-toolchain nightly-2024-03-12 -y && \ - rm /rustup.sh - -# Download libafl. -RUN git clone https://github.com/AFLplusplus/LibAFL /libafl - -# Checkout a current commit -RUN cd /libafl && git pull && git checkout 19f5081bd8ce0c043642b6075501988cdd2c6691 || true -# Note that due a nightly bug it is currently fixed to a known version on top! - -# Compile libafl. -RUN cd /libafl && \ +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ export LIBAFL_EDGES_MAP_SIZE=2621440 && \ cd ./fuzzers/fuzzbench && \ - PATH="/root/.cargo/bin/:$PATH" cargo build --profile release-fuzzbench --features no_link_main + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main # Auxiliary weak references. -RUN cd /libafl/fuzzers/fuzzbench && \ +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ clang -c stub_rt.c && \ ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_reachable/description.md b/fuzzers/prescientfuzz_reachable/description.md new file mode 100644 index 000000000..452b0e374 --- /dev/null +++ b/fuzzers/prescientfuzz_reachable/description.md @@ -0,0 +1,8 @@ +# PrescientFuzz + +based on libafl fuzzer instance + - persistent mode + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/libafl_19f5081/fuzzer.py b/fuzzers/prescientfuzz_reachable/fuzzer.py similarity index 76% rename from fuzzers/libafl_19f5081/fuzzer.py rename to fuzzers/prescientfuzz_reachable/fuzzer.py index 0f191a744..5f2dfa95f 100755 --- a/fuzzers/libafl_19f5081/fuzzer.py +++ b/fuzzers/prescientfuzz_reachable/fuzzer.py @@ -15,7 +15,9 @@ """Integration code for a LibAFL-based fuzzer.""" import os +import sys import subprocess +from pathlib import Path from fuzzers import utils @@ -38,23 +40,26 @@ def prepare_fuzz_environment(input_corpus): utils.create_seed_file_for_empty_corpus(input_corpus) -def build(): # pylint: disable=too-many-branches,too-many-statements +def build(): """Build benchmark.""" - os.environ[ - 'CC'] = '/libafl/fuzzers/fuzzbench/target/release-fuzzbench/libafl_cc' - os.environ[ - 'CXX'] = '/libafl/fuzzers/fuzzbench/target/release-fuzzbench/libafl_cxx' + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' cflags = ['--libafl'] - cxxflags = ['--libafl', '--std=c++14'] utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cxxflags) + utils.append_flags('CXXFLAGS', cflags) utils.append_flags('LDFLAGS', cflags) os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file utils.build_benchmark() @@ -65,7 +70,13 @@ def fuzz(input_corpus, output_corpus, target_binary): command = [target_binary] if dictionary_path: command += (['-x', dictionary_path]) - command += (['-o', output_corpus, '-i', input_corpus]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) fuzzer_env = os.environ.copy() fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' print(command) diff --git a/fuzzers/prescientfuzz_reachable/patch b/fuzzers/prescientfuzz_reachable/patch new file mode 100644 index 000000000..e5d2c16a9 --- /dev/null +++ b/fuzzers/prescientfuzz_reachable/patch @@ -0,0 +1,18 @@ +diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs +index 6761c534..8c279ab8 100644 +--- a/libafl/src/schedulers/prescient_weighted.rs ++++ b/libafl/src/schedulers/prescient_weighted.rs +@@ -273,10 +273,10 @@ where + if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { + let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); + if freq.is_none() { println!("frequency is none for {:?}", reachability); } +- let rarity = 1f64 / *freq.unwrap() as f64; +- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); ++ let rarity = 1f64; // / *freq.unwrap() as f64; ++ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); + if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } +- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; ++ neighbour_score += backoff_weighting.unwrap() * rarity; // * 1f64 / reachability.depth as f64; + reachability_favored |= favored_filled.insert(reachability.index); + } + } diff --git a/fuzzers/libafl_19f5081/runner.Dockerfile b/fuzzers/prescientfuzz_reachable/runner.Dockerfile similarity index 96% rename from fuzzers/libafl_19f5081/runner.Dockerfile rename to fuzzers/prescientfuzz_reachable/runner.Dockerfile index f0c5eb6cc..1a023b81e 100644 --- a/fuzzers/libafl_19f5081/runner.Dockerfile +++ b/fuzzers/prescientfuzz_reachable/runner.Dockerfile @@ -18,7 +18,7 @@ RUN apt install libjemalloc2 # This makes interactive docker runs painless: ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" -#ENV AFL_MAP_SIZE=2621440 +ENV AFL_MAP_SIZE=2621440 ENV PATH="$PATH:/out" ENV AFL_SKIP_CPUFREQ=1 ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 diff --git a/fuzzers/prescientfuzz_reachable_rarity/builder.Dockerfile b/fuzzers/prescientfuzz_reachable_rarity/builder.Dockerfile new file mode 100644 index 000000000..4762c742f --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity/builder.Dockerfile @@ -0,0 +1,50 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ + rm /rustup.sh + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + cargo && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +COPY ./patch /PrescientFuzz/patch +RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 && git apply patch + +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_reachable_rarity/description.md b/fuzzers/prescientfuzz_reachable_rarity/description.md new file mode 100644 index 000000000..452b0e374 --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity/description.md @@ -0,0 +1,8 @@ +# PrescientFuzz + +based on libafl fuzzer instance + - persistent mode + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_reachable_rarity/fuzzer.py b/fuzzers/prescientfuzz_reachable_rarity/fuzzer.py new file mode 100755 index 000000000..5f2dfa95f --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity/fuzzer.py @@ -0,0 +1,83 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import sys +import subprocess +from pathlib import Path + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): + """Build benchmark.""" + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_reachable_rarity/patch b/fuzzers/prescientfuzz_reachable_rarity/patch new file mode 100644 index 000000000..5ff4ca293 --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity/patch @@ -0,0 +1,16 @@ +diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs +index 6761c534..f26e347c 100644 +--- a/libafl/src/schedulers/prescient_weighted.rs ++++ b/libafl/src/schedulers/prescient_weighted.rs +@@ -274,9 +274,9 @@ where + let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); + if freq.is_none() { println!("frequency is none for {:?}", reachability); } + let rarity = 1f64 / *freq.unwrap() as f64; +- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); ++ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); + if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } +- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; ++ neighbour_score += backoff_weighting.unwrap() * rarity; // * 1f64 / reachability.depth as f64; + reachability_favored |= favored_filled.insert(reachability.index); + } + } diff --git a/fuzzers/prescientfuzz_reachable_rarity/runner.Dockerfile b/fuzzers/prescientfuzz_reachable_rarity/runner.Dockerfile new file mode 100644 index 000000000..1a023b81e --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth/builder.Dockerfile b/fuzzers/prescientfuzz_reachable_rarity_depth/builder.Dockerfile new file mode 100644 index 000000000..4762c742f --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity_depth/builder.Dockerfile @@ -0,0 +1,50 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ + rm /rustup.sh + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + cargo && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +COPY ./patch /PrescientFuzz/patch +RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 && git apply patch + +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth/description.md b/fuzzers/prescientfuzz_reachable_rarity_depth/description.md new file mode 100644 index 000000000..452b0e374 --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity_depth/description.md @@ -0,0 +1,8 @@ +# PrescientFuzz + +based on libafl fuzzer instance + - persistent mode + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth/fuzzer.py b/fuzzers/prescientfuzz_reachable_rarity_depth/fuzzer.py new file mode 100755 index 000000000..5f2dfa95f --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity_depth/fuzzer.py @@ -0,0 +1,83 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import sys +import subprocess +from pathlib import Path + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): + """Build benchmark.""" + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth/patch b/fuzzers/prescientfuzz_reachable_rarity_depth/patch new file mode 100644 index 000000000..85f40dffb --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity_depth/patch @@ -0,0 +1,13 @@ +diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs +index 6761c534..97eb14a0 100644 +--- a/libafl/src/schedulers/prescient_weighted.rs ++++ b/libafl/src/schedulers/prescient_weighted.rs +@@ -274,7 +274,7 @@ where + let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); + if freq.is_none() { println!("frequency is none for {:?}", reachability); } + let rarity = 1f64 / *freq.unwrap() as f64; +- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); ++ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); + if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } + neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; + reachability_favored |= favored_filled.insert(reachability.index); diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth/runner.Dockerfile b/fuzzers/prescientfuzz_reachable_rarity_depth/runner.Dockerfile new file mode 100644 index 000000000..1a023b81e --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity_depth/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/builder.Dockerfile b/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/builder.Dockerfile new file mode 100644 index 000000000..4762c742f --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/builder.Dockerfile @@ -0,0 +1,50 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ + rm /rustup.sh + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + cargo && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +COPY ./patch /PrescientFuzz/patch +RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 && git apply patch + +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/description.md b/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/description.md new file mode 100644 index 000000000..452b0e374 --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/description.md @@ -0,0 +1,8 @@ +# PrescientFuzz + +based on libafl fuzzer instance + - persistent mode + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/fuzzer.py b/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/fuzzer.py new file mode 100755 index 000000000..5f2dfa95f --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/fuzzer.py @@ -0,0 +1,83 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import sys +import subprocess +from pathlib import Path + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): + """Build benchmark.""" + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/patch b/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/patch new file mode 100644 index 000000000..e69de29bb diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/runner.Dockerfile b/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/runner.Dockerfile new file mode 100644 index 000000000..1a023b81e --- /dev/null +++ b/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 From 4672593b47d45e99d9de8989308662b20cbd92bd Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Mon, 3 Jun 2024 21:27:29 +0100 Subject: [PATCH 18/25] Back to the default 20 trials per setup --- service/experiment-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/experiment-config.yaml b/service/experiment-config.yaml index bd829361b..b9acb09f8 100644 --- a/service/experiment-config.yaml +++ b/service/experiment-config.yaml @@ -2,7 +2,7 @@ # Unless you are a fuzzbench maintainer running this service, this # will not work with your setup. -trials: 10 +trials: 20 max_total_time: 82800 # 23 hours, the default time for preemptible experiments. cloud_project: fuzzbench docker_registry: gcr.io/fuzzbench From b9a186f5eeb39d158937e8618482dc4edf646ca1 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Thu, 6 Jun 2024 17:32:48 +0100 Subject: [PATCH 19/25] Added alternative setups to test impact of disabling mopt --- .../builder.Dockerfile | 3 +- .../description.md | 0 .../fuzzer.py | 0 .../runner.Dockerfile | 0 .../builder.Dockerfile | 0 .../description.md | 0 .../fuzzer.py | 0 .../patch | 49 +++++++++++++++++++ .../runner.Dockerfile | 0 .../builder.Dockerfile | 0 .../description.md | 0 .../fuzzer.py | 0 .../patch | 22 ++++++++- .../runner.Dockerfile | 0 .../builder.Dockerfile | 0 .../description.md | 0 .../fuzzer.py | 0 .../patch | 48 ++++++++++++++++++ .../runner.Dockerfile | 0 fuzzers/prescientfuzz_reachable/patch | 18 ------- .../patch | 13 ----- .../patch | 0 service/experiment-config.yaml | 2 +- 23 files changed, 119 insertions(+), 36 deletions(-) rename fuzzers/{prescientfuzz_reachable_rarity_depth_backoff => prescientfuzz_all}/builder.Dockerfile (95%) rename fuzzers/{prescientfuzz_reachable => prescientfuzz_all}/description.md (100%) rename fuzzers/{prescientfuzz_reachable => prescientfuzz_all}/fuzzer.py (100%) rename fuzzers/{prescientfuzz_reachable => prescientfuzz_all}/runner.Dockerfile (100%) rename fuzzers/{prescientfuzz_reachable => prescientfuzz_direct_neighbours_no_mopt}/builder.Dockerfile (100%) rename fuzzers/{prescientfuzz_reachable_rarity => prescientfuzz_direct_neighbours_no_mopt}/description.md (100%) rename fuzzers/{prescientfuzz_reachable_rarity => prescientfuzz_direct_neighbours_no_mopt}/fuzzer.py (100%) create mode 100644 fuzzers/prescientfuzz_direct_neighbours_no_mopt/patch rename fuzzers/{prescientfuzz_reachable_rarity => prescientfuzz_direct_neighbours_no_mopt}/runner.Dockerfile (100%) rename fuzzers/{prescientfuzz_reachable_rarity => prescientfuzz_direct_neighbours_rarity}/builder.Dockerfile (100%) rename fuzzers/{prescientfuzz_reachable_rarity_depth => prescientfuzz_direct_neighbours_rarity}/description.md (100%) rename fuzzers/{prescientfuzz_reachable_rarity_depth => prescientfuzz_direct_neighbours_rarity}/fuzzer.py (100%) rename fuzzers/{prescientfuzz_reachable_rarity => prescientfuzz_direct_neighbours_rarity}/patch (56%) rename fuzzers/{prescientfuzz_reachable_rarity_depth => prescientfuzz_direct_neighbours_rarity}/runner.Dockerfile (100%) rename fuzzers/{prescientfuzz_reachable_rarity_depth => prescientfuzz_direct_neighbours_rarity_no_mopt}/builder.Dockerfile (100%) rename fuzzers/{prescientfuzz_reachable_rarity_depth_backoff => prescientfuzz_direct_neighbours_rarity_no_mopt}/description.md (100%) rename fuzzers/{prescientfuzz_reachable_rarity_depth_backoff => prescientfuzz_direct_neighbours_rarity_no_mopt}/fuzzer.py (100%) create mode 100644 fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/patch rename fuzzers/{prescientfuzz_reachable_rarity_depth_backoff => prescientfuzz_direct_neighbours_rarity_no_mopt}/runner.Dockerfile (100%) delete mode 100644 fuzzers/prescientfuzz_reachable/patch delete mode 100644 fuzzers/prescientfuzz_reachable_rarity_depth/patch delete mode 100644 fuzzers/prescientfuzz_reachable_rarity_depth_backoff/patch diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/builder.Dockerfile b/fuzzers/prescientfuzz_all/builder.Dockerfile similarity index 95% rename from fuzzers/prescientfuzz_reachable_rarity_depth_backoff/builder.Dockerfile rename to fuzzers/prescientfuzz_all/builder.Dockerfile index 4762c742f..396820bef 100644 --- a/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/builder.Dockerfile +++ b/fuzzers/prescientfuzz_all/builder.Dockerfile @@ -33,8 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -COPY ./patch /PrescientFuzz/patch -RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 && git apply patch +RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz_reachable/description.md b/fuzzers/prescientfuzz_all/description.md similarity index 100% rename from fuzzers/prescientfuzz_reachable/description.md rename to fuzzers/prescientfuzz_all/description.md diff --git a/fuzzers/prescientfuzz_reachable/fuzzer.py b/fuzzers/prescientfuzz_all/fuzzer.py similarity index 100% rename from fuzzers/prescientfuzz_reachable/fuzzer.py rename to fuzzers/prescientfuzz_all/fuzzer.py diff --git a/fuzzers/prescientfuzz_reachable/runner.Dockerfile b/fuzzers/prescientfuzz_all/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_reachable/runner.Dockerfile rename to fuzzers/prescientfuzz_all/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_reachable/builder.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours_no_mopt/builder.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_reachable/builder.Dockerfile rename to fuzzers/prescientfuzz_direct_neighbours_no_mopt/builder.Dockerfile diff --git a/fuzzers/prescientfuzz_reachable_rarity/description.md b/fuzzers/prescientfuzz_direct_neighbours_no_mopt/description.md similarity index 100% rename from fuzzers/prescientfuzz_reachable_rarity/description.md rename to fuzzers/prescientfuzz_direct_neighbours_no_mopt/description.md diff --git a/fuzzers/prescientfuzz_reachable_rarity/fuzzer.py b/fuzzers/prescientfuzz_direct_neighbours_no_mopt/fuzzer.py similarity index 100% rename from fuzzers/prescientfuzz_reachable_rarity/fuzzer.py rename to fuzzers/prescientfuzz_direct_neighbours_no_mopt/fuzzer.py diff --git a/fuzzers/prescientfuzz_direct_neighbours_no_mopt/patch b/fuzzers/prescientfuzz_direct_neighbours_no_mopt/patch new file mode 100644 index 000000000..06de424ee --- /dev/null +++ b/fuzzers/prescientfuzz_direct_neighbours_no_mopt/patch @@ -0,0 +1,49 @@ +diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs +index e63325d8..5e00b8ed 100644 +--- a/fuzzers/fuzzbench/src/lib.rs ++++ b/fuzzers/fuzzbench/src/lib.rs +@@ -322,13 +322,15 @@ fn fuzz( + // Setup a randomic Input2State stage + let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); + +- // Setup a MOPT mutator +- let mutator = StdMOptMutator::new( +- &mut state, +- havoc_mutations().merge(tokens_mutations()), +- 7, +- 5, +- )?; ++ // // Setup a MOPT mutator ++ // let mutator = StdMOptMutator::new( ++ // &mut state, ++ // havoc_mutations().merge(tokens_mutations()), ++ // 7, ++ // 5, ++ // )?; ++ // Setup a mutational stage with a basic bytes mutator ++ let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6); + + let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); + +diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs +index 6761c534..316d5038 100644 +--- a/libafl/src/schedulers/prescient_weighted.rs ++++ b/libafl/src/schedulers/prescient_weighted.rs +@@ -270,13 +270,13 @@ where + let idx_meta = tc.metadata::().unwrap(); + for reachability in reachabilities { + // Only keep this if it's the best depth we've seen for this edge +- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { ++ if reachability.depth == 1 { // reachable_blocks_result.least_depth_for_index[&reachability.index] { + let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); + if freq.is_none() { println!("frequency is none for {:?}", reachability); } +- let rarity = 1f64 / *freq.unwrap() as f64; +- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); ++ let rarity = 1f64; // / *freq.unwrap() as f64; ++ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); + if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } +- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; ++ neighbour_score += backoff_weighting.unwrap() * rarity; // * 1f64 / reachability.depth as f64; + reachability_favored |= favored_filled.insert(reachability.index); + } + } diff --git a/fuzzers/prescientfuzz_reachable_rarity/runner.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours_no_mopt/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_reachable_rarity/runner.Dockerfile rename to fuzzers/prescientfuzz_direct_neighbours_no_mopt/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_reachable_rarity/builder.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours_rarity/builder.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_reachable_rarity/builder.Dockerfile rename to fuzzers/prescientfuzz_direct_neighbours_rarity/builder.Dockerfile diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth/description.md b/fuzzers/prescientfuzz_direct_neighbours_rarity/description.md similarity index 100% rename from fuzzers/prescientfuzz_reachable_rarity_depth/description.md rename to fuzzers/prescientfuzz_direct_neighbours_rarity/description.md diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth/fuzzer.py b/fuzzers/prescientfuzz_direct_neighbours_rarity/fuzzer.py similarity index 100% rename from fuzzers/prescientfuzz_reachable_rarity_depth/fuzzer.py rename to fuzzers/prescientfuzz_direct_neighbours_rarity/fuzzer.py diff --git a/fuzzers/prescientfuzz_reachable_rarity/patch b/fuzzers/prescientfuzz_direct_neighbours_rarity/patch similarity index 56% rename from fuzzers/prescientfuzz_reachable_rarity/patch rename to fuzzers/prescientfuzz_direct_neighbours_rarity/patch index 5ff4ca293..dab36b79d 100644 --- a/fuzzers/prescientfuzz_reachable_rarity/patch +++ b/fuzzers/prescientfuzz_direct_neighbours_rarity/patch @@ -1,8 +1,26 @@ +diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs +index e63325d8..1f128a4c 100644 +--- a/fuzzers/fuzzbench/src/lib.rs ++++ b/fuzzers/fuzzbench/src/lib.rs +@@ -329,6 +329,8 @@ fn fuzz( + 7, + 5, + )?; ++ // Setup a mutational stage with a basic bytes mutator ++ // let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6); + + let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); + diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs -index 6761c534..f26e347c 100644 +index 6761c534..1879e0b3 100644 --- a/libafl/src/schedulers/prescient_weighted.rs +++ b/libafl/src/schedulers/prescient_weighted.rs -@@ -274,9 +274,9 @@ where +@@ -270,13 +270,13 @@ where + let idx_meta = tc.metadata::().unwrap(); + for reachability in reachabilities { + // Only keep this if it's the best depth we've seen for this edge +- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { ++ if reachability.depth == 1 { // reachable_blocks_result.least_depth_for_index[&reachability.index] { let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); if freq.is_none() { println!("frequency is none for {:?}", reachability); } let rarity = 1f64 / *freq.unwrap() as f64; diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth/runner.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours_rarity/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_reachable_rarity_depth/runner.Dockerfile rename to fuzzers/prescientfuzz_direct_neighbours_rarity/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth/builder.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/builder.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_reachable_rarity_depth/builder.Dockerfile rename to fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/builder.Dockerfile diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/description.md b/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/description.md similarity index 100% rename from fuzzers/prescientfuzz_reachable_rarity_depth_backoff/description.md rename to fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/description.md diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/fuzzer.py b/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/fuzzer.py similarity index 100% rename from fuzzers/prescientfuzz_reachable_rarity_depth_backoff/fuzzer.py rename to fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/fuzzer.py diff --git a/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/patch b/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/patch new file mode 100644 index 000000000..4aabaa330 --- /dev/null +++ b/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/patch @@ -0,0 +1,48 @@ +diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs +index e63325d8..5e00b8ed 100644 +--- a/fuzzers/fuzzbench/src/lib.rs ++++ b/fuzzers/fuzzbench/src/lib.rs +@@ -322,13 +322,15 @@ fn fuzz( + // Setup a randomic Input2State stage + let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); + +- // Setup a MOPT mutator +- let mutator = StdMOptMutator::new( +- &mut state, +- havoc_mutations().merge(tokens_mutations()), +- 7, +- 5, +- )?; ++ // // Setup a MOPT mutator ++ // let mutator = StdMOptMutator::new( ++ // &mut state, ++ // havoc_mutations().merge(tokens_mutations()), ++ // 7, ++ // 5, ++ // )?; ++ // Setup a mutational stage with a basic bytes mutator ++ let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6); + + let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); + +diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs +index 6761c534..1879e0b3 100644 +--- a/libafl/src/schedulers/prescient_weighted.rs ++++ b/libafl/src/schedulers/prescient_weighted.rs +@@ -270,13 +270,13 @@ where + let idx_meta = tc.metadata::().unwrap(); + for reachability in reachabilities { + // Only keep this if it's the best depth we've seen for this edge +- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { ++ if reachability.depth == 1 { // reachable_blocks_result.least_depth_for_index[&reachability.index] { + let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); + if freq.is_none() { println!("frequency is none for {:?}", reachability); } + let rarity = 1f64 / *freq.unwrap() as f64; +- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); ++ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); + if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } +- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; ++ neighbour_score += backoff_weighting.unwrap() * rarity; // * 1f64 / reachability.depth as f64; + reachability_favored |= favored_filled.insert(reachability.index); + } + } diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/runner.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_reachable_rarity_depth_backoff/runner.Dockerfile rename to fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_reachable/patch b/fuzzers/prescientfuzz_reachable/patch deleted file mode 100644 index e5d2c16a9..000000000 --- a/fuzzers/prescientfuzz_reachable/patch +++ /dev/null @@ -1,18 +0,0 @@ -diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs -index 6761c534..8c279ab8 100644 ---- a/libafl/src/schedulers/prescient_weighted.rs -+++ b/libafl/src/schedulers/prescient_weighted.rs -@@ -273,10 +273,10 @@ where - if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { - let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); - if freq.is_none() { println!("frequency is none for {:?}", reachability); } -- let rarity = 1f64 / *freq.unwrap() as f64; -- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); -+ let rarity = 1f64; // / *freq.unwrap() as f64; -+ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); - if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } -- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; -+ neighbour_score += backoff_weighting.unwrap() * rarity; // * 1f64 / reachability.depth as f64; - reachability_favored |= favored_filled.insert(reachability.index); - } - } diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth/patch b/fuzzers/prescientfuzz_reachable_rarity_depth/patch deleted file mode 100644 index 85f40dffb..000000000 --- a/fuzzers/prescientfuzz_reachable_rarity_depth/patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs -index 6761c534..97eb14a0 100644 ---- a/libafl/src/schedulers/prescient_weighted.rs -+++ b/libafl/src/schedulers/prescient_weighted.rs -@@ -274,7 +274,7 @@ where - let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); - if freq.is_none() { println!("frequency is none for {:?}", reachability); } - let rarity = 1f64 / *freq.unwrap() as f64; -- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); -+ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); - if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } - neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; - reachability_favored |= favored_filled.insert(reachability.index); diff --git a/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/patch b/fuzzers/prescientfuzz_reachable_rarity_depth_backoff/patch deleted file mode 100644 index e69de29bb..000000000 diff --git a/service/experiment-config.yaml b/service/experiment-config.yaml index b9acb09f8..53885721b 100644 --- a/service/experiment-config.yaml +++ b/service/experiment-config.yaml @@ -15,7 +15,7 @@ preemptible_runners: true # This experiment should generate a report that is combined with other public # "production" experiments. -merge_with_nonprivate: true +merge_with_nonprivate: false # This experiment should be merged with other reports in later experiments. private: false From 3fc873dfe3d18c9ddadc86c57df21de6a1a67df4 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Fri, 7 Jun 2024 13:07:43 +0100 Subject: [PATCH 20/25] Revert #1993 --- service/automatic_run_experiment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/automatic_run_experiment.py b/service/automatic_run_experiment.py index 38c9059ad..f1d9f180e 100644 --- a/service/automatic_run_experiment.py +++ b/service/automatic_run_experiment.py @@ -64,7 +64,7 @@ def _get_description(experiment_config: dict) -> Optional[str]: def _use_oss_fuzz_corpus(experiment_config: dict) -> bool: """Returns the oss_fuzz_corpus flag of the experiment described by |experiment_config| as a bool.""" - return bool(experiment_config.get('oss-fuzz-corpus')) + return bool(experiment_config.get('oss_fuzz_corpus')) def _get_requested_experiments(): From 39b1e6bc02e8ff7f86c9394092981996e886866f Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Thu, 13 Jun 2024 12:09:51 +0100 Subject: [PATCH 21/25] Made fast setup for direct neighbours (limit BFS exploration depth) --- fuzzers/prescientfuzz_all/builder.Dockerfile | 49 ------ fuzzers/prescientfuzz_all_no_mopt/patch | 27 --- .../builder.Dockerfile | 0 .../description.md | 0 .../fuzzer.py | 0 .../prescientfuzz_direct_neighbour_fast/patch | 158 ++++++++++++++++++ .../runner.Dockerfile | 0 .../builder.Dockerfile | 0 .../description.md | 0 .../fuzzer.py | 0 .../patch | 153 +++++++++++++++++ .../runner.Dockerfile | 0 .../description.md | 8 - .../prescientfuzz_direct_neighbours/fuzzer.py | 83 --------- fuzzers/prescientfuzz_direct_neighbours/patch | 22 --- .../runner.Dockerfile | 25 --- .../builder.Dockerfile | 50 ------ .../description.md | 8 - .../fuzzer.py | 83 --------- .../patch | 49 ------ .../runner.Dockerfile | 25 --- .../builder.Dockerfile | 50 ------ .../description.md | 8 - .../fuzzer.py | 83 --------- .../patch | 34 ---- .../runner.Dockerfile | 25 --- .../builder.Dockerfile | 50 ------ .../description.md | 8 - .../fuzzer.py | 83 --------- .../patch | 48 ------ .../runner.Dockerfile | 25 --- 31 files changed, 311 insertions(+), 843 deletions(-) delete mode 100644 fuzzers/prescientfuzz_all/builder.Dockerfile delete mode 100644 fuzzers/prescientfuzz_all_no_mopt/patch rename fuzzers/{prescientfuzz_all_no_mopt => prescientfuzz_direct_neighbour_fast}/builder.Dockerfile (100%) rename fuzzers/{prescientfuzz_all => prescientfuzz_direct_neighbour_fast}/description.md (100%) rename fuzzers/{prescientfuzz_all => prescientfuzz_direct_neighbour_fast}/fuzzer.py (100%) create mode 100644 fuzzers/prescientfuzz_direct_neighbour_fast/patch rename fuzzers/{prescientfuzz_all => prescientfuzz_direct_neighbour_fast}/runner.Dockerfile (100%) rename fuzzers/{prescientfuzz_direct_neighbours => prescientfuzz_direct_neighbour_fast_w_backoff}/builder.Dockerfile (100%) rename fuzzers/{prescientfuzz_all_no_mopt => prescientfuzz_direct_neighbour_fast_w_backoff}/description.md (100%) rename fuzzers/{prescientfuzz_all_no_mopt => prescientfuzz_direct_neighbour_fast_w_backoff}/fuzzer.py (100%) create mode 100644 fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch rename fuzzers/{prescientfuzz_all_no_mopt => prescientfuzz_direct_neighbour_fast_w_backoff}/runner.Dockerfile (100%) delete mode 100644 fuzzers/prescientfuzz_direct_neighbours/description.md delete mode 100755 fuzzers/prescientfuzz_direct_neighbours/fuzzer.py delete mode 100644 fuzzers/prescientfuzz_direct_neighbours/patch delete mode 100644 fuzzers/prescientfuzz_direct_neighbours/runner.Dockerfile delete mode 100644 fuzzers/prescientfuzz_direct_neighbours_no_mopt/builder.Dockerfile delete mode 100644 fuzzers/prescientfuzz_direct_neighbours_no_mopt/description.md delete mode 100755 fuzzers/prescientfuzz_direct_neighbours_no_mopt/fuzzer.py delete mode 100644 fuzzers/prescientfuzz_direct_neighbours_no_mopt/patch delete mode 100644 fuzzers/prescientfuzz_direct_neighbours_no_mopt/runner.Dockerfile delete mode 100644 fuzzers/prescientfuzz_direct_neighbours_rarity/builder.Dockerfile delete mode 100644 fuzzers/prescientfuzz_direct_neighbours_rarity/description.md delete mode 100755 fuzzers/prescientfuzz_direct_neighbours_rarity/fuzzer.py delete mode 100644 fuzzers/prescientfuzz_direct_neighbours_rarity/patch delete mode 100644 fuzzers/prescientfuzz_direct_neighbours_rarity/runner.Dockerfile delete mode 100644 fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/builder.Dockerfile delete mode 100644 fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/description.md delete mode 100755 fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/fuzzer.py delete mode 100644 fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/patch delete mode 100644 fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_all/builder.Dockerfile b/fuzzers/prescientfuzz_all/builder.Dockerfile deleted file mode 100644 index 396820bef..000000000 --- a/fuzzers/prescientfuzz_all/builder.Dockerfile +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ARG parent_image -FROM $parent_image - -# Uninstall old Rust & Install the latest one. -RUN if which rustup; then rustup self uninstall -y; fi && \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh -y && \ - /root/.cargo/bin/rustup toolchain install nightly && \ - rm /rustup.sh - -RUN apt-get update && \ - apt-get install -y \ - build-essential \ - cargo && \ - apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ - libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ - apt-utils apt-transport-https ca-certificates joe curl && \ - PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make - -# Download PrescientFuzz -RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 - -# Compile PrescientFuzz. -RUN cd /PrescientFuzz && \ - unset CFLAGS CXXFLAGS && \ - export CC=clang AFL_NO_X86 && \ - export LIBAFL_EDGES_MAP_SIZE=2621440 && \ - cd ./fuzzers/fuzzbench && \ - PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main - -# Auxiliary weak references. -RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ - clang -c stub_rt.c && \ - ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_all_no_mopt/patch b/fuzzers/prescientfuzz_all_no_mopt/patch deleted file mode 100644 index dff74d9d2..000000000 --- a/fuzzers/prescientfuzz_all_no_mopt/patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs -index e63325d8..5e00b8ed 100644 ---- a/fuzzers/fuzzbench/src/lib.rs -+++ b/fuzzers/fuzzbench/src/lib.rs -@@ -322,13 +322,15 @@ fn fuzz( - // Setup a randomic Input2State stage - let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); - -- // Setup a MOPT mutator -- let mutator = StdMOptMutator::new( -- &mut state, -- havoc_mutations().merge(tokens_mutations()), -- 7, -- 5, -- )?; -+ // // Setup a MOPT mutator -+ // let mutator = StdMOptMutator::new( -+ // &mut state, -+ // havoc_mutations().merge(tokens_mutations()), -+ // 7, -+ // 5, -+ // )?; -+ // Setup a mutational stage with a basic bytes mutator -+ let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6); - - let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); - diff --git a/fuzzers/prescientfuzz_all_no_mopt/builder.Dockerfile b/fuzzers/prescientfuzz_direct_neighbour_fast/builder.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_all_no_mopt/builder.Dockerfile rename to fuzzers/prescientfuzz_direct_neighbour_fast/builder.Dockerfile diff --git a/fuzzers/prescientfuzz_all/description.md b/fuzzers/prescientfuzz_direct_neighbour_fast/description.md similarity index 100% rename from fuzzers/prescientfuzz_all/description.md rename to fuzzers/prescientfuzz_direct_neighbour_fast/description.md diff --git a/fuzzers/prescientfuzz_all/fuzzer.py b/fuzzers/prescientfuzz_direct_neighbour_fast/fuzzer.py similarity index 100% rename from fuzzers/prescientfuzz_all/fuzzer.py rename to fuzzers/prescientfuzz_direct_neighbour_fast/fuzzer.py diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast/patch b/fuzzers/prescientfuzz_direct_neighbour_fast/patch new file mode 100644 index 000000000..9b4d7bc99 --- /dev/null +++ b/fuzzers/prescientfuzz_direct_neighbour_fast/patch @@ -0,0 +1,158 @@ +diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs +index e63325d8..adb2cb88 100644 +--- a/fuzzers/fuzzbench/src/lib.rs ++++ b/fuzzers/fuzzbench/src/lib.rs +@@ -322,17 +322,13 @@ fn fuzz( + // Setup a randomic Input2State stage + let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); + +- // Setup a MOPT mutator +- let mutator = StdMOptMutator::new( +- &mut state, +- havoc_mutations().merge(tokens_mutations()), +- 7, +- 5, +- )?; ++ // Setup a mutational stage with a basic bytes mutator ++ let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6); + + let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); + +- let scheduler = PrescientProbabilitySamplingScheduler::new_with_backoff(backoff_factor); ++ // set max_depth to 1, so only direct neighbours are counted ++ let scheduler = PrescientProbabilitySamplingScheduler::new_with_backoff(backoff_factor, 1); + + // A fuzzer with feedbacks and a corpus scheduler + let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); +diff --git a/libafl/src/feedbacks/cfg_prescience.rs b/libafl/src/feedbacks/cfg_prescience.rs +index 871cd858..bb4fc1b7 100644 +--- a/libafl/src/feedbacks/cfg_prescience.rs ++++ b/libafl/src/feedbacks/cfg_prescience.rs +@@ -725,7 +725,8 @@ impl ControlFlowGraph { + pub fn get_all_neighbours_full_depth( + &mut self, + input_coverage_map_indexes: &[usize], +- all_coverage_map_indexes: &HashSet ++ all_coverage_map_indexes: &HashSet, ++ max_depth: usize + ) -> Vec { + + let mut dupes = vec![]; +@@ -752,6 +753,11 @@ impl ControlFlowGraph { + + while let Some((depth, to_explore, direct_neighbour_predecessor)) = queue.pop_front() { + ++ // Don't keep exploring past max depth ++ if depth >= max_depth { ++ continue; ++ } ++ + debug_assert!(covered.contains(&to_explore), "to_explore: {to_explore}, covered: {:?}", covered); + + if to_explore >= 1_000_000 { +diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs +index 6761c534..8fd1e74b 100644 +--- a/libafl/src/schedulers/prescient_weighted.rs ++++ b/libafl/src/schedulers/prescient_weighted.rs +@@ -23,16 +23,6 @@ use crate::{ + state::{HasCorpus, HasRand, State, UsesState}, Error + }; + +-/// Calculate Testcase probabilities using prescience +-#[derive(Debug, Clone)] +-pub struct PrescientProbabilitySamplingScheduler +-where +- S: UsesInput, +-{ +- backoff_factor: f64, +- phantom: PhantomData, +-} +- + /// A state metadata holding a map of probability of corpus elements. + #[derive(Debug, Serialize, Deserialize)] + #[cfg_attr( +@@ -85,6 +75,17 @@ struct ReachableBlocksResult { + } + + ++/// Calculate Testcase probabilities using prescience ++#[derive(Debug, Clone)] ++pub struct PrescientProbabilitySamplingScheduler ++where ++ S: UsesInput, ++{ ++ backoff_factor: f64, ++ max_cfg_depth: usize, ++ phantom: PhantomData, ++} ++ + impl PrescientProbabilitySamplingScheduler + where + S: HasCorpus + HasMetadata + HasNamedMetadata + HasRand, +@@ -92,9 +93,10 @@ where + { + /// Creates a new [`struct@ProbabilitySamplingScheduler`] + #[must_use] +- pub fn new_with_backoff(backoff_factor: f64) -> Self { ++ pub fn new_with_backoff(backoff_factor: f64, max_cfg_depth: usize) -> Self { + Self { + backoff_factor, ++ max_cfg_depth, + phantom: PhantomData, + } + } +@@ -144,7 +146,7 @@ where + + let reachabilities = { + let cfg_metadata = state.metadata_mut::().unwrap(); +- cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) ++ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks, self.max_cfg_depth) + }; + + if !last_recalc_corpus_ids.contains(&idx) { +@@ -263,18 +265,18 @@ where + + let reachabilities = { + let cfg_metadata = state.metadata_mut::().unwrap(); +- cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) ++ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks, self.max_cfg_depth) + }; + + let tc = state.corpus().get(entry)?.borrow(); + let idx_meta = tc.metadata::().unwrap(); + for reachability in reachabilities { + // Only keep this if it's the best depth we've seen for this edge +- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { ++ if reachability.depth == 1 { // reachable_blocks_result.least_depth_for_index[&reachability.index] { + let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); + if freq.is_none() { println!("frequency is none for {:?}", reachability); } + let rarity = 1f64 / *freq.unwrap() as f64; +- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); ++ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); + if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } + neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; + reachability_favored |= favored_filled.insert(reachability.index); +@@ -417,12 +419,12 @@ where + } + } + +-impl Default for PrescientProbabilitySamplingScheduler +-where +- S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand, +- S::Input: HasLen, +-{ +- fn default() -> Self { +- Self::new_with_backoff(0.9999) +- } +-} +\ No newline at end of file ++// impl Default for PrescientProbabilitySamplingScheduler ++// where ++// S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand, ++// S::Input: HasLen, ++// { ++// fn default() -> Self { ++// Self::new_with_backoff(0.9999, 999) ++// } ++// } +\ No newline at end of file diff --git a/fuzzers/prescientfuzz_all/runner.Dockerfile b/fuzzers/prescientfuzz_direct_neighbour_fast/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_all/runner.Dockerfile rename to fuzzers/prescientfuzz_direct_neighbour_fast/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_direct_neighbours/builder.Dockerfile b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/builder.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_direct_neighbours/builder.Dockerfile rename to fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/builder.Dockerfile diff --git a/fuzzers/prescientfuzz_all_no_mopt/description.md b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/description.md similarity index 100% rename from fuzzers/prescientfuzz_all_no_mopt/description.md rename to fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/description.md diff --git a/fuzzers/prescientfuzz_all_no_mopt/fuzzer.py b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/fuzzer.py similarity index 100% rename from fuzzers/prescientfuzz_all_no_mopt/fuzzer.py rename to fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/fuzzer.py diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch new file mode 100644 index 000000000..c8f4963aa --- /dev/null +++ b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch @@ -0,0 +1,153 @@ +diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs +index e63325d8..adb2cb88 100644 +--- a/fuzzers/fuzzbench/src/lib.rs ++++ b/fuzzers/fuzzbench/src/lib.rs +@@ -322,17 +322,13 @@ fn fuzz( + // Setup a randomic Input2State stage + let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); + +- // Setup a MOPT mutator +- let mutator = StdMOptMutator::new( +- &mut state, +- havoc_mutations().merge(tokens_mutations()), +- 7, +- 5, +- )?; ++ // Setup a mutational stage with a basic bytes mutator ++ let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6); + + let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); + +- let scheduler = PrescientProbabilitySamplingScheduler::new_with_backoff(backoff_factor); ++ // set max_depth to 1, so only direct neighbours are counted ++ let scheduler = PrescientProbabilitySamplingScheduler::new_with_backoff(backoff_factor, 1); + + // A fuzzer with feedbacks and a corpus scheduler + let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); +diff --git a/libafl/src/feedbacks/cfg_prescience.rs b/libafl/src/feedbacks/cfg_prescience.rs +index 871cd858..bb4fc1b7 100644 +--- a/libafl/src/feedbacks/cfg_prescience.rs ++++ b/libafl/src/feedbacks/cfg_prescience.rs +@@ -725,7 +725,8 @@ impl ControlFlowGraph { + pub fn get_all_neighbours_full_depth( + &mut self, + input_coverage_map_indexes: &[usize], +- all_coverage_map_indexes: &HashSet ++ all_coverage_map_indexes: &HashSet, ++ max_depth: usize + ) -> Vec { + + let mut dupes = vec![]; +@@ -752,6 +753,11 @@ impl ControlFlowGraph { + + while let Some((depth, to_explore, direct_neighbour_predecessor)) = queue.pop_front() { + ++ // Don't keep exploring past max depth ++ if depth >= max_depth { ++ continue; ++ } ++ + debug_assert!(covered.contains(&to_explore), "to_explore: {to_explore}, covered: {:?}", covered); + + if to_explore >= 1_000_000 { +diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs +index 6761c534..9ce2013d 100644 +--- a/libafl/src/schedulers/prescient_weighted.rs ++++ b/libafl/src/schedulers/prescient_weighted.rs +@@ -23,16 +23,6 @@ use crate::{ + state::{HasCorpus, HasRand, State, UsesState}, Error + }; + +-/// Calculate Testcase probabilities using prescience +-#[derive(Debug, Clone)] +-pub struct PrescientProbabilitySamplingScheduler +-where +- S: UsesInput, +-{ +- backoff_factor: f64, +- phantom: PhantomData, +-} +- + /// A state metadata holding a map of probability of corpus elements. + #[derive(Debug, Serialize, Deserialize)] + #[cfg_attr( +@@ -85,6 +75,17 @@ struct ReachableBlocksResult { + } + + ++/// Calculate Testcase probabilities using prescience ++#[derive(Debug, Clone)] ++pub struct PrescientProbabilitySamplingScheduler ++where ++ S: UsesInput, ++{ ++ backoff_factor: f64, ++ max_cfg_depth: usize, ++ phantom: PhantomData, ++} ++ + impl PrescientProbabilitySamplingScheduler + where + S: HasCorpus + HasMetadata + HasNamedMetadata + HasRand, +@@ -92,9 +93,10 @@ where + { + /// Creates a new [`struct@ProbabilitySamplingScheduler`] + #[must_use] +- pub fn new_with_backoff(backoff_factor: f64) -> Self { ++ pub fn new_with_backoff(backoff_factor: f64, max_cfg_depth: usize) -> Self { + Self { + backoff_factor, ++ max_cfg_depth, + phantom: PhantomData, + } + } +@@ -144,7 +146,7 @@ where + + let reachabilities = { + let cfg_metadata = state.metadata_mut::().unwrap(); +- cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) ++ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks, self.max_cfg_depth) + }; + + if !last_recalc_corpus_ids.contains(&idx) { +@@ -263,14 +265,14 @@ where + + let reachabilities = { + let cfg_metadata = state.metadata_mut::().unwrap(); +- cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) ++ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks, self.max_cfg_depth) + }; + + let tc = state.corpus().get(entry)?.borrow(); + let idx_meta = tc.metadata::().unwrap(); + for reachability in reachabilities { + // Only keep this if it's the best depth we've seen for this edge +- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { ++ if reachability.depth == 1 { // reachable_blocks_result.least_depth_for_index[&reachability.index] { + let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); + if freq.is_none() { println!("frequency is none for {:?}", reachability); } + let rarity = 1f64 / *freq.unwrap() as f64; +@@ -417,12 +419,12 @@ where + } + } + +-impl Default for PrescientProbabilitySamplingScheduler +-where +- S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand, +- S::Input: HasLen, +-{ +- fn default() -> Self { +- Self::new_with_backoff(0.9999) +- } +-} +\ No newline at end of file ++// impl Default for PrescientProbabilitySamplingScheduler ++// where ++// S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand, ++// S::Input: HasLen, ++// { ++// fn default() -> Self { ++// Self::new_with_backoff(0.9999, 999) ++// } ++// } +\ No newline at end of file diff --git a/fuzzers/prescientfuzz_all_no_mopt/runner.Dockerfile b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_all_no_mopt/runner.Dockerfile rename to fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_direct_neighbours/description.md b/fuzzers/prescientfuzz_direct_neighbours/description.md deleted file mode 100644 index 452b0e374..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours/description.md +++ /dev/null @@ -1,8 +0,0 @@ -# PrescientFuzz - -based on libafl fuzzer instance - - persistent mode - -[builder.Dockerfile](builder.Dockerfile) -[fuzzer.py](fuzzer.py) -[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_direct_neighbours/fuzzer.py b/fuzzers/prescientfuzz_direct_neighbours/fuzzer.py deleted file mode 100755 index 5f2dfa95f..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours/fuzzer.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -"""Integration code for a LibAFL-based fuzzer.""" - -import os -import sys -import subprocess -from pathlib import Path - -from fuzzers import utils - - -def prepare_fuzz_environment(input_corpus): - """Prepare to fuzz with a LibAFL-based fuzzer.""" - os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ - 'malloc_context_size=0:symbolize=0:'\ - 'allocator_may_return_null=1:'\ - 'detect_odr_violation=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_abort=0:'\ - 'handle_sigfpe=0:handle_sigill=0' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ - 'allocator_release_to_os_interval_ms=500:'\ - 'handle_abort=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_sigfpe=0:'\ - 'handle_sigill=0:print_stacktrace=0:'\ - 'symbolize=0:symbolize_inline_frames=0' - # Create at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def build(): - """Build benchmark.""" - os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') - os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cxx') - - os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' - - cflags = ['--libafl'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - utils.append_flags('LDFLAGS', cflags) - - os.environ['FUZZER_LIB'] = '/stub_rt.a' - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - Path(cfg_file).touch() - os.environ['AFL_LLVM_CFG_FILE'] = cfg_file - utils.build_benchmark() - - -def fuzz(input_corpus, output_corpus, target_binary): - """Run fuzzer.""" - prepare_fuzz_environment(input_corpus) - dictionary_path = utils.get_dictionary_path(target_binary) - command = [target_binary] - if dictionary_path: - command += (['-x', dictionary_path]) - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - if os.path.exists(cfg_file): - command += (['-c', cfg_file]) - else: - sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) - fuzzer_env = os.environ.copy() - fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' - print(command) - subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_direct_neighbours/patch b/fuzzers/prescientfuzz_direct_neighbours/patch deleted file mode 100644 index 0d88780f3..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours/patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs -index 6761c534..316d5038 100644 ---- a/libafl/src/schedulers/prescient_weighted.rs -+++ b/libafl/src/schedulers/prescient_weighted.rs -@@ -270,13 +270,13 @@ where - let idx_meta = tc.metadata::().unwrap(); - for reachability in reachabilities { - // Only keep this if it's the best depth we've seen for this edge -- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { -+ if reachability.depth == 1 { // reachable_blocks_result.least_depth_for_index[&reachability.index] { - let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); - if freq.is_none() { println!("frequency is none for {:?}", reachability); } -- let rarity = 1f64 / *freq.unwrap() as f64; -- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); -+ let rarity = 1f64; // / *freq.unwrap() as f64; -+ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); - if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } -- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; -+ neighbour_score += backoff_weighting.unwrap() * rarity; // * 1f64 / reachability.depth as f64; - reachability_favored |= favored_filled.insert(reachability.index); - } - } diff --git a/fuzzers/prescientfuzz_direct_neighbours/runner.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours/runner.Dockerfile deleted file mode 100644 index 1a023b81e..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours/runner.Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FROM gcr.io/fuzzbench/base-image - -RUN apt install libjemalloc2 - -# This makes interactive docker runs painless: -ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" -ENV AFL_MAP_SIZE=2621440 -ENV PATH="$PATH:/out" -ENV AFL_SKIP_CPUFREQ=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 -ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_direct_neighbours_no_mopt/builder.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours_no_mopt/builder.Dockerfile deleted file mode 100644 index 4762c742f..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_no_mopt/builder.Dockerfile +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ARG parent_image -FROM $parent_image - -# Uninstall old Rust & Install the latest one. -RUN if which rustup; then rustup self uninstall -y; fi && \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh -y && \ - /root/.cargo/bin/rustup toolchain install nightly && \ - rm /rustup.sh - -RUN apt-get update && \ - apt-get install -y \ - build-essential \ - cargo && \ - apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ - libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ - apt-utils apt-transport-https ca-certificates joe curl && \ - PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make - -# Download PrescientFuzz -RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -COPY ./patch /PrescientFuzz/patch -RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 && git apply patch - -# Compile PrescientFuzz. -RUN cd /PrescientFuzz && \ - unset CFLAGS CXXFLAGS && \ - export CC=clang AFL_NO_X86 && \ - export LIBAFL_EDGES_MAP_SIZE=2621440 && \ - cd ./fuzzers/fuzzbench && \ - PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main - -# Auxiliary weak references. -RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ - clang -c stub_rt.c && \ - ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_direct_neighbours_no_mopt/description.md b/fuzzers/prescientfuzz_direct_neighbours_no_mopt/description.md deleted file mode 100644 index 452b0e374..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_no_mopt/description.md +++ /dev/null @@ -1,8 +0,0 @@ -# PrescientFuzz - -based on libafl fuzzer instance - - persistent mode - -[builder.Dockerfile](builder.Dockerfile) -[fuzzer.py](fuzzer.py) -[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_direct_neighbours_no_mopt/fuzzer.py b/fuzzers/prescientfuzz_direct_neighbours_no_mopt/fuzzer.py deleted file mode 100755 index 5f2dfa95f..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_no_mopt/fuzzer.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -"""Integration code for a LibAFL-based fuzzer.""" - -import os -import sys -import subprocess -from pathlib import Path - -from fuzzers import utils - - -def prepare_fuzz_environment(input_corpus): - """Prepare to fuzz with a LibAFL-based fuzzer.""" - os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ - 'malloc_context_size=0:symbolize=0:'\ - 'allocator_may_return_null=1:'\ - 'detect_odr_violation=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_abort=0:'\ - 'handle_sigfpe=0:handle_sigill=0' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ - 'allocator_release_to_os_interval_ms=500:'\ - 'handle_abort=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_sigfpe=0:'\ - 'handle_sigill=0:print_stacktrace=0:'\ - 'symbolize=0:symbolize_inline_frames=0' - # Create at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def build(): - """Build benchmark.""" - os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') - os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cxx') - - os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' - - cflags = ['--libafl'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - utils.append_flags('LDFLAGS', cflags) - - os.environ['FUZZER_LIB'] = '/stub_rt.a' - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - Path(cfg_file).touch() - os.environ['AFL_LLVM_CFG_FILE'] = cfg_file - utils.build_benchmark() - - -def fuzz(input_corpus, output_corpus, target_binary): - """Run fuzzer.""" - prepare_fuzz_environment(input_corpus) - dictionary_path = utils.get_dictionary_path(target_binary) - command = [target_binary] - if dictionary_path: - command += (['-x', dictionary_path]) - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - if os.path.exists(cfg_file): - command += (['-c', cfg_file]) - else: - sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) - fuzzer_env = os.environ.copy() - fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' - print(command) - subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_direct_neighbours_no_mopt/patch b/fuzzers/prescientfuzz_direct_neighbours_no_mopt/patch deleted file mode 100644 index 06de424ee..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_no_mopt/patch +++ /dev/null @@ -1,49 +0,0 @@ -diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs -index e63325d8..5e00b8ed 100644 ---- a/fuzzers/fuzzbench/src/lib.rs -+++ b/fuzzers/fuzzbench/src/lib.rs -@@ -322,13 +322,15 @@ fn fuzz( - // Setup a randomic Input2State stage - let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); - -- // Setup a MOPT mutator -- let mutator = StdMOptMutator::new( -- &mut state, -- havoc_mutations().merge(tokens_mutations()), -- 7, -- 5, -- )?; -+ // // Setup a MOPT mutator -+ // let mutator = StdMOptMutator::new( -+ // &mut state, -+ // havoc_mutations().merge(tokens_mutations()), -+ // 7, -+ // 5, -+ // )?; -+ // Setup a mutational stage with a basic bytes mutator -+ let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6); - - let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); - -diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs -index 6761c534..316d5038 100644 ---- a/libafl/src/schedulers/prescient_weighted.rs -+++ b/libafl/src/schedulers/prescient_weighted.rs -@@ -270,13 +270,13 @@ where - let idx_meta = tc.metadata::().unwrap(); - for reachability in reachabilities { - // Only keep this if it's the best depth we've seen for this edge -- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { -+ if reachability.depth == 1 { // reachable_blocks_result.least_depth_for_index[&reachability.index] { - let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); - if freq.is_none() { println!("frequency is none for {:?}", reachability); } -- let rarity = 1f64 / *freq.unwrap() as f64; -- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); -+ let rarity = 1f64; // / *freq.unwrap() as f64; -+ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); - if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } -- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; -+ neighbour_score += backoff_weighting.unwrap() * rarity; // * 1f64 / reachability.depth as f64; - reachability_favored |= favored_filled.insert(reachability.index); - } - } diff --git a/fuzzers/prescientfuzz_direct_neighbours_no_mopt/runner.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours_no_mopt/runner.Dockerfile deleted file mode 100644 index 1a023b81e..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_no_mopt/runner.Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FROM gcr.io/fuzzbench/base-image - -RUN apt install libjemalloc2 - -# This makes interactive docker runs painless: -ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" -ENV AFL_MAP_SIZE=2621440 -ENV PATH="$PATH:/out" -ENV AFL_SKIP_CPUFREQ=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 -ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_direct_neighbours_rarity/builder.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours_rarity/builder.Dockerfile deleted file mode 100644 index 4762c742f..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_rarity/builder.Dockerfile +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ARG parent_image -FROM $parent_image - -# Uninstall old Rust & Install the latest one. -RUN if which rustup; then rustup self uninstall -y; fi && \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh -y && \ - /root/.cargo/bin/rustup toolchain install nightly && \ - rm /rustup.sh - -RUN apt-get update && \ - apt-get install -y \ - build-essential \ - cargo && \ - apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ - libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ - apt-utils apt-transport-https ca-certificates joe curl && \ - PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make - -# Download PrescientFuzz -RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -COPY ./patch /PrescientFuzz/patch -RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 && git apply patch - -# Compile PrescientFuzz. -RUN cd /PrescientFuzz && \ - unset CFLAGS CXXFLAGS && \ - export CC=clang AFL_NO_X86 && \ - export LIBAFL_EDGES_MAP_SIZE=2621440 && \ - cd ./fuzzers/fuzzbench && \ - PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main - -# Auxiliary weak references. -RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ - clang -c stub_rt.c && \ - ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_direct_neighbours_rarity/description.md b/fuzzers/prescientfuzz_direct_neighbours_rarity/description.md deleted file mode 100644 index 452b0e374..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_rarity/description.md +++ /dev/null @@ -1,8 +0,0 @@ -# PrescientFuzz - -based on libafl fuzzer instance - - persistent mode - -[builder.Dockerfile](builder.Dockerfile) -[fuzzer.py](fuzzer.py) -[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_direct_neighbours_rarity/fuzzer.py b/fuzzers/prescientfuzz_direct_neighbours_rarity/fuzzer.py deleted file mode 100755 index 5f2dfa95f..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_rarity/fuzzer.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -"""Integration code for a LibAFL-based fuzzer.""" - -import os -import sys -import subprocess -from pathlib import Path - -from fuzzers import utils - - -def prepare_fuzz_environment(input_corpus): - """Prepare to fuzz with a LibAFL-based fuzzer.""" - os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ - 'malloc_context_size=0:symbolize=0:'\ - 'allocator_may_return_null=1:'\ - 'detect_odr_violation=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_abort=0:'\ - 'handle_sigfpe=0:handle_sigill=0' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ - 'allocator_release_to_os_interval_ms=500:'\ - 'handle_abort=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_sigfpe=0:'\ - 'handle_sigill=0:print_stacktrace=0:'\ - 'symbolize=0:symbolize_inline_frames=0' - # Create at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def build(): - """Build benchmark.""" - os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') - os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cxx') - - os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' - - cflags = ['--libafl'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - utils.append_flags('LDFLAGS', cflags) - - os.environ['FUZZER_LIB'] = '/stub_rt.a' - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - Path(cfg_file).touch() - os.environ['AFL_LLVM_CFG_FILE'] = cfg_file - utils.build_benchmark() - - -def fuzz(input_corpus, output_corpus, target_binary): - """Run fuzzer.""" - prepare_fuzz_environment(input_corpus) - dictionary_path = utils.get_dictionary_path(target_binary) - command = [target_binary] - if dictionary_path: - command += (['-x', dictionary_path]) - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - if os.path.exists(cfg_file): - command += (['-c', cfg_file]) - else: - sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) - fuzzer_env = os.environ.copy() - fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' - print(command) - subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_direct_neighbours_rarity/patch b/fuzzers/prescientfuzz_direct_neighbours_rarity/patch deleted file mode 100644 index dab36b79d..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_rarity/patch +++ /dev/null @@ -1,34 +0,0 @@ -diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs -index e63325d8..1f128a4c 100644 ---- a/fuzzers/fuzzbench/src/lib.rs -+++ b/fuzzers/fuzzbench/src/lib.rs -@@ -329,6 +329,8 @@ fn fuzz( - 7, - 5, - )?; -+ // Setup a mutational stage with a basic bytes mutator -+ // let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6); - - let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); - -diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs -index 6761c534..1879e0b3 100644 ---- a/libafl/src/schedulers/prescient_weighted.rs -+++ b/libafl/src/schedulers/prescient_weighted.rs -@@ -270,13 +270,13 @@ where - let idx_meta = tc.metadata::().unwrap(); - for reachability in reachabilities { - // Only keep this if it's the best depth we've seen for this edge -- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { -+ if reachability.depth == 1 { // reachable_blocks_result.least_depth_for_index[&reachability.index] { - let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); - if freq.is_none() { println!("frequency is none for {:?}", reachability); } - let rarity = 1f64 / *freq.unwrap() as f64; -- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); -+ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); - if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } -- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; -+ neighbour_score += backoff_weighting.unwrap() * rarity; // * 1f64 / reachability.depth as f64; - reachability_favored |= favored_filled.insert(reachability.index); - } - } diff --git a/fuzzers/prescientfuzz_direct_neighbours_rarity/runner.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours_rarity/runner.Dockerfile deleted file mode 100644 index 1a023b81e..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_rarity/runner.Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FROM gcr.io/fuzzbench/base-image - -RUN apt install libjemalloc2 - -# This makes interactive docker runs painless: -ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" -ENV AFL_MAP_SIZE=2621440 -ENV PATH="$PATH:/out" -ENV AFL_SKIP_CPUFREQ=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 -ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/builder.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/builder.Dockerfile deleted file mode 100644 index 4762c742f..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/builder.Dockerfile +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ARG parent_image -FROM $parent_image - -# Uninstall old Rust & Install the latest one. -RUN if which rustup; then rustup self uninstall -y; fi && \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh -y && \ - /root/.cargo/bin/rustup toolchain install nightly && \ - rm /rustup.sh - -RUN apt-get update && \ - apt-get install -y \ - build-essential \ - cargo && \ - apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ - libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ - apt-utils apt-transport-https ca-certificates joe curl && \ - PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make - -# Download PrescientFuzz -RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -COPY ./patch /PrescientFuzz/patch -RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 && git apply patch - -# Compile PrescientFuzz. -RUN cd /PrescientFuzz && \ - unset CFLAGS CXXFLAGS && \ - export CC=clang AFL_NO_X86 && \ - export LIBAFL_EDGES_MAP_SIZE=2621440 && \ - cd ./fuzzers/fuzzbench && \ - PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main - -# Auxiliary weak references. -RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ - clang -c stub_rt.c && \ - ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/description.md b/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/description.md deleted file mode 100644 index 452b0e374..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/description.md +++ /dev/null @@ -1,8 +0,0 @@ -# PrescientFuzz - -based on libafl fuzzer instance - - persistent mode - -[builder.Dockerfile](builder.Dockerfile) -[fuzzer.py](fuzzer.py) -[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/fuzzer.py b/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/fuzzer.py deleted file mode 100755 index 5f2dfa95f..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/fuzzer.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -"""Integration code for a LibAFL-based fuzzer.""" - -import os -import sys -import subprocess -from pathlib import Path - -from fuzzers import utils - - -def prepare_fuzz_environment(input_corpus): - """Prepare to fuzz with a LibAFL-based fuzzer.""" - os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ - 'malloc_context_size=0:symbolize=0:'\ - 'allocator_may_return_null=1:'\ - 'detect_odr_violation=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_abort=0:'\ - 'handle_sigfpe=0:handle_sigill=0' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ - 'allocator_release_to_os_interval_ms=500:'\ - 'handle_abort=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_sigfpe=0:'\ - 'handle_sigill=0:print_stacktrace=0:'\ - 'symbolize=0:symbolize_inline_frames=0' - # Create at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def build(): - """Build benchmark.""" - os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') - os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cxx') - - os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' - - cflags = ['--libafl'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - utils.append_flags('LDFLAGS', cflags) - - os.environ['FUZZER_LIB'] = '/stub_rt.a' - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - Path(cfg_file).touch() - os.environ['AFL_LLVM_CFG_FILE'] = cfg_file - utils.build_benchmark() - - -def fuzz(input_corpus, output_corpus, target_binary): - """Run fuzzer.""" - prepare_fuzz_environment(input_corpus) - dictionary_path = utils.get_dictionary_path(target_binary) - command = [target_binary] - if dictionary_path: - command += (['-x', dictionary_path]) - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - if os.path.exists(cfg_file): - command += (['-c', cfg_file]) - else: - sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) - fuzzer_env = os.environ.copy() - fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' - print(command) - subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/patch b/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/patch deleted file mode 100644 index 4aabaa330..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/patch +++ /dev/null @@ -1,48 +0,0 @@ -diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs -index e63325d8..5e00b8ed 100644 ---- a/fuzzers/fuzzbench/src/lib.rs -+++ b/fuzzers/fuzzbench/src/lib.rs -@@ -322,13 +322,15 @@ fn fuzz( - // Setup a randomic Input2State stage - let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); - -- // Setup a MOPT mutator -- let mutator = StdMOptMutator::new( -- &mut state, -- havoc_mutations().merge(tokens_mutations()), -- 7, -- 5, -- )?; -+ // // Setup a MOPT mutator -+ // let mutator = StdMOptMutator::new( -+ // &mut state, -+ // havoc_mutations().merge(tokens_mutations()), -+ // 7, -+ // 5, -+ // )?; -+ // Setup a mutational stage with a basic bytes mutator -+ let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6); - - let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); - -diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs -index 6761c534..1879e0b3 100644 ---- a/libafl/src/schedulers/prescient_weighted.rs -+++ b/libafl/src/schedulers/prescient_weighted.rs -@@ -270,13 +270,13 @@ where - let idx_meta = tc.metadata::().unwrap(); - for reachability in reachabilities { - // Only keep this if it's the best depth we've seen for this edge -- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { -+ if reachability.depth == 1 { // reachable_blocks_result.least_depth_for_index[&reachability.index] { - let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); - if freq.is_none() { println!("frequency is none for {:?}", reachability); } - let rarity = 1f64 / *freq.unwrap() as f64; -- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); -+ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); - if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } -- neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; -+ neighbour_score += backoff_weighting.unwrap() * rarity; // * 1f64 / reachability.depth as f64; - reachability_favored |= favored_filled.insert(reachability.index); - } - } diff --git a/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/runner.Dockerfile b/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/runner.Dockerfile deleted file mode 100644 index 1a023b81e..000000000 --- a/fuzzers/prescientfuzz_direct_neighbours_rarity_no_mopt/runner.Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FROM gcr.io/fuzzbench/base-image - -RUN apt install libjemalloc2 - -# This makes interactive docker runs painless: -ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" -ENV AFL_MAP_SIZE=2621440 -ENV PATH="$PATH:/out" -ENV AFL_SKIP_CPUFREQ=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 -ENV AFL_TESTCACHE_SIZE=2 From 83645a8871c8e906294f219949ed0af4ebe55249 Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Tue, 18 Jun 2024 10:29:53 +0100 Subject: [PATCH 22/25] Added rand scheduler setup for libafl (to act as true control) --- .../libafl_rand_scheduler/builder.Dockerfile | 61 ++++++++++++++++ fuzzers/libafl_rand_scheduler/description.md | 11 +++ fuzzers/libafl_rand_scheduler/fuzzer.py | 72 +++++++++++++++++++ fuzzers/libafl_rand_scheduler/patch | 39 ++++++++++ .../libafl_rand_scheduler/runner.Dockerfile | 25 +++++++ 5 files changed, 208 insertions(+) create mode 100644 fuzzers/libafl_rand_scheduler/builder.Dockerfile create mode 100644 fuzzers/libafl_rand_scheduler/description.md create mode 100755 fuzzers/libafl_rand_scheduler/fuzzer.py create mode 100644 fuzzers/libafl_rand_scheduler/patch create mode 100644 fuzzers/libafl_rand_scheduler/runner.Dockerfile diff --git a/fuzzers/libafl_rand_scheduler/builder.Dockerfile b/fuzzers/libafl_rand_scheduler/builder.Dockerfile new file mode 100644 index 000000000..cc348e702 --- /dev/null +++ b/fuzzers/libafl_rand_scheduler/builder.Dockerfile @@ -0,0 +1,61 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh --default-toolchain nightly-2023-09-21 -y && \ + rm /rustup.sh + +# Install dependencies. +RUN apt-get update && \ + apt-get remove -y llvm-10 && \ + apt-get install -y \ + build-essential \ + lsb-release wget software-properties-common gnupg && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 17 + +RUN wget https://gist.githubusercontent.com/tokatoka/26f4ba95991c6e33139999976332aa8e/raw/698ac2087d58ce5c7a6ad59adce58dbfdc32bd46/createAliases.sh && chmod u+x ./createAliases.sh && ./createAliases.sh + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh --default-toolchain nightly-2024-06-16 -y && \ + rm /rustup.sh + +# Download libafl. +RUN git clone https://github.com/AFLplusplus/LibAFL /libafl + +# Checkout a current commit +COPY ./patch /libafl/patch +RUN cd /libafl && git pull && git checkout b4efb6151550a37f61a869acf2957a1b07894a93 && git apply patch || true +# Note that due a nightly bug it is currently fixed to a known version on top! + +# Compile libafl. +RUN cd /libafl && \ + unset CFLAGS CXXFLAGS && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /libafl/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/libafl_rand_scheduler/description.md b/fuzzers/libafl_rand_scheduler/description.md new file mode 100644 index 000000000..ea9b947d6 --- /dev/null +++ b/fuzzers/libafl_rand_scheduler/description.md @@ -0,0 +1,11 @@ +# libafl + +libafl fuzzer instance + - cmplog feature + - persistent mode + +Repository: [https://github.com/AFLplusplus/libafl/](https://github.com/AFLplusplus/libafl/) + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/libafl_rand_scheduler/fuzzer.py b/fuzzers/libafl_rand_scheduler/fuzzer.py new file mode 100755 index 000000000..0f191a744 --- /dev/null +++ b/fuzzers/libafl_rand_scheduler/fuzzer.py @@ -0,0 +1,72 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import subprocess + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): # pylint: disable=too-many-branches,too-many-statements + """Build benchmark.""" + os.environ[ + 'CC'] = '/libafl/fuzzers/fuzzbench/target/release-fuzzbench/libafl_cc' + os.environ[ + 'CXX'] = '/libafl/fuzzers/fuzzbench/target/release-fuzzbench/libafl_cxx' + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + cxxflags = ['--libafl', '--std=c++14'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cxxflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['FUZZER_LIB'] = '/stub_rt.a' + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + command += (['-o', output_corpus, '-i', input_corpus]) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/libafl_rand_scheduler/patch b/fuzzers/libafl_rand_scheduler/patch new file mode 100644 index 000000000..6f6e13bcd --- /dev/null +++ b/fuzzers/libafl_rand_scheduler/patch @@ -0,0 +1,39 @@ +diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs +index 9b162a48..af4ff31f 100644 +--- a/fuzzers/fuzzbench/src/lib.rs ++++ b/fuzzers/fuzzbench/src/lib.rs +@@ -29,9 +29,7 @@ use libafl::{ + StdMOptMutator, StdScheduledMutator, Tokens, + }, + observers::{CanTrack, HitcountsMapObserver, TimeObserver}, +- schedulers::{ +- powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, +- }, ++ schedulers::RandScheduler, + stages::{ + calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage, + TracingStage, +@@ -307,11 +305,8 @@ fn fuzz( + + let power = StdPowerMutationalStage::new(mutator); + +- // A minimization+queue policy to get testcasess from the corpus +- let scheduler = IndexesLenTimeMinimizerScheduler::new( +- &edges_observer, +- StdWeightedScheduler::with_schedule(&mut state, &edges_observer, Some(PowerSchedule::FAST)), +- ); ++ // A random scheduler ++ let scheduler = RandScheduler::new(); + + // A fuzzer with feedbacks and a corpus scheduler + let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); +diff --git a/libafl_bolts/build.rs b/libafl_bolts/build.rs +index 5253398d..39acd4c6 100644 +--- a/libafl_bolts/build.rs ++++ b/libafl_bolts/build.rs +@@ -1,3 +1,5 @@ ++#![feature(error_in_core)] ++ + #[rustversion::nightly] + fn nightly() { + println!("cargo:rustc-cfg=nightly"); diff --git a/fuzzers/libafl_rand_scheduler/runner.Dockerfile b/fuzzers/libafl_rand_scheduler/runner.Dockerfile new file mode 100644 index 000000000..f0c5eb6cc --- /dev/null +++ b/fuzzers/libafl_rand_scheduler/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +#ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 From d16da1a7c43d8c36538843e1e90468098ce47e0e Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Wed, 19 Jun 2024 10:58:17 +0100 Subject: [PATCH 23/25] Fix typo (>= instead of >) --- fuzzers/prescientfuzz_direct_neighbour_fast/patch | 4 ++-- fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast/patch b/fuzzers/prescientfuzz_direct_neighbour_fast/patch index 9b4d7bc99..5f5b4c117 100644 --- a/fuzzers/prescientfuzz_direct_neighbour_fast/patch +++ b/fuzzers/prescientfuzz_direct_neighbour_fast/patch @@ -25,7 +25,7 @@ index e63325d8..adb2cb88 100644 // A fuzzer with feedbacks and a corpus scheduler let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); diff --git a/libafl/src/feedbacks/cfg_prescience.rs b/libafl/src/feedbacks/cfg_prescience.rs -index 871cd858..bb4fc1b7 100644 +index 871cd858..e11350f4 100644 --- a/libafl/src/feedbacks/cfg_prescience.rs +++ b/libafl/src/feedbacks/cfg_prescience.rs @@ -725,7 +725,8 @@ impl ControlFlowGraph { @@ -43,7 +43,7 @@ index 871cd858..bb4fc1b7 100644 while let Some((depth, to_explore, direct_neighbour_predecessor)) = queue.pop_front() { + // Don't keep exploring past max depth -+ if depth >= max_depth { ++ if depth > max_depth { + continue; + } + diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch index c8f4963aa..34d94c417 100644 --- a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch +++ b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch @@ -25,7 +25,7 @@ index e63325d8..adb2cb88 100644 // A fuzzer with feedbacks and a corpus scheduler let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); diff --git a/libafl/src/feedbacks/cfg_prescience.rs b/libafl/src/feedbacks/cfg_prescience.rs -index 871cd858..bb4fc1b7 100644 +index 871cd858..e11350f4 100644 --- a/libafl/src/feedbacks/cfg_prescience.rs +++ b/libafl/src/feedbacks/cfg_prescience.rs @@ -725,7 +725,8 @@ impl ControlFlowGraph { @@ -43,7 +43,7 @@ index 871cd858..bb4fc1b7 100644 while let Some((depth, to_explore, direct_neighbour_predecessor)) = queue.pop_front() { + // Don't keep exploring past max depth -+ if depth >= max_depth { ++ if depth > max_depth { + continue; + } + From fd4b24b51476f9bf110ca0423b1ca5629a85c06d Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Mon, 29 Jul 2024 11:14:54 +0100 Subject: [PATCH 24/25] Added PrescientFuzz with compiler flag to expand binary conditionals --- .../builder.Dockerfile | 3 +- .../description.md | 0 .../fuzzer.py | 0 .../runner.Dockerfile | 0 .../prescientfuzz_direct_neighbour_fast/patch | 158 ------------------ .../builder.Dockerfile | 50 ------ .../description.md | 8 - .../fuzzer.py | 83 --------- .../patch | 153 ----------------- .../runner.Dockerfile | 25 --- 10 files changed, 1 insertion(+), 479 deletions(-) rename fuzzers/{prescientfuzz_direct_neighbour_fast => prescientfuzz}/builder.Dockerfile (92%) rename fuzzers/{prescientfuzz_direct_neighbour_fast => prescientfuzz}/description.md (100%) rename fuzzers/{prescientfuzz_direct_neighbour_fast => prescientfuzz}/fuzzer.py (100%) rename fuzzers/{prescientfuzz_direct_neighbour_fast => prescientfuzz}/runner.Dockerfile (100%) delete mode 100644 fuzzers/prescientfuzz_direct_neighbour_fast/patch delete mode 100644 fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/builder.Dockerfile delete mode 100644 fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/description.md delete mode 100755 fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/fuzzer.py delete mode 100644 fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch delete mode 100644 fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast/builder.Dockerfile b/fuzzers/prescientfuzz/builder.Dockerfile similarity index 92% rename from fuzzers/prescientfuzz_direct_neighbour_fast/builder.Dockerfile rename to fuzzers/prescientfuzz/builder.Dockerfile index 4762c742f..4470a39c8 100644 --- a/fuzzers/prescientfuzz_direct_neighbour_fast/builder.Dockerfile +++ b/fuzzers/prescientfuzz/builder.Dockerfile @@ -33,8 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -COPY ./patch /PrescientFuzz/patch -RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 && git apply patch +RUN cd /PrescientFuzz && git fetch && git checkout b8f55284dafc0d63108d1cc31a0b476a347cf205 # Compile PrescientFuzz. RUN cd /PrescientFuzz && \ diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast/description.md b/fuzzers/prescientfuzz/description.md similarity index 100% rename from fuzzers/prescientfuzz_direct_neighbour_fast/description.md rename to fuzzers/prescientfuzz/description.md diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast/fuzzer.py b/fuzzers/prescientfuzz/fuzzer.py similarity index 100% rename from fuzzers/prescientfuzz_direct_neighbour_fast/fuzzer.py rename to fuzzers/prescientfuzz/fuzzer.py diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast/runner.Dockerfile b/fuzzers/prescientfuzz/runner.Dockerfile similarity index 100% rename from fuzzers/prescientfuzz_direct_neighbour_fast/runner.Dockerfile rename to fuzzers/prescientfuzz/runner.Dockerfile diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast/patch b/fuzzers/prescientfuzz_direct_neighbour_fast/patch deleted file mode 100644 index 5f5b4c117..000000000 --- a/fuzzers/prescientfuzz_direct_neighbour_fast/patch +++ /dev/null @@ -1,158 +0,0 @@ -diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs -index e63325d8..adb2cb88 100644 ---- a/fuzzers/fuzzbench/src/lib.rs -+++ b/fuzzers/fuzzbench/src/lib.rs -@@ -322,17 +322,13 @@ fn fuzz( - // Setup a randomic Input2State stage - let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); - -- // Setup a MOPT mutator -- let mutator = StdMOptMutator::new( -- &mut state, -- havoc_mutations().merge(tokens_mutations()), -- 7, -- 5, -- )?; -+ // Setup a mutational stage with a basic bytes mutator -+ let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6); - - let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); - -- let scheduler = PrescientProbabilitySamplingScheduler::new_with_backoff(backoff_factor); -+ // set max_depth to 1, so only direct neighbours are counted -+ let scheduler = PrescientProbabilitySamplingScheduler::new_with_backoff(backoff_factor, 1); - - // A fuzzer with feedbacks and a corpus scheduler - let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); -diff --git a/libafl/src/feedbacks/cfg_prescience.rs b/libafl/src/feedbacks/cfg_prescience.rs -index 871cd858..e11350f4 100644 ---- a/libafl/src/feedbacks/cfg_prescience.rs -+++ b/libafl/src/feedbacks/cfg_prescience.rs -@@ -725,7 +725,8 @@ impl ControlFlowGraph { - pub fn get_all_neighbours_full_depth( - &mut self, - input_coverage_map_indexes: &[usize], -- all_coverage_map_indexes: &HashSet -+ all_coverage_map_indexes: &HashSet, -+ max_depth: usize - ) -> Vec { - - let mut dupes = vec![]; -@@ -752,6 +753,11 @@ impl ControlFlowGraph { - - while let Some((depth, to_explore, direct_neighbour_predecessor)) = queue.pop_front() { - -+ // Don't keep exploring past max depth -+ if depth > max_depth { -+ continue; -+ } -+ - debug_assert!(covered.contains(&to_explore), "to_explore: {to_explore}, covered: {:?}", covered); - - if to_explore >= 1_000_000 { -diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs -index 6761c534..8fd1e74b 100644 ---- a/libafl/src/schedulers/prescient_weighted.rs -+++ b/libafl/src/schedulers/prescient_weighted.rs -@@ -23,16 +23,6 @@ use crate::{ - state::{HasCorpus, HasRand, State, UsesState}, Error - }; - --/// Calculate Testcase probabilities using prescience --#[derive(Debug, Clone)] --pub struct PrescientProbabilitySamplingScheduler --where -- S: UsesInput, --{ -- backoff_factor: f64, -- phantom: PhantomData, --} -- - /// A state metadata holding a map of probability of corpus elements. - #[derive(Debug, Serialize, Deserialize)] - #[cfg_attr( -@@ -85,6 +75,17 @@ struct ReachableBlocksResult { - } - - -+/// Calculate Testcase probabilities using prescience -+#[derive(Debug, Clone)] -+pub struct PrescientProbabilitySamplingScheduler -+where -+ S: UsesInput, -+{ -+ backoff_factor: f64, -+ max_cfg_depth: usize, -+ phantom: PhantomData, -+} -+ - impl PrescientProbabilitySamplingScheduler - where - S: HasCorpus + HasMetadata + HasNamedMetadata + HasRand, -@@ -92,9 +93,10 @@ where - { - /// Creates a new [`struct@ProbabilitySamplingScheduler`] - #[must_use] -- pub fn new_with_backoff(backoff_factor: f64) -> Self { -+ pub fn new_with_backoff(backoff_factor: f64, max_cfg_depth: usize) -> Self { - Self { - backoff_factor, -+ max_cfg_depth, - phantom: PhantomData, - } - } -@@ -144,7 +146,7 @@ where - - let reachabilities = { - let cfg_metadata = state.metadata_mut::().unwrap(); -- cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) -+ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks, self.max_cfg_depth) - }; - - if !last_recalc_corpus_ids.contains(&idx) { -@@ -263,18 +265,18 @@ where - - let reachabilities = { - let cfg_metadata = state.metadata_mut::().unwrap(); -- cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) -+ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks, self.max_cfg_depth) - }; - - let tc = state.corpus().get(entry)?.borrow(); - let idx_meta = tc.metadata::().unwrap(); - for reachability in reachabilities { - // Only keep this if it's the best depth we've seen for this edge -- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { -+ if reachability.depth == 1 { // reachable_blocks_result.least_depth_for_index[&reachability.index] { - let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); - if freq.is_none() { println!("frequency is none for {:?}", reachability); } - let rarity = 1f64 / *freq.unwrap() as f64; -- let backoff_weighting = backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); -+ let backoff_weighting = Some(1f64); // backoff_weighting_for_direct_neighbour.get(&reachability.direct_neighbour_ancestor_index); - if backoff_weighting.is_none() { println!("backoff_weighting is none for {:?}", reachability.direct_neighbour_ancestor_index); } - neighbour_score += backoff_weighting.unwrap() * rarity * 1f64 / reachability.depth as f64; - reachability_favored |= favored_filled.insert(reachability.index); -@@ -417,12 +419,12 @@ where - } - } - --impl Default for PrescientProbabilitySamplingScheduler --where -- S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand, -- S::Input: HasLen, --{ -- fn default() -> Self { -- Self::new_with_backoff(0.9999) -- } --} -\ No newline at end of file -+// impl Default for PrescientProbabilitySamplingScheduler -+// where -+// S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand, -+// S::Input: HasLen, -+// { -+// fn default() -> Self { -+// Self::new_with_backoff(0.9999, 999) -+// } -+// } -\ No newline at end of file diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/builder.Dockerfile b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/builder.Dockerfile deleted file mode 100644 index 4762c742f..000000000 --- a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/builder.Dockerfile +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ARG parent_image -FROM $parent_image - -# Uninstall old Rust & Install the latest one. -RUN if which rustup; then rustup self uninstall -y; fi && \ - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ - sh /rustup.sh -y && \ - /root/.cargo/bin/rustup toolchain install nightly && \ - rm /rustup.sh - -RUN apt-get update && \ - apt-get install -y \ - build-essential \ - cargo && \ - apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ - libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ - apt-utils apt-transport-https ca-certificates joe curl && \ - PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make - -# Download PrescientFuzz -RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -COPY ./patch /PrescientFuzz/patch -RUN cd /PrescientFuzz && git fetch && git checkout 0299c8eed31c2a06eb064dee3c7cc4d66af90530 && git apply patch - -# Compile PrescientFuzz. -RUN cd /PrescientFuzz && \ - unset CFLAGS CXXFLAGS && \ - export CC=clang AFL_NO_X86 && \ - export LIBAFL_EDGES_MAP_SIZE=2621440 && \ - cd ./fuzzers/fuzzbench && \ - PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main - -# Auxiliary weak references. -RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ - clang -c stub_rt.c && \ - ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/description.md b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/description.md deleted file mode 100644 index 452b0e374..000000000 --- a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/description.md +++ /dev/null @@ -1,8 +0,0 @@ -# PrescientFuzz - -based on libafl fuzzer instance - - persistent mode - -[builder.Dockerfile](builder.Dockerfile) -[fuzzer.py](fuzzer.py) -[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/fuzzer.py b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/fuzzer.py deleted file mode 100755 index 5f2dfa95f..000000000 --- a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/fuzzer.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -"""Integration code for a LibAFL-based fuzzer.""" - -import os -import sys -import subprocess -from pathlib import Path - -from fuzzers import utils - - -def prepare_fuzz_environment(input_corpus): - """Prepare to fuzz with a LibAFL-based fuzzer.""" - os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ - 'malloc_context_size=0:symbolize=0:'\ - 'allocator_may_return_null=1:'\ - 'detect_odr_violation=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_abort=0:'\ - 'handle_sigfpe=0:handle_sigill=0' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ - 'allocator_release_to_os_interval_ms=500:'\ - 'handle_abort=0:handle_segv=0:'\ - 'handle_sigbus=0:handle_sigfpe=0:'\ - 'handle_sigill=0:print_stacktrace=0:'\ - 'symbolize=0:symbolize_inline_frames=0' - # Create at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def build(): - """Build benchmark.""" - os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cc') - os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' - 'release-fuzzbench/libafl_cxx') - - os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' - os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' - - cflags = ['--libafl'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - utils.append_flags('LDFLAGS', cflags) - - os.environ['FUZZER_LIB'] = '/stub_rt.a' - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - Path(cfg_file).touch() - os.environ['AFL_LLVM_CFG_FILE'] = cfg_file - utils.build_benchmark() - - -def fuzz(input_corpus, output_corpus, target_binary): - """Run fuzzer.""" - prepare_fuzz_environment(input_corpus) - dictionary_path = utils.get_dictionary_path(target_binary) - command = [target_binary] - if dictionary_path: - command += (['-x', dictionary_path]) - build_directory = os.environ['OUT'] - cfg_file = build_directory + '/afl_cfg.bin' - if os.path.exists(cfg_file): - command += (['-c', cfg_file]) - else: - sys.exit(1) - command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) - fuzzer_env = os.environ.copy() - fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' - print(command) - subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch deleted file mode 100644 index 34d94c417..000000000 --- a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/patch +++ /dev/null @@ -1,153 +0,0 @@ -diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs -index e63325d8..adb2cb88 100644 ---- a/fuzzers/fuzzbench/src/lib.rs -+++ b/fuzzers/fuzzbench/src/lib.rs -@@ -322,17 +322,13 @@ fn fuzz( - // Setup a randomic Input2State stage - let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); - -- // Setup a MOPT mutator -- let mutator = StdMOptMutator::new( -- &mut state, -- havoc_mutations().merge(tokens_mutations()), -- 7, -- 5, -- )?; -+ // Setup a mutational stage with a basic bytes mutator -+ let mutator = StdScheduledMutator::with_max_stack_pow(havoc_mutations().merge(tokens_mutations()), 6); - - let mutation = StdMutationalStage::with_max_iterations(mutator, 1024); - -- let scheduler = PrescientProbabilitySamplingScheduler::new_with_backoff(backoff_factor); -+ // set max_depth to 1, so only direct neighbours are counted -+ let scheduler = PrescientProbabilitySamplingScheduler::new_with_backoff(backoff_factor, 1); - - // A fuzzer with feedbacks and a corpus scheduler - let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); -diff --git a/libafl/src/feedbacks/cfg_prescience.rs b/libafl/src/feedbacks/cfg_prescience.rs -index 871cd858..e11350f4 100644 ---- a/libafl/src/feedbacks/cfg_prescience.rs -+++ b/libafl/src/feedbacks/cfg_prescience.rs -@@ -725,7 +725,8 @@ impl ControlFlowGraph { - pub fn get_all_neighbours_full_depth( - &mut self, - input_coverage_map_indexes: &[usize], -- all_coverage_map_indexes: &HashSet -+ all_coverage_map_indexes: &HashSet, -+ max_depth: usize - ) -> Vec { - - let mut dupes = vec![]; -@@ -752,6 +753,11 @@ impl ControlFlowGraph { - - while let Some((depth, to_explore, direct_neighbour_predecessor)) = queue.pop_front() { - -+ // Don't keep exploring past max depth -+ if depth > max_depth { -+ continue; -+ } -+ - debug_assert!(covered.contains(&to_explore), "to_explore: {to_explore}, covered: {:?}", covered); - - if to_explore >= 1_000_000 { -diff --git a/libafl/src/schedulers/prescient_weighted.rs b/libafl/src/schedulers/prescient_weighted.rs -index 6761c534..9ce2013d 100644 ---- a/libafl/src/schedulers/prescient_weighted.rs -+++ b/libafl/src/schedulers/prescient_weighted.rs -@@ -23,16 +23,6 @@ use crate::{ - state::{HasCorpus, HasRand, State, UsesState}, Error - }; - --/// Calculate Testcase probabilities using prescience --#[derive(Debug, Clone)] --pub struct PrescientProbabilitySamplingScheduler --where -- S: UsesInput, --{ -- backoff_factor: f64, -- phantom: PhantomData, --} -- - /// A state metadata holding a map of probability of corpus elements. - #[derive(Debug, Serialize, Deserialize)] - #[cfg_attr( -@@ -85,6 +75,17 @@ struct ReachableBlocksResult { - } - - -+/// Calculate Testcase probabilities using prescience -+#[derive(Debug, Clone)] -+pub struct PrescientProbabilitySamplingScheduler -+where -+ S: UsesInput, -+{ -+ backoff_factor: f64, -+ max_cfg_depth: usize, -+ phantom: PhantomData, -+} -+ - impl PrescientProbabilitySamplingScheduler - where - S: HasCorpus + HasMetadata + HasNamedMetadata + HasRand, -@@ -92,9 +93,10 @@ where - { - /// Creates a new [`struct@ProbabilitySamplingScheduler`] - #[must_use] -- pub fn new_with_backoff(backoff_factor: f64) -> Self { -+ pub fn new_with_backoff(backoff_factor: f64, max_cfg_depth: usize) -> Self { - Self { - backoff_factor, -+ max_cfg_depth, - phantom: PhantomData, - } - } -@@ -144,7 +146,7 @@ where - - let reachabilities = { - let cfg_metadata = state.metadata_mut::().unwrap(); -- cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) -+ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks, self.max_cfg_depth) - }; - - if !last_recalc_corpus_ids.contains(&idx) { -@@ -263,14 +265,14 @@ where - - let reachabilities = { - let cfg_metadata = state.metadata_mut::().unwrap(); -- cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks) -+ cfg_metadata.get_all_neighbours_full_depth(&covered_indexes, &covered_blocks, self.max_cfg_depth) - }; - - let tc = state.corpus().get(entry)?.borrow(); - let idx_meta = tc.metadata::().unwrap(); - for reachability in reachabilities { - // Only keep this if it's the best depth we've seen for this edge -- if reachability.depth == reachable_blocks_result.least_depth_for_index[&reachability.index] { -+ if reachability.depth == 1 { // reachable_blocks_result.least_depth_for_index[&reachability.index] { - let freq = reachable_blocks_result.frequency_for_reachability.get(&reachability); - if freq.is_none() { println!("frequency is none for {:?}", reachability); } - let rarity = 1f64 / *freq.unwrap() as f64; -@@ -417,12 +419,12 @@ where - } - } - --impl Default for PrescientProbabilitySamplingScheduler --where -- S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand, -- S::Input: HasLen, --{ -- fn default() -> Self { -- Self::new_with_backoff(0.9999) -- } --} -\ No newline at end of file -+// impl Default for PrescientProbabilitySamplingScheduler -+// where -+// S: HasCorpus + HasNamedMetadata + HasMetadata + HasRand, -+// S::Input: HasLen, -+// { -+// fn default() -> Self { -+// Self::new_with_backoff(0.9999, 999) -+// } -+// } -\ No newline at end of file diff --git a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/runner.Dockerfile b/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/runner.Dockerfile deleted file mode 100644 index 1a023b81e..000000000 --- a/fuzzers/prescientfuzz_direct_neighbour_fast_w_backoff/runner.Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FROM gcr.io/fuzzbench/base-image - -RUN apt install libjemalloc2 - -# This makes interactive docker runs painless: -ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" -ENV AFL_MAP_SIZE=2621440 -ENV PATH="$PATH:/out" -ENV AFL_SKIP_CPUFREQ=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 -ENV AFL_TESTCACHE_SIZE=2 From 22039bf3908d0d946ef49ff3ce39599c74d5fa1e Mon Sep 17 00:00:00 2001 From: Dan Blackwell Date: Wed, 31 Jul 2024 17:47:32 +0100 Subject: [PATCH 25/25] Fix issue whereby basic block UUIDs were not unique --- fuzzers/prescientfuzz/builder.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuzzers/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz/builder.Dockerfile index 4470a39c8..1dd37a126 100644 --- a/fuzzers/prescientfuzz/builder.Dockerfile +++ b/fuzzers/prescientfuzz/builder.Dockerfile @@ -33,7 +33,7 @@ RUN apt-get update && \ # Download PrescientFuzz RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz -RUN cd /PrescientFuzz && git fetch && git checkout b8f55284dafc0d63108d1cc31a0b476a347cf205 +RUN cd /PrescientFuzz && git fetch && git checkout 9014fe72a16af3b7298e9c2f80512f21f479223a # Compile PrescientFuzz. RUN cd /PrescientFuzz && \