From 5ef24b12b375388c9dc3a2c81ee5802169cd9b4c Mon Sep 17 00:00:00 2001 From: Yu3h0 Date: Fri, 13 Dec 2024 23:58:08 +0800 Subject: [PATCH 1/8] init --- fuzzers/hfuzz/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 fuzzers/hfuzz/.gitkeep diff --git a/fuzzers/hfuzz/.gitkeep b/fuzzers/hfuzz/.gitkeep new file mode 100644 index 000000000..e69de29bb From a8cd44cc0b3ee0d10add13cb668a065956062bdf Mon Sep 17 00:00:00 2001 From: Yu3h0 Date: Tue, 7 Jan 2025 16:03:49 +0800 Subject: [PATCH 2/8] commit hfuzz --- fuzzers/hfuzz/builder.Dockerfile | 132 ++++++ fuzzers/hfuzz/ensemble_runner.py | 727 +++++++++++++++++++++++++++++++ fuzzers/hfuzz/fuzzer.py | 724 ++++++++++++++++++++++++++++++ fuzzers/hfuzz/runner.Dockerfile | 24 + 4 files changed, 1607 insertions(+) create mode 100644 fuzzers/hfuzz/builder.Dockerfile create mode 100644 fuzzers/hfuzz/ensemble_runner.py create mode 100644 fuzzers/hfuzz/fuzzer.py create mode 100644 fuzzers/hfuzz/runner.Dockerfile diff --git a/fuzzers/hfuzz/builder.Dockerfile b/fuzzers/hfuzz/builder.Dockerfile new file mode 100644 index 000000000..1334ac158 --- /dev/null +++ b/fuzzers/hfuzz/builder.Dockerfile @@ -0,0 +1,132 @@ +# 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 + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + python3-dev \ + python3-setuptools \ + automake \ + cmake \ + git \ + flex \ + bison \ + libglib2.0-dev \ + libpixman-1-dev \ + cargo \ + libgtk-3-dev \ + # for QEMU mode + ninja-build \ + gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev \ + libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev + +RUN git clone https://github.com/Yu3H0/HFuzz.git /hfuzz1 +RUN git -C /hfuzz1 checkout hfuzz1 + +RUN git clone https://github.com/Yu3H0/HFuzz.git /hfuzz2 +RUN git -C /hfuzz2 checkout hfuzz2 + +RUN git clone https://github.com/Yu3H0/HFuzz.git /hfuzz3 +RUN git -C /hfuzz3 checkout hfuzz3 + +# Download afl++. +RUN git clone -b dev https://github.com/AFLplusplus/AFLplusplus /afl_vanilla && \ + cd /afl_vanilla && \ + git checkout tags/v4.30c || \ + true + +# 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 libc6-dev joe curl + +# Build without Python support as we don't need it. +# Set AFL_NO_X86 to skip flaky tests. +RUN cd /afl_vanilla && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang-15 AFL_NO_X86=1 && \ + PYTHON_INCLUDE=/ make && \ + cp utils/aflpp_driver/libAFLDriver.a / + +RUN cd /hfuzz1 && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang-15 AFL_NO_X86=1 && \ + PYTHON_INCLUDE=/ make && \ + cp utils/aflpp_driver/libAFLDriver.a / + +RUN cd /hfuzz2 && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang-15 AFL_NO_X86=1 && \ + PYTHON_INCLUDE=/ make && \ + cp utils/aflpp_driver/libAFLDriver.a / + +# The hfuzz3 fuzzer +COPY ./ensemble_runner.py /hfuzz2/ensemble_runner.py +# COPY ./hfuzz3 /hfuzz3 +RUN cd /hfuzz3 && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang-15 AFL_NO_X86=1 && \ + PYTHON_INCLUDE=/ CFLAGS="-DAFL_CFG_PATH=\\\"/out/hfuzz3/hfuzz3_sancov_cfg\\\"" CXXFLAGS="-DAFL_CFG_PATH=\\\"/out/hfuzz3/hfuzz3_sancov_cfg\\\"" make source-only && \ + cp utils/aflpp_driver/libAFLDriver.a / + + +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-08-12 -y && \ + rm /rustup.sh + + +RUN wget https://gist.githubusercontent.com/tokatoka/26f4ba95991c6e33139999976332aa8e/raw/698ac2087d58ce5c7a6ad59adce58dbfdc32bd46/createAliases.sh && \ + chmod u+x ./createAliases.sh && ./createAliases.sh +# RUN rustup component add rustfmt clippy + +# Download libafl. +RUN git clone https://github.com/AFLplusplus/LibAFL /libafl + +# Checkout a current commit +RUN cd /libafl && git pull && git checkout f856092f3d393056b010fcae3b086769377cba18 || 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/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /libafl/fuzzers/fuzzbench/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o + + +# RUN cargo install cargo-make +# build afl-cc, afl-cxx compilers + +# RUN cd $SRC && ls ./build.sh +# RUN cd $SRC && CC=/libafl/fuzzers/fuzzbench/fuzzbench/target/release-fuzzbench/libafl_cc \ +# CXX=/libafl/fuzzers/fuzzbench/fuzzbench/target/release-fuzzbench/libafl_cxx \ +# CFLAGS= CXXFLAGS= FUZZER_LIB="/stub_rt.a /libafl/fuzzers/fuzzbench/fuzzbench/target/release-fuzzbench/libfuzzbench.a" \ +# ./build.sh +# RUN mv $OUT/cms_transform_fuzzer $OUT/libafl_target_bin +# RUN $OUT/libafl_target_bin --help + diff --git a/fuzzers/hfuzz/ensemble_runner.py b/fuzzers/hfuzz/ensemble_runner.py new file mode 100644 index 000000000..1c9211c3c --- /dev/null +++ b/fuzzers/hfuzz/ensemble_runner.py @@ -0,0 +1,727 @@ +""" +Description: Ensemble runner for Cmplog, HFUZZ1, and HFuzz2 fuzzer modes. + +Usage: + python3 ensemble_runner.py -i [corpus_dir] -o [output_dir] -b [target_binary] -x [dicts] + --hfuzz1_target_binary [hfuzz1_target_binary] + --cmplog_target_binary [cmplog_target_binary] + --hfuzz2_target_binary [hfuzz2_target_binary] + +Note: + - Input and output directories are managed per fuzzer instance. + - Before each fuzzer runs, a new output directory is created. + - The input for each subsequent fuzzer is the 'queue' directory from the previous fuzzer's output. + - The 'queue' directory is searched within the fuzzer's output directory. + - The environment variable 'AFL_AUTORESUME' is not set. + +Alternatively, you can directly import the EnsembleFuzzer class and use it as follows: + EnsembleFuzzer(corpus_dir, output_dir, dicts, + target_binary, + cmplog_target_binary, + hfuzz1_target_binary, + hfuzz2_target_binary).run() + +Required fuzzer binaries in the current directory (names/paths modifiable in the script, see CMPLOG_FUZZ_BIN_NAME, HFUZZ1_FUZZ_BIN_NAME, and HFUZZ2_FUZZ_BIN_NAME): + - hfuzz1_4.30c_hybrid_start + - cmplog_4.30c_hybrid_start + - hfuzz2_4.30c_hybrid_start + +Environment variables touched: + - None +""" + +import argparse +import json +import logging +import os +import shutil +import subprocess +import time + +from collections import deque +from typing import List, Deque + +# Fuzzer-command specific constants +INT_MAX = '2147483647' +COMMON_ARGS = ['-m', 'none', '-d', '-t', '1000+'] +CMPLOG_FUZZ_BIN_NAME = "./cmplog_4.30c_hybrid_start" +HFUZZ3_FUZZ_BIN_NAME = "./hfuzz3_4.30c_hybrid_start" +HFUZZ1_FUZZ_BIN_NAME = "./hfuzz1_4.30c_hybrid_start" +HFUZZ2_FUZZ_BIN_NAME = "./hfuzz2_4.30c_hybrid_start" + +# Timeout strategies (in seconds) +TMOUT_CMPLOG = 60 * 60 # 90 minutes +TIMEOUT_HFUZZ3 = 60 * 60 +TMOUT_HFUZZ1 = 8 * 60 * 60 # 120 minutes +TMOUT_HFUZZ2 = 60 * 60 # 120 minutes +TIMEOUT_LIBAFL = 60 * 60 # 1 minute + + +def time_s(): + """Get the current time in seconds.""" + return int(time.time()) + + +def run_command(command: List[str]): + """Run a checked command.""" + subprocess.run(command, check=True) + + +class AbstractFuzzer: + """Abstract class for a fuzzer.""" + name: str + run_cnt: int + corpus_dir: str + output_dir: str + command: List[str] + dicts: List[str] + target_binary: str + args: List[str] + + def run(self): + raise NotImplementedError() + + def build_command(self): + raise NotImplementedError() + + def get_timeout(self): + raise NotImplementedError() + + + +# class LibAFLFuzzer(AbstractFuzzer): +# """ lib afl fuzzer """ +# timeout: bool; +# run_err: Exception +# time_start: int +# time_end: int +# libafl_target_binary: str + +# def __init__( +# self, +# name, +# corpus_dir, +# output_dir, +# dicts: List[str], +# target_binary: str, +# args: List[str] +# ): +# self.name = name +# self.corpus_dir = corpus_dir +# self.output_dir = output_dir +# self.dicts = dicts +# self.args = args +# self.run_cnt = 0 +# self.command = None +# self.timeout = False +# self.run_err = None +# self.libafl_target_binary = target_binary + +# def add_common_args(self): +# """Add the common arguments to the command.""" +# self.command += ["-t", "1000"] +# self.command += [ +# '--input', self.corpus_dir, +# '--output', self.output_dir, +# ] + +# def build_command(self): +# self.command = [self.libafl_target_binary] +# self.add_common_args() + +# def do_run(self): +# """ +# Run the fuzzer with the specified command. +# If self.timeout is True, enforce timeout using subprocess. +# Handle exceptions appropriately. +# """ +# try: +# if self.timeout: +# subprocess.run(self.command, check=True, timeout=self.get_timeout()) +# else: +# subprocess.run(self.command, check=True) +# self.run_err = None +# except subprocess.TimeoutExpired: +# logging.info(f"Fuzzer {self.name} timed out after {self.get_timeout()} seconds") +# # Timeout is not considered an error; fuzzer can be re-queued +# self.run_err = None +# except subprocess.CalledProcessError as e: +# logging.error(f"Unexpected error while running the fuzzer") +# logging.exception(e) +# self.run_err = e + +# def do_run_timed(self): +# """Run the fuzzer, timing the execution, and save any error if it fails.""" +# self.time_start = time_s() +# self.do_run() +# self.time_end = time_s() + +# def get_timeout(self): +# return TIMEOUT_LIBAFL; + +# def run(self): +# """Build the command, run the fuzzer, and log the result.""" +# self.build_command() +# self.do_run_timed() +# logging.info(self.run_info()) +# self.run_cnt += 1 + +# def run_info(self): +# """Get the run info as a JSON string.""" +# return json.dumps({ +# 'name': self.name, +# 'run_cnt': self.run_cnt, +# 'time_start': self.time_start, +# 'time_end': self.time_end, +# 'command': self.command, +# 'run_err': str(self.run_err) +# }) + + +class AFLFuzzer(AbstractFuzzer): + """Base class for an AFL fuzzer.""" + timeout: bool + run_err: Exception + time_start: int + time_end: int + + def __init__( + self, + name: str, + corpus_dir: str, + output_dir: str, + dicts: List[str], + target_binary: str, + args: List[str] + ): + self.name = name + self.corpus_dir = corpus_dir + self.output_dir = output_dir + self.dicts = dicts + self.target_binary = target_binary + self.args = args + self.run_cnt = 0 + self.command = None + self.timeout = False + self.run_err = None + + def add_common_args(self): + """Add the common arguments to the command.""" + self.command += COMMON_ARGS + for dict_path in self.dicts: + self.command += ['-x', dict_path] + self.command += [ + '-i', self.corpus_dir, + '-o', self.output_dir, + '--', + self.target_binary + ] + self.args + [INT_MAX] + + def do_run(self): + """ + Run the fuzzer with the specified command. + If self.timeout is True, enforce timeout using subprocess. + Handle exceptions appropriately. + """ + try: + if self.timeout: + subprocess.run(self.command, check=True, timeout=self.get_timeout()) + else: + subprocess.run(self.command, check=True) + self.run_err = None + except subprocess.TimeoutExpired: + logging.info(f"Fuzzer {self.name} timed out after {self.get_timeout()} seconds") + # Timeout is not considered an error; fuzzer can be re-queued + self.run_err = None + except subprocess.CalledProcessError as e: + logging.error(f"Unexpected error while running the fuzzer") + logging.exception(e) + self.run_err = e + + def do_run_timed(self): + """Run the fuzzer, timing the execution, and save any error if it fails.""" + self.time_start = time_s() + self.do_run() + self.time_end = time_s() + + def run(self): + """Build the command, run the fuzzer, and log the result.""" + self.build_command() + self.do_run_timed() + logging.info(self.run_info()) + self.run_cnt += 1 + + def run_info(self): + """Get the run info as a JSON string.""" + return json.dumps({ + 'name': self.name, + 'run_cnt': self.run_cnt, + 'time_start': self.time_start, + 'time_end': self.time_end, + 'command': self.command, + 'run_err': str(self.run_err) + }) + +class LibAFLFuzzer(AFLFuzzer): + """ lib afl fuzzer """ + timeout: bool; + run_err: Exception + time_start: int + time_end: int + libafl_target_binary: str + + def __init__( + self, + corpus_dir, + output_dir, + dicts: List[str], + target_binary: str, + libafl_target_binary: str, + args: List[str] + ): + self.libafl_target_binary = libafl_target_binary + super().__init__("libafl", corpus_dir, output_dir, dicts, target_binary, args) + + def add_common_args(self): + """Add the common arguments to the command.""" + self.command += ["-t", "1000"] + self.command += [ + '--input', self.corpus_dir, + '--output', self.output_dir, + ] + + def build_command(self): + self.command = [self.libafl_target_binary] + self.add_common_args() + + + def get_timeout(self): + """Get the timeout value for the LibAFL fuzzer (in seconds).""" + return TIMEOUT_LIBAFL + def do_run(self): + """ + Override to set LD_PRELOAD for LibAFL-specific runs. + """ + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + try: + if self.timeout: + subprocess.run(self.command, check=True, timeout=self.get_timeout(), env=fuzzer_env) + else: + subprocess.run(self.command, check=True, env=fuzzer_env) + self.run_err = None + except subprocess.TimeoutExpired: + logging.info(f"Fuzzer {self.name} timed out after {self.get_timeout()} seconds") + self.run_err = None + except subprocess.CalledProcessError as e: + logging.error(f"Unexpected error while running the fuzzer") + logging.exception(e) + self.run_err = e + + +class HFuzz3Fuzzer(AFLFuzzer): + hfuzz3_target_binary: str + + """ + Example usage: + ./hfuzz3_fuzzer -H -c /out/hfuzz3_cms_transform_fuzzer -m none -d -t 1000+ \\ + -x /out/keyval.dict -x /out/cms_transform_fuzzer.dict \\ + -i /out/corpus/ensemble_fuzzer/hfuzz3_input_0 \\ + -o '/out/corpus/ensemble_fuzzer/hfuzz3_run_0' \\ + -- /out/cms_transform_fuzzer 2147483648 + """ + + def __init__( + self, + corpus_dir: str, + output_dir: str, + dicts: List[str], + target_binary: str, + hfuzz3_target_binary: str, + args: List[str] + ): + self.hfuzz3_target_binary = hfuzz3_target_binary + super().__init__("hfuzz3", corpus_dir, output_dir, dicts, target_binary, args) + + def build_command(self): + """ + Build the command for running the Cmplog fuzzer. + The '-c' option specifies the cmplog-instrumented binary. + """ + out_dir = os.getenv("OUT") + fuzz_target = os.getenv("FUZZ_TARGET") + self.command = [ + HFUZZ3_FUZZ_BIN_NAME, + "-H", "-c", + self.hfuzz3_target_binary + ] + self.add_common_args() + + def get_timeout(self): + """Get the timeout value for the Cmplog fuzzer (in seconds).""" + return TIMEOUT_HFUZZ3 + +class CmplogFuzzer(AFLFuzzer): + """Fuzzer class for the Cmplog mode.""" + cmplog_target_binary: str + + def __init__( + self, + corpus_dir: str, + output_dir: str, + dicts: List[str], + target_binary: str, + cmplog_target_binary: str, + args: List[str] + ): + self.cmplog_target_binary = cmplog_target_binary + super().__init__("cmplog", corpus_dir, output_dir, dicts, target_binary, args) + + def build_command(self): + """ + Build the command for running the Cmplog fuzzer. + The '-c' option specifies the cmplog-instrumented binary. + """ + self.command = [ + CMPLOG_FUZZ_BIN_NAME, + '-c', + self.cmplog_target_binary + ] + self.add_common_args() + + def get_timeout(self): + """Get the timeout value for the Cmplog fuzzer (in seconds).""" + return TMOUT_CMPLOG + + +class HFuzz1Fuzzer(AFLFuzzer): + """Fuzzer class for the HFUZZ1 mode.""" + + def __init__( + self, + corpus_dir: str, + output_dir: str, + dicts: List[str], + target_binary: str, + args: List[str] + ): + super().__init__("hfuzz1", corpus_dir, output_dir, dicts, target_binary, args) + + def build_command(self): + """Build the command for running the HFUZZ1 fuzzer.""" + self.command = [ + HFUZZ1_FUZZ_BIN_NAME, + '-k', + '-p', + 'wd_scheduler' + ] + self.add_common_args() + + def get_timeout(self): + """Get the timeout value for the HFUZZ1 fuzzer (in seconds).""" + return TMOUT_HFUZZ1 + + +class HFuzz2Fuzzer(AFLFuzzer): + """Fuzzer class for the HFuzz2 mode.""" + cmplog_target_binary: str + + def __init__( + self, + corpus_dir: str, + output_dir: str, + dicts: List[str], + target_binary: str, + cmplog_target_binary: str, + args: List[str] + ): + """ + 如果传入了 cmplog_target_binary,则在构造命令时加上 -c cmplog_target_binary。 + target_binary 为 HFuzz2 编译出的可执行文件。 + """ + self.cmplog_target_binary = cmplog_target_binary + super().__init__("hfuzz2", corpus_dir, output_dir, dicts, target_binary, args) + + def build_command(self): + """Build the command for running the HFuzz2 fuzzer.""" + if self.cmplog_target_binary: + # 如果有 cmplog_target_binary,则像 cmplog 一样加上 -c 参数 + self.command = [ + HFUZZ2_FUZZ_BIN_NAME, + '-c', + self.cmplog_target_binary + ] + else: + # 否则普通运行 + self.command = [HFUZZ2_FUZZ_BIN_NAME] + self.add_common_args() + + def get_timeout(self): + """Get the timeout value for the HFuzz2 fuzzer (in seconds).""" + return TMOUT_HFUZZ2 + + +class EnsembleFuzzer: + """ + EnsembleFuzzer orchestrates multiple fuzzers, running them in a coordinated manner. + Before each fuzzer runs, a new output directory is created, and the input directory is set up by copying + the previous fuzzer's queue into it. + The 'queue' directory is searched within the previous fuzzer's output directory. + The environment variable 'AFL_AUTORESUME' is not set, so each fuzzer starts fresh with the provided inputs. + """ + output_dir: str + fuzzer_queue: Deque[AFLFuzzer] + initial_corpus_dir: str + args: List[str] + dicts: List[str] + + def __init__( + self, + corpus_dir: str, + output_dir: str, + dicts: List[str], + target_binary: str, + cmplog_target_binary: str, + hfuzz1_target_binary: str, + hfuzz2_target_binary: str, + libafl_target_binary: str, + hfuzz3_target_binary: str, + args: List[str] + ): + self.output_dir = os.path.join(output_dir, "ensemble_fuzzer") + self.initial_corpus_dir = corpus_dir # Store initial corpus directory + self.dicts = dicts # Store dictionaries + self.args = args # Store target binary arguments + self.fuzzer_queue = deque() + + if hfuzz1_target_binary: + self.fuzzer_queue.append( + HFuzz1Fuzzer( + corpus_dir=None, + output_dir=None, + dicts=self.dicts, + target_binary=hfuzz1_target_binary, + args=self.args + ) + ) + if hfuzz2_target_binary: + self.fuzzer_queue.append( + HFuzz2Fuzzer( + corpus_dir=None, + output_dir=None, + dicts=self.dicts, + target_binary=hfuzz2_target_binary, + cmplog_target_binary=cmplog_target_binary, + args=self.args + ) + ) + if cmplog_target_binary: + self.fuzzer_queue.append( + CmplogFuzzer( + corpus_dir=None, + output_dir=None, + dicts=self.dicts, + target_binary=target_binary, + cmplog_target_binary=cmplog_target_binary, + args=self.args + ) + ) + if libafl_target_binary: + self.fuzzer_queue.append( + LibAFLFuzzer( + corpus_dir=None, + output_dir=None, + dicts=self.dicts, + target_binary=target_binary, + libafl_target_binary=libafl_target_binary, + args=self.args + ) + ) + + if hfuzz3_target_binary: + self.fuzzer_queue.append( + HFuzz3Fuzzer( + corpus_dir=None, + output_dir=None, + dicts=self.dicts, + target_binary=target_binary, + hfuzz3_target_binary=hfuzz3_target_binary, + args=self.args + ) + ) + + def find_queue_directory(self, output_dir): + """ + Search the output directory recursively for a 'queue' directory. + Return the path to the 'queue' directory if found, else None. + """ + for root, dirs, files in os.walk(output_dir): + if 'queue' in dirs: + return os.path.join(root, 'queue') + return None + + def copy_queue_to_input(self, queue_dir, input_dir): + """ + Copy the contents of the queue directory to the new input directory. + """ + if not os.path.exists(queue_dir): + logging.warning(f"Queue directory {queue_dir} does not exist.") + return + for filename in os.listdir(queue_dir): + src_path = os.path.join(queue_dir, filename) + dst_path = os.path.join(input_dir, filename) + if os.path.isfile(src_path): + shutil.copy2(src_path, dst_path) + + def merge_queue_directories(self, src_queue_dir, dst_queue_dir): + """ + Merge contents from src queue directory into dst queue directory. + """ + if not os.path.exists(src_queue_dir) or not os.path.exists(dst_queue_dir): + logging.warning(f"Cannot merge queues - source or destination directory does not exist") + return + + # Copy all files from src to dst, skipping if file already exists + for filename in os.listdir(src_queue_dir): + src_path = os.path.join(src_queue_dir, filename) + dst_path = os.path.join(dst_queue_dir, filename) + if os.path.isfile(src_path) and not os.path.exists(dst_path): + shutil.copy2(src_path, dst_path) + + def run(self): + """ + Run the ensemble of fuzzers. + Each fuzzer runs in a round-robin fashion. + Each fuzzer uses the output from the previously successful run. + If a fuzzer errors, its queue is merged back into the last successful queue. + """ + os.makedirs(self.output_dir, exist_ok=True) + prev_output_dir = None # Keep track of previous successful fuzzer's output directory + last_successful_output_dir = None # Keep track of the last successful run + + while len(self.fuzzer_queue): + fuzzer = self.fuzzer_queue.popleft() + + # Create unique output directory for this fuzzer run + fuzzer_output_dir = os.path.join( + self.output_dir, + f"{fuzzer.name}_run_{fuzzer.run_cnt}" + ) + os.makedirs(fuzzer_output_dir, exist_ok=True) + + # Set up the input directory + # For all runs, use prev_output_dir if available, otherwise use initial corpus + if prev_output_dir is None: + fuzzer_input_dir = self.initial_corpus_dir + else: + queue_dir = self.find_queue_directory(prev_output_dir) + if queue_dir is None: + logging.warning(f"No queue directory found in {prev_output_dir}. Using initial corpus.") + fuzzer_input_dir = self.initial_corpus_dir + else: + fuzzer_input_dir = queue_dir + + # Prepare the input directory by copying files + fuzzer_input_dir_prepared = os.path.join( + self.output_dir, + f"{fuzzer.name}_input_{fuzzer.run_cnt}" + ) + os.makedirs(fuzzer_input_dir_prepared, exist_ok=True) + self.copy_queue_to_input(fuzzer_input_dir, fuzzer_input_dir_prepared) + + # Update fuzzer's input and output directories + fuzzer.corpus_dir = fuzzer_input_dir_prepared + fuzzer.output_dir = fuzzer_output_dir + + # Decide on timeout + fuzzer.timeout = len(self.fuzzer_queue) > 0 + + # Run the fuzzer + fuzzer.run() + + if isinstance(fuzzer.run_err, Exception): + # If an error occurred: + # 1. Try to merge any findings back into the last successful queue + # 2. Do not update prev_output_dir + # 3. Do not re-queue the fuzzer + logging.error(f"Fuzzer {fuzzer.name} encountered an error and will not be re-queued.") + + if last_successful_output_dir: + current_queue = self.find_queue_directory(fuzzer_output_dir) + last_successful_queue = self.find_queue_directory(last_successful_output_dir) + + if current_queue and last_successful_queue: + logging.info(f"Merging findings from failed run into last successful queue") + self.merge_queue_directories(current_queue, last_successful_queue) + + # Restore prev_output_dir to last successful directory + prev_output_dir = last_successful_output_dir + else: + # Successful run + # Update both prev_output_dir and last_successful_output_dir + prev_output_dir = fuzzer_output_dir + last_successful_output_dir = fuzzer_output_dir + + # Re-queue the fuzzer to run again + self.fuzzer_queue.append(fuzzer) + + logging.info("Fuzzing completed: all fuzzers have been processed.") + +def parse_args(): + """Parse command-line arguments.""" + parser = argparse.ArgumentParser() + parser.add_argument("-i", "--corpus_dir", type=str, required=True, + help="Directory containing the corpus") + parser.add_argument("-o", "--output_dir", type=str, required=True, + help="Directory to store output") + parser.add_argument("-b", "--target_binary", type=str, required=True, + help="Path to the vanilla AFLplusplus-instrumented target binary") + parser.add_argument("-a", "--args", type=str, nargs="*", default=[], + help="Arguments to pass to the target binary") + parser.add_argument("-x", "--dicts", type=str, nargs="+", default=None, + help="Path to the dictionaries; if not provided, will use all .dict files in the current directory") + parser.add_argument("--hfuzz1_target_binary", type=str, required=False, + help="Path to the HFuzz1-instrumented target binary (optional)") + parser.add_argument("--cmplog_target_binary", type=str, required=False, + help="Path to the cmplog-instrumented target binary (optional)") + parser.add_argument("--hfuzz2_target_binary", type=str, required=False, + help="Path to the HFuzz2-instrumented target binary (optional)") + parser.add_argument("--libafl_target_binary", type=str, required=False, + help="Path to the LibAFL-instrumented target binary (optional)") + parser.add_argument("--hfuzz3_target_binary", type=str, required=False, + help="Path to the HFuzz3-instrumented target binary (optional)") + return parser.parse_args() + + +def main(args): + """Main function to run the ensemble fuzzer.""" + os.makedirs(args.output_dir, exist_ok=True) + logging.basicConfig( + filename=os.path.join(args.output_dir, "ensemble_runner.log"), + level=logging.DEBUG + ) + + if args.dicts is None: + args.dicts = [os.path.abspath(f) for f in os.listdir('.') if f.endswith('.dict')] + if not args.dicts: + logging.warning("No dictionaries found; proceeding without any dictionaries.") + else: + args.dicts = [os.path.abspath(dict_path) for dict_path in args.dicts] + + fuzzer = EnsembleFuzzer( + corpus_dir=args.corpus_dir, + output_dir=args.output_dir, + dicts=args.dicts, + target_binary=args.target_binary, + cmplog_target_binary=args.cmplog_target_binary, + hfuzz1_target_binary=args.hfuzz1_target_binary, + hfuzz2_target_binary=args.hfuzz2_target_binary, + libafl_target_binary=args.libafl_target_binary, + hfuzz3_target_binary=args.hfuzz3_target_binary, + args=args.args + ) + fuzzer.run() + + +if __name__ == "__main__": + main(parse_args()) diff --git a/fuzzers/hfuzz/fuzzer.py b/fuzzers/hfuzz/fuzzer.py new file mode 100644 index 000000000..c956543e9 --- /dev/null +++ b/fuzzers/hfuzz/fuzzer.py @@ -0,0 +1,724 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# ... + +import os +import shutil +import subprocess +import sys + +from fuzzers import utils + +def is_benchmark(name): + """Check if the benchmark contains the string |name|.""" + benchmark = os.getenv("BENCHMARK", None) + return benchmark is not None and name in benchmark + + +def install(package): + """Install a Python package with pip.""" + subprocess.check_call([sys.executable, "-m", "pip", "install", package]) + + +def install_all(): + """Install all required Python dependencies.""" + packages = [ + "asttokens==2.2.1", "backcall==0.2.0", "decorator==5.1.1", + "executing==1.2.0", "greenstalk==2.0.2", "ipdb==0.13.13", + "ipython==8.12.2", "jedi==0.18.2", "networkit==10.1", "numpy==1.24.4", + "parso==0.8.3", "pexpect==4.8.0", "pickleshare==0.7.5", + "prompt-toolkit==3.0.39", "psutil==5.9.5", "ptyprocess==0.7.0", + "pure-eval==0.2.2", "Pygments==2.15.1", "PyYAML==5.3.1", + "scipy==1.10.1", "six==1.16.0", "stack-data==0.6.2", "tabulate==0.9.0", + "tomli==2.0.1", "traitlets==5.9.0", "typing-extensions==4.7.1", + "wcwidth==0.2.6", + # 额外需求 + "pyelftools==0.30" + ] + for p in packages: + install(p) + + +def prepare_build_environment(): + if is_benchmark("mbedtls"): + file_path = os.path.join(os.getenv("SRC"), "mbedtls", "library", "CMakeLists.txt") + if os.path.isfile(file_path): + subst_cmd = r"sed -i 's/\(-Wdocumentation\)//g' " + file_path + subprocess.check_call(subst_cmd, shell=True) + + if is_benchmark("openthread"): + mbed_cmake_one = os.path.join( + os.getenv("SRC"), + "openthread", "third_party", "mbedtls", "repo", + "library", "CMakeLists.txt") + mbed_cmake_two = os.path.join( + os.getenv("SRC"), + "openthread", "third_party", "mbedtls", "repo", + "CMakeLists.txt") + if os.path.isfile(mbed_cmake_one): + subst_cmd = r"sed -i 's/\(-Wdocumentation\)//g' " + mbed_cmake_one + subprocess.check_call(subst_cmd, shell=True) + if os.path.isfile(mbed_cmake_two): + subst_cmd = r"sed -i 's/\(-Werror\)//g' " + mbed_cmake_two + subprocess.check_call(subst_cmd, shell=True) + + +def get_hfuzz1_build_directory(target_directory): + return os.path.join(target_directory, "hfuzz1") + + +def get_hfuzz2_build_directory(target_directory): + """Return path to hfuzz2 build directory.""" + return os.path.join(target_directory, "hfuzz2") + + +def get_vanilla_build_directory(target_directory): + """Return path to vanilla build directory.""" + return os.path.join(target_directory, "vanilla") + + +def get_cmplog_build_directory(target_directory): + """Return path to cmplog build directory.""" + return os.path.join(target_directory, "cmplog") + +def get_hfuzz3_build_directory(target_directory): + return os.path.join(target_directory, "hfuzz3"); + +def get_libafl_build_directory(target_directory): + """Return path to libafl build directory.""" + return os.path.join(target_directory, "libafl") + +def build_hfuzz1_binary(): + print("[build_hfuzz1_binary] Building hfuzz1 instrumentation.") + is_build_failed = False + + subprocess.check_call(["rm", "-f", "/dev/shm/*"]) + + src = os.getenv("SRC") + work = os.getenv("WORK") + fuzz_target = os.getenv("FUZZ_TARGET") + out_dir = os.getenv("OUT") + pwd = os.getcwd() + + old_cc = os.environ.get("CC") + old_cxx = os.environ.get("CXX") + old_lib = os.environ.get("FUZZER_LIB") + + os.environ["CC"] = "/hfuzz1/afl-clang-fast" + os.environ["CXX"] = "/hfuzz1/afl-clang-fast++" + os.environ["FUZZER_LIB"] = "/hfuzz1/libAFLDriver.a" + + os.environ["AFL_LLVM_DICT2FILE"] = os.path.join(out_dir, "keyval.dict") + os.environ["AFL_LLVM_DICT2FILE_NO_MAIN"] = "1" + + hfuzz1_dir = get_hfuzz1_build_directory(out_dir) + if not os.path.exists(hfuzz1_dir): + os.mkdir(hfuzz1_dir) + + with utils.restore_directory(src), utils.restore_directory(work): + new_env = os.environ.copy() + new_env["OUT"] = hfuzz1_dir + if fuzz_target: + new_env["FUZZ_TARGET"] = os.path.join(hfuzz1_dir, os.path.basename(fuzz_target)) + + try: + utils.build_benchmark(env=new_env) + + # 拷贝中间件信息 + for f in ["br_src_map", "strcmp_err_log", "instrument_meta_data"]: + tmp_path = os.path.join("/dev/shm", f) + if os.path.exists(tmp_path): + shutil.copy(tmp_path, os.path.join(hfuzz1_dir, f)) + + HFUZZ1_FILES = [ + "br_node_id_2_cmp_type", + "border_edges", + "max_border_edge_id", + "max_br_dist_edge_id", + "border_edges_cache" + ] + for f in HFUZZ1_FILES: + hfuzz1_file_path = os.path.join("/dev/shm", f) + if os.path.exists(hfuzz1_file_path): + shutil.copy(hfuzz1_file_path, os.path.join(hfuzz1_dir, f)) + + # 切换到 hfuzz1_dir 调用 gen_graph_no_gllvm_15.py + graph_script = "/hfuzz1/gen_graph_no_gllvm_15.py" + old_dir = os.getcwd() + try: + os.chdir(hfuzz1_dir) + final_fuzz_bin = new_env["FUZZ_TARGET"] + subprocess.check_call([ + "python3", graph_script, final_fuzz_bin, "instrument_meta_data" + ]) + finally: + os.chdir(old_dir) + + except subprocess.CalledProcessError: + print("[build_hfuzz1_binary] Failed, skip.") + is_build_failed = True + finally: + os.chdir(pwd) + if old_cc is not None: + os.environ["CC"] = old_cc + if old_cxx is not None: + os.environ["CXX"] = old_cxx + if old_lib is not None: + os.environ["FUZZER_LIB"] = old_lib + + # 如果编译成功,把 hfuzz1_dir 下的 fuzz_target 拷贝回 out_dir + if (not is_build_failed) and fuzz_target: + built_bin = os.path.join(hfuzz1_dir, os.path.basename(fuzz_target)) + if os.path.exists(built_bin): + shutil.copy(built_bin, os.path.join(out_dir, "hfuzz1_" + os.path.basename(fuzz_target))) + + # 同时也把 HFUZZ1_FILES 复制到 /out (如果它们在 hfuzz1_dir 里) + HFUZZ1_FILES = [ + "br_node_id_2_cmp_type", + "border_edges", + "max_border_edge_id", + "max_br_dist_edge_id", + "border_edges_cache" + ] + for f in HFUZZ1_FILES: + in_build_dir = os.path.join(hfuzz1_dir, f) + if os.path.exists(in_build_dir): + shutil.copy(in_build_dir, os.path.join(out_dir, f)) + + return (not is_build_failed) + + +def build_hfuzz2_binary(): + """ + Build HFuzz2-instrumented binary: + 1) 清理 /dev/shm/* + 2) 切换 CC/CXX/FUZZER_LIB => /hfuzz2 + 3) 创建 hfuzz2 目录 + 4) 调用 build_benchmark + 5) 执行 gen_graph_no_gllvm_15.py (切换到 hfuzz2_dir) + 6) 若成功,把产物复制回 /out + 7) 把 HFuzz2 生成的 hfuzz2_br_node_id_2_cmp_type 等文件也复制到 /out + """ + print("[build_hfuzz2_binary] Building HFuzz2 instrumentation.") + is_build_failed = False + + subprocess.check_call(["rm", "-f", "/dev/shm/*"]) + + src = os.getenv("SRC") + work = os.getenv("WORK") + fuzz_target = os.getenv("FUZZ_TARGET") + out_dir = os.getenv("OUT") + pwd = os.getcwd() + + old_cc = os.environ.get("CC") + old_cxx = os.environ.get("CXX") + old_lib = os.environ.get("FUZZER_LIB") + + os.environ["CC"] = "/hfuzz2/afl-clang-fast" + os.environ["CXX"] = "/hfuzz2/afl-clang-fast++" + os.environ["FUZZER_LIB"] = "/hfuzz2/libAFLDriver.a" + + os.environ["AFL_LLVM_DICT2FILE"] = os.path.join(out_dir, "keyval.dict") + os.environ["AFL_LLVM_DICT2FILE_NO_MAIN"] = "1" + + hfuzz2_dir = get_hfuzz2_build_directory(out_dir) + if not os.path.exists(hfuzz2_dir): + os.mkdir(hfuzz2_dir) + + with utils.restore_directory(src), utils.restore_directory(work): + new_env = os.environ.copy() + new_env["OUT"] = hfuzz2_dir + if fuzz_target: + new_env["FUZZ_TARGET"] = os.path.join(hfuzz2_dir, os.path.basename(fuzz_target)) + + try: + utils.build_benchmark(env=new_env) + + for f in ["br_src_map", "strcmp_err_log", "instrument_meta_data"]: + tmp_path = os.path.join("/dev/shm", f) + if os.path.exists(tmp_path): + shutil.copy(tmp_path, os.path.join(hfuzz2_dir, f)) + + graph_script = "/hfuzz2/gen_graph_no_gllvm_15.py" + old_dir = os.getcwd() + try: + os.chdir(hfuzz2_dir) + final_fuzz_bin = new_env["FUZZ_TARGET"] + subprocess.check_call(["python3", graph_script, + final_fuzz_bin, "instrument_meta_data"]) + finally: + os.chdir(old_dir) + + except subprocess.CalledProcessError: + print("[build_hfuzz2_binary] Failed, skip.") + is_build_failed = True + finally: + os.chdir(pwd) + if old_cc is not None: + os.environ["CC"] = old_cc + if old_cxx is not None: + os.environ["CXX"] = old_cxx + if old_lib is not None: + os.environ["FUZZER_LIB"] = old_lib + + if (not is_build_failed) and fuzz_target: + built_bin = os.path.join(hfuzz2_dir, os.path.basename(fuzz_target)) + if os.path.exists(built_bin): + shutil.copy(built_bin, os.path.join(out_dir, "hfuzz2_" + os.path.basename(fuzz_target))) + + # 同时也将 HFUZZ2_FILES 复制到 /out + HFUZZ2_FILES = [ + "hfuzz2_br_node_id_2_cmp_type", + "hfuzz2_border_edges", + "hfuzz2_max_border_edge_id", + "hfuzz2_max_br_dist_edge_id", + "hfuzz2_border_edges_cache" + ] + for f in HFUZZ2_FILES: + in_build_dir = os.path.join(hfuzz2_dir, f) + if os.path.exists(in_build_dir): + shutil.copy(in_build_dir, os.path.join(out_dir, f)) + + return (not is_build_failed) + + +def build_vanilla_binary(): + print("[build_vanilla_binary] Building vanilla instrumentation.") + is_build_failed = False + + subprocess.check_call(["rm", "-f", "/dev/shm/*"]) + + src = os.getenv("SRC") + work = os.getenv("WORK") + fuzz_target = os.getenv("FUZZ_TARGET") + out_dir = os.getenv("OUT") + pwd = os.getcwd() + + old_cc = os.environ.get("CC") + old_cxx = os.environ.get("CXX") + old_lib = os.environ.get("FUZZER_LIB") + + os.environ["CC"] = "/afl_vanilla/afl-clang-fast" + os.environ["CXX"] = "/afl_vanilla/afl-clang-fast++" + os.environ["FUZZER_LIB"] = "/afl_vanilla/libAFLDriver.a" + + vanilla_dir = get_vanilla_build_directory(out_dir) + if not os.path.exists(vanilla_dir): + os.mkdir(vanilla_dir) + + with utils.restore_directory(src), utils.restore_directory(work): + new_env = os.environ.copy() + new_env["OUT"] = vanilla_dir + if fuzz_target: + new_env["FUZZ_TARGET"] = os.path.join(vanilla_dir, os.path.basename(fuzz_target)) + + try: + utils.build_benchmark(env=new_env) + except subprocess.CalledProcessError: + print("[build_vanilla_binary] Failed, skip.") + is_build_failed = True + finally: + os.chdir(pwd) + if old_cc is not None: + os.environ["CC"] = old_cc + if old_cxx is not None: + os.environ["CXX"] = old_cxx + if old_lib is not None: + os.environ["FUZZER_LIB"] = old_lib + + if (not is_build_failed) and fuzz_target: + built_bin = os.path.join(vanilla_dir, os.path.basename(fuzz_target)) + if os.path.exists(built_bin): + shutil.copy(built_bin, os.path.join(out_dir, os.path.basename(fuzz_target))) + + return (not is_build_failed) + + +def build_cmplog_binary(): + print("[build_cmplog_binary] Building cmplog instrumentation.") + is_build_failed = False + + subprocess.check_call(["rm", "-f", "/dev/shm/*"]) + + src = os.getenv("SRC") + work = os.getenv("WORK") + fuzz_target = os.getenv("FUZZ_TARGET") + out_dir = os.getenv("OUT") + pwd = os.getcwd() + + old_cc = os.environ.get("CC") + old_cxx = os.environ.get("CXX") + old_lib = os.environ.get("FUZZER_LIB") + old_cmp = os.environ.get("AFL_LLVM_CMPLOG") + + os.environ["CC"] = "/afl_vanilla/afl-clang-fast" + os.environ["CXX"] = "/afl_vanilla/afl-clang-fast++" + os.environ["FUZZER_LIB"] = "/afl_vanilla/libAFLDriver.a" + os.environ["AFL_LLVM_CMPLOG"] = "1" + + cmplog_dir = get_cmplog_build_directory(out_dir) + if not os.path.exists(cmplog_dir): + os.mkdir(cmplog_dir) + + with utils.restore_directory(src), utils.restore_directory(work): + new_env = os.environ.copy() + new_env["OUT"] = cmplog_dir + if fuzz_target: + new_env["FUZZ_TARGET"] = os.path.join(cmplog_dir, os.path.basename(fuzz_target)) + + try: + utils.build_benchmark(env=new_env) + except subprocess.CalledProcessError: + print("[build_cmplog_binary] Failed, skip.") + is_build_failed = True + finally: + os.chdir(pwd) + if old_cc is not None: + os.environ["CC"] = old_cc + if old_cxx is not None: + os.environ["CXX"] = old_cxx + if old_lib is not None: + os.environ["FUZZER_LIB"] = old_lib + if old_cmp is not None: + os.environ["AFL_LLVM_CMPLOG"] = old_cmp + else: + os.environ.pop("AFL_LLVM_CMPLOG", None) + + if (not is_build_failed) and fuzz_target: + built_bin = os.path.join(cmplog_dir, os.path.basename(fuzz_target)) + if os.path.exists(built_bin): + shutil.copy( + built_bin, + os.path.join(out_dir, "cmplog_" + os.path.basename(fuzz_target)) + ) + + return (not is_build_failed) + +def build_hfuzz3_binary(): + + is_build_failed = False + print("[build_hfuzz3_binary] Building hfuzz3 instrumentation.") + + out_dir = os.getenv("OUT") + pwd = os.getcwd() + # src = os.path.join(out_dir, "hfuzz3_target_bin") + src = os.getenv("SRC") + work = os.getenv("WORK") + + fuzz_target = os.getenv("FUZZ_TARGET") + + old_cc = os.environ.get("CC") + old_cxx = os.environ.get("CXX") + old_cflags = os.environ.get("CFLAGS") + old_cxxflags = os.environ.get("CXXFLAGS") + old_lib = os.environ.get("FUZZER_LIB") + old_cmp = os.environ.get("AFL_LLVM_CMPLOG") + + + os.environ["CC"] = "/hfuzz3/afl-clang-fast" + os.environ["CXX"] = "/hfuzz3/afl-clang-fast++" + os.environ["FUZZER_LIB"] = "/afl_vanilla/libAFLDriver.a" + # macros = "-DAFL_CFG_PATH=\\\"hfuzz3_sandcov_cfg\\\"" + # os.environ["CFLAGS"] = macros + # os.environ["CXXFLAGS"] = macros + + hfuzz3_dir = get_hfuzz3_build_directory(out_dir) + + if not os.path.exists(hfuzz3_dir): + os.mkdir(hfuzz3_dir) + + with utils.restore_directory(src), utils.restore_directory(work): + new_env = os.environ.copy() + new_env["OUT"] = hfuzz3_dir + + if fuzz_target is None: + raise RuntimeError(f"FUZZ_TARGET is not set") + if fuzz_target: + new_env["FUZZ_TARGET"] = os.path.join(hfuzz3_dir, os.path.basename(fuzz_target)) + + # dst = os.path.join(out_dir, 'hfuzz3_' + os.path.basename(fuzz_target)) + + # if os.path.exists(src): + # os.system(f"link {src} {dst}") + # return True + # else: + # return False + + try: + utils.build_benchmark(env=new_env) + + # for f in ["gen_graph.py", "hfuzz3_sancov_cfg"]: + # tmp_path = os.path.join("/hfuzz3", f) + # if os.path.exists(tmp_path): + # shutil.copy(tmp_path, os.path.join(hfuzz3_dir, f)) + + + graph_script = "/hfuzz3/gen_graph.py" + old_dir = os.getcwd() + try: + os.chdir(hfuzz3_dir) + final_fuzz_bin = new_env["FUZZ_TARGET"] + subprocess.check_call(["python3", graph_script, + final_fuzz_bin]) + finally: + os.chdir(old_dir) + except subprocess.CalledProcessError: + print("[build_hfuzz3_binary] Failed, skip.") + is_build_failed = True + finally: + os.chdir(pwd) + if old_cc is not None: + os.environ["CC"] = old_cc + if old_cxx is not None: + os.environ["CXX"] = old_cxx + # if old_cflags is not None: + # os.environ["CFLAGS"] = old_cflags + # if old_cxxflags is not None: + # os.environ["CXXFLAGS"] = old_cxxflags; + if old_lib is not None: + os.environ["FUZZER_LIB"] = old_lib + + if (not is_build_failed) and fuzz_target: + built_bin = os.path.join(hfuzz3_dir, os.path.basename(fuzz_target)) + if os.path.exists(built_bin): + shutil.copy( + built_bin, + os.path.join(out_dir, "hfuzz3_" + os.path.basename(fuzz_target)) + ) + + return (not is_build_failed) + +# def build_libafl_binary(): +# print("[build_libafl_binary] Building libafl instrumentation.") +# out_dir = os.getenv("OUT") +# src = os.path.join(out_dir, "libafl_target_bin") +# fuzz_target = os.getenv("FUZZ_TARGET") +# dst = os.path.join(out_dir, 'libafl_' + os.path.basename(fuzz_target)) + +# if os.path.exists(src): +# os.system(f"link {src} {dst}") +# return True +# else: +# return False + +def build_libafl_binary(): + print("[build_libafl_binary] Building libafl instrumentation.") + is_build_failed = False + + subprocess.check_call(["rm", "-f", "/dev/shm/*"]) + + src = os.getenv("SRC") + work = os.getenv("WORK") + fuzz_target = os.getenv("FUZZ_TARGET") + out_dir = os.getenv("OUT") + pwd = os.getcwd() + + old_cc = os.environ.get("CC") + old_cxx = os.environ.get("CXX") + old_lib = os.environ.get("FUZZER_LIB") + + + """Build benchmark.""" + os.environ['CC'] = ('/libafl/fuzzers/fuzzbench/fuzzbench' + '/target/release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/libafl/fuzzers/fuzzbench/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' + + libafl_dir = get_libafl_build_directory(out_dir) + if not os.path.exists(libafl_dir): + os.mkdir(libafl_dir) + + with utils.restore_directory(src), utils.restore_directory(work): + new_env = os.environ.copy() + new_env["OUT"] = libafl_dir + if fuzz_target: + new_env["FUZZ_TARGET"] = os.path.join(libafl_dir, os.path.basename(fuzz_target)) + + try: + utils.build_benchmark(env=new_env) + + except subprocess.CalledProcessError: + print("[build_libafl_binary] Failed, skip.") + is_build_failed = True + finally: + os.chdir(pwd) + if old_cc is not None: + os.environ["CC"] = old_cc + if old_cxx is not None: + os.environ["CXX"] = old_cxx + if old_lib is not None: + os.environ["FUZZER_LIB"] = old_lib + + if (not is_build_failed) and fuzz_target: + built_bin = os.path.join(libafl_dir, os.path.basename(fuzz_target)) + if os.path.exists(built_bin): + shutil.copy(built_bin, os.path.join(out_dir, "libafl_" + os.path.basename(fuzz_target))) + + return (not is_build_failed) + +def build(): + """ + 在 OSS-Fuzz 中被调用的主要构建入口。 + 按顺序编译:hfuzz1、hfuzz2、vanilla、cmplog, + 并复制相应的 fuzzer 主程序到 /out。 + """ + install_all() + prepare_build_environment() + + built_hfuzz1 = build_hfuzz1_binary() + built_hfuzz2 = build_hfuzz2_binary() + built_vanilla = build_vanilla_binary() + built_cmplog = build_cmplog_binary() + built_hfuzz3 = build_hfuzz3_binary() + build_libafl = build_libafl_binary() + + + # 复制 fuzzer 主程序。如果没编译成功, 也许不会用到, 但这里先都拷或者做检查 + if os.path.exists("/hfuzz1/afl-fuzz"): + shutil.copy("/hfuzz1/afl-fuzz", os.path.join(os.environ["OUT"], "hfuzz1_4.30c_hybrid_start")) + if os.path.exists("/hfuzz2/afl-fuzz"): + shutil.copy("/hfuzz2/afl-fuzz", os.path.join(os.environ["OUT"], "hfuzz2_4.30c_hybrid_start")) + if os.path.exists("/afl_vanilla/afl-fuzz"): + shutil.copy("/afl_vanilla/afl-fuzz", os.path.join(os.environ["OUT"], "afl-fuzz-vanilla")) + shutil.copy("/afl_vanilla/afl-fuzz", os.path.join(os.environ["OUT"], "cmplog_4.30c_hybrid_start")) + # @yrd the fuzzer is compiled in $OUT. The fuzzer is $OUT/libafl_fuzzer. + # if os.path.exists("/PATH/to/libafl-fuzzer"): + # shutil.copy("/path/to/libafl-fuzzer", os.path.join(os.environ["OUT"], "libafl_fuzzer")) + """ + if os.path.exists("/hfuzz3/main"): + shutil.copy("/hfuzz3/main", os.path.join(os.environ["OUT"], "hfuzz3_4.30c_hybrid_start")) + """ + # if os.path.exists("/hfuzz3/gen_graph.py"): + # shutil.copy("/hfuzz3/gen_graph.py", os.path.join(os.environ["OUT"], "gen_graph.py")) + if os.path.exists("/hfuzz3/afl-fuzz"): + shutil.copy("/hfuzz3/afl-fuzz", os.path.join(os.environ["OUT"], "hfuzz3_fuzzer")) + shutil.copy("/hfuzz3/afl-fuzz", os.path.join(os.environ["OUT"], "hfuzz3_4.30c_hybrid_start")) + + + # ensemble_runner.py + if os.path.exists("/hfuzz2/ensemble_runner.py"): + shutil.copy("/hfuzz2/ensemble_runner.py", os.environ["OUT"]) + + print("[build] Build results:") + print(" HFUZZ1 :", "OK" if built_hfuzz1 else "FAIL") + print(" HFuzz2 :", "OK" if built_hfuzz2 else "FAIL") + print(" Vanilla :", "OK" if built_vanilla else "FAIL") + print(" CmpLog :", "OK" if built_cmplog else "FAIL") + print(" LibAFL :", "OK" if build_libafl else "FAIL") + print(" HFuzz3:", "OK" if built_hfuzz3 else "FAIL") + + if not any([built_hfuzz1, built_hfuzz2, built_vanilla, built_cmplog, build_libafl]): + with open(os.path.join(os.getenv("OUT"), "is_vanilla"), "w") as f: + f.write("all_failed") + print("[build] All instrumentation failed.") + + +def prepare_fuzz_environment(input_corpus): + """准备fuzz环境,比如设置AFL_NO_UI, AFL_AUTORESUME等。""" + os.environ["AFL_NO_UI"] = "1" + os.environ["AFL_SKIP_CPUFREQ"] = "1" + os.environ["AFL_NO_AFFINITY"] = "1" + os.environ["AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES"] = "1" + os.environ["AFL_SKIP_CRASHES"] = "1" + os.environ["AFL_SHUFFLE_QUEUE"] = "1" + os.environ["AFL_FAST_CAL"] = "1" + os.environ["AFL_DISABLE_TRIM"] = "1" + os.environ["AFL_CMPLOG_ONLY_NEW"] = "1" + os.environ["AFL_AUTORESUME"] = "1" + + utils.create_seed_file_for_empty_corpus(input_corpus) + +# def run_libafl_fuzz(input_corpus, output_corpus, target_binary): +# out_dir = os.getenv("OUT") +# target_binary = target_binary +# subprocess.run( +# f"{os.path.join(out_dir, target_binary)} --cores 1 --input {input_corpus} --output {output_corpus}", +# shell=True +# ) + +def run_afl_fuzz(input_corpus, output_corpus, target_binary, hide_output=False): + dictionary_path = utils.get_dictionary_path(target_binary) + out_dir = os.getenv("OUT") + + van_bin = os.path.join(out_dir, "afl-fuzz-vanilla") + + hfuzz1_built_path = os.path.join(out_dir, "hfuzz1_" + os.path.basename(target_binary)) + hfuzz2_built_path = os.path.join(out_dir, "hfuzz2_" + os.path.basename(target_binary)) + cmplog_built_path = os.path.join(out_dir, "cmplog_" + os.path.basename(target_binary)) + libafl_build_path = os.path.join(out_dir, "libafl_" + os.path.basename(target_binary)) + hfuzz3_build_path = os.path.join(out_dir, "hfuzz3_" + os.path.basename(target_binary)) + + has_any_ensemble = any([os.path.exists(hfuzz1_built_path), + os.path.exists(hfuzz2_built_path), + os.path.exists(cmplog_built_path), + os.path.exists(libafl_build_path), + os.path.exists(hfuzz3_build_path)]) + if has_any_ensemble: + cmd = [ + "python", "ensemble_runner.py", + "-i", input_corpus, "-o", output_corpus, + "-b", target_binary + ] + + if os.path.exists(hfuzz1_built_path): + cmd += ["--hfuzz1_target_binary", hfuzz1_built_path] + + if os.path.exists(hfuzz2_built_path): + cmd += ["--hfuzz2_target_binary", hfuzz2_built_path] + + if os.path.exists(cmplog_built_path): + cmd += ["--cmplog_target_binary", cmplog_built_path] + + + if os.path.exists(libafl_build_path): + cmd += ["--libafl_target_binary", libafl_build_path] + + + if os.path.exists(hfuzz3_build_path): + cmd += ["--hfuzz3_target_binary", hfuzz3_build_path] + + if dictionary_path: + cmd += ["-x", os.path.join("/out", "keyval.dict"), dictionary_path] + + print("[run_afl_fuzz] Ensemble command:", " ".join(cmd)) + output_stream = subprocess.DEVNULL if hide_output else None + subprocess.check_call(cmd, stdout=output_stream, stderr=output_stream) + else: + if os.path.exists(van_bin): + cmd = [ + van_bin, + "-i", input_corpus, + "-o", output_corpus, + "-t", "1000+", + "-m", "none", + "--", + target_binary + ] + if dictionary_path: + cmd += ["-x", os.path.join("/out", "keyval.dict"), "-x", dictionary_path] + + print("[run_afl_fuzz] Vanilla command:", " ".join(cmd)) + output_stream = subprocess.DEVNULL if hide_output else None + subprocess.check_call(cmd, stdout=output_stream, stderr=output_stream) + else: + print("[run_afl_fuzz] No valid fuzzer found, aborting.") + + +def fuzz(input_corpus, output_corpus, target_binary): + """ + 在 OSS-Fuzz 中实际执行fuzz的入口。 + """ + prepare_fuzz_environment(input_corpus) + run_afl_fuzz(input_corpus, output_corpus, target_binary) \ No newline at end of file diff --git a/fuzzers/hfuzz/runner.Dockerfile b/fuzzers/hfuzz/runner.Dockerfile new file mode 100644 index 000000000..5640d5b24 --- /dev/null +++ b/fuzzers/hfuzz/runner.Dockerfile @@ -0,0 +1,24 @@ +# 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 + +# 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 +# RUN apt-get update && apt-get upgrade && apt install -y unzip git gdb joe From 3689ccce1d7f79a067547b3b07bafe032175b554 Mon Sep 17 00:00:00 2001 From: Yu3H0 Date: Tue, 7 Jan 2025 18:41:01 +0800 Subject: [PATCH 3/8] add benchmark --- .../libarchive_libarchive_fuzzer/Dockerfile | 42 +++++++++ .../benchmark.yaml | 4 + .../libarchive_libarchive_fuzzer/build.sh | 57 ++++++++++++ .../libarchive_fuzzer.cc | 86 +++++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 benchmarks/libarchive_libarchive_fuzzer/Dockerfile create mode 100644 benchmarks/libarchive_libarchive_fuzzer/benchmark.yaml create mode 100755 benchmarks/libarchive_libarchive_fuzzer/build.sh create mode 100644 benchmarks/libarchive_libarchive_fuzzer/libarchive_fuzzer.cc diff --git a/benchmarks/libarchive_libarchive_fuzzer/Dockerfile b/benchmarks/libarchive_libarchive_fuzzer/Dockerfile new file mode 100644 index 000000000..8374b7c8f --- /dev/null +++ b/benchmarks/libarchive_libarchive_fuzzer/Dockerfile @@ -0,0 +1,42 @@ +# Copyright 2016 Google Inc. +# +# 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/oss-fuzz-base/base-builder + +RUN apt-get update && apt-get install -y make autoconf libtool pkg-config \ + libbz2-dev liblzo2-dev liblzma-dev liblz4-dev libz-dev \ + libssl-dev libacl1-dev libattr1-dev lrzip liblzo2-dev \ + liblz4-tool lzop zstd lcab genisoimage jlha-utils rar default-jdk sharutils +RUN curl -LO http://mirrors.kernel.org/ubuntu/pool/main/a/automake-1.16/automake_1.16.5-1.3_all.deb && \ + apt install ./automake_1.16.5-1.3_all.deb +RUN git clone --depth 1 https://github.com/libarchive/libarchive.git +RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git +# compile libxml2 from source so we can statically link +RUN mkdir /deps && \ + cd $SRC/libxml2 && \ + ./autogen.sh \ + --without-debug \ + --without-ftp \ + --without-http \ + --without-legacy \ + --without-python \ + --enable-static && \ + make -j$(nproc) && \ + make install && \ + cp .libs/libxml2.a /deps/ + +COPY build.sh libarchive_fuzzer.cc $SRC/ +WORKDIR $SRC diff --git a/benchmarks/libarchive_libarchive_fuzzer/benchmark.yaml b/benchmarks/libarchive_libarchive_fuzzer/benchmark.yaml new file mode 100644 index 000000000..ef331a97d --- /dev/null +++ b/benchmarks/libarchive_libarchive_fuzzer/benchmark.yaml @@ -0,0 +1,4 @@ +commit: d5b74d5cccd0601ef4f88b19ea9f32740fcb10ba +commit_date: 2024-07-01 15:34:53+00:00 +fuzz_target: libarchive_fuzzer +project: libarchive diff --git a/benchmarks/libarchive_libarchive_fuzzer/build.sh b/benchmarks/libarchive_libarchive_fuzzer/build.sh new file mode 100755 index 000000000..368f2b0bf --- /dev/null +++ b/benchmarks/libarchive_libarchive_fuzzer/build.sh @@ -0,0 +1,57 @@ +#!/bin/bash -eu +# Copyright 2016 Google Inc. +# +# 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. +# +################################################################################ + +# For fuzz-introspector. This is to exclude all libxml2 code from the +# fuzz-introspector reports. +export FUZZ_INTROSPECTOR_CONFIG=$SRC/fuzz_introspector_exclusion.config +cat > $FUZZ_INTROSPECTOR_CONFIG < +#include +#include + +#include "archive.h" +#include "archive_entry.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { + struct archive *a = archive_read_new(); + + archive_read_support_filter_all(a); + archive_read_support_format_all(a); + archive_read_support_format_empty(a); + archive_read_support_format_raw(a); + archive_read_support_format_gnutar(a); + + if (ARCHIVE_OK != archive_read_set_options(a, "zip:ignorecrc32,tar:read_concatenated_archives,tar:mac-ext")) { + return 0; + } + + archive_read_add_passphrase(a, "secret"); + + if (ARCHIVE_OK != archive_read_open_memory(a, buf, len)) { + archive_read_free(a); + return 0; + } + + while(1) { + std::vector data_buffer(getpagesize(), 0); + struct archive_entry *entry; + int ret = archive_read_next_header(a, &entry); + if (ret == ARCHIVE_EOF || ret == ARCHIVE_FATAL) + break; + if (ret == ARCHIVE_RETRY) + continue; + + (void)archive_entry_pathname(entry); + (void)archive_entry_pathname_utf8(entry); + (void)archive_entry_pathname_w(entry); + + (void)archive_entry_atime(entry); + (void)archive_entry_birthtime(entry); + (void)archive_entry_ctime(entry); + (void)archive_entry_dev(entry); + (void)archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA1); + (void)archive_entry_filetype(entry); + (void)archive_entry_gid(entry); + (void)archive_entry_is_data_encrypted(entry); + (void)archive_entry_is_encrypted(entry); + (void)archive_entry_is_metadata_encrypted(entry); + (void)archive_entry_mode(entry); + (void)archive_entry_mtime(entry); + (void)archive_entry_size(entry); + (void)archive_entry_uid(entry); + + ssize_t r; + while ((r = archive_read_data(a, data_buffer.data(), + data_buffer.size())) > 0) + ; + if (r == ARCHIVE_FATAL) + break; + } + + archive_read_has_encrypted_entries(a); + archive_read_format_capabilities(a); + archive_file_count(a); + archive_seek_data(a, 0, SEEK_SET); + + archive_read_free(a); + return 0; +} From de2131c0a3420ccc7a77a87e9c923ca15629ed14 Mon Sep 17 00:00:00 2001 From: Yuchong Xie <82574337+Yu3H0@users.noreply.github.com> Date: Thu, 9 Jan 2025 20:53:10 +0800 Subject: [PATCH 4/8] fix a little bug --- fuzzers/hfuzz/fuzzer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fuzzers/hfuzz/fuzzer.py b/fuzzers/hfuzz/fuzzer.py index c956543e9..f51f55826 100644 --- a/fuzzers/hfuzz/fuzzer.py +++ b/fuzzers/hfuzz/fuzzer.py @@ -603,7 +603,7 @@ def build(): # if os.path.exists("/hfuzz3/gen_graph.py"): # shutil.copy("/hfuzz3/gen_graph.py", os.path.join(os.environ["OUT"], "gen_graph.py")) if os.path.exists("/hfuzz3/afl-fuzz"): - shutil.copy("/hfuzz3/afl-fuzz", os.path.join(os.environ["OUT"], "hfuzz3_fuzzer")) + # shutil.copy("/hfuzz3/afl-fuzz", os.path.join(os.environ["OUT"], "hfuzz3_fuzzer")) shutil.copy("/hfuzz3/afl-fuzz", os.path.join(os.environ["OUT"], "hfuzz3_4.30c_hybrid_start")) @@ -721,4 +721,4 @@ def fuzz(input_corpus, output_corpus, target_binary): 在 OSS-Fuzz 中实际执行fuzz的入口。 """ prepare_fuzz_environment(input_corpus) - run_afl_fuzz(input_corpus, output_corpus, target_binary) \ No newline at end of file + run_afl_fuzz(input_corpus, output_corpus, target_binary) From d4e6abccc27087f441d68540be6e79404dedb20a Mon Sep 17 00:00:00 2001 From: Yuchong Xie <82574337+Yu3H0@users.noreply.github.com> Date: Fri, 17 Jan 2025 19:04:34 +0800 Subject: [PATCH 5/8] drop cmplog --- fuzzers/hfuzz/ensemble_runner.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/fuzzers/hfuzz/ensemble_runner.py b/fuzzers/hfuzz/ensemble_runner.py index 1c9211c3c..2be2ef01a 100644 --- a/fuzzers/hfuzz/ensemble_runner.py +++ b/fuzzers/hfuzz/ensemble_runner.py @@ -445,14 +445,8 @@ def __init__( def build_command(self): """Build the command for running the HFuzz2 fuzzer.""" if self.cmplog_target_binary: - # 如果有 cmplog_target_binary,则像 cmplog 一样加上 -c 参数 - self.command = [ - HFUZZ2_FUZZ_BIN_NAME, - '-c', - self.cmplog_target_binary - ] + self.command = [HFUZZ2_FUZZ_BIN_NAME] else: - # 否则普通运行 self.command = [HFUZZ2_FUZZ_BIN_NAME] self.add_common_args() From 4b69c745f5b81d72de9ab320a2e3582deeeb8824 Mon Sep 17 00:00:00 2001 From: Yuchong Xie <82574337+Yu3H0@users.noreply.github.com> Date: Fri, 17 Jan 2025 19:24:29 +0800 Subject: [PATCH 6/8] use the same directory --- fuzzers/hfuzz/fuzzer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuzzers/hfuzz/fuzzer.py b/fuzzers/hfuzz/fuzzer.py index f51f55826..b1cad8b72 100644 --- a/fuzzers/hfuzz/fuzzer.py +++ b/fuzzers/hfuzz/fuzzer.py @@ -75,7 +75,7 @@ def get_hfuzz2_build_directory(target_directory): def get_vanilla_build_directory(target_directory): """Return path to vanilla build directory.""" - return os.path.join(target_directory, "vanilla") + return target_directory def get_cmplog_build_directory(target_directory): From f88c7b1897ee3804305e44b1c2131219004a82a6 Mon Sep 17 00:00:00 2001 From: Yuchong Xie <82574337+Yu3H0@users.noreply.github.com> Date: Sat, 18 Jan 2025 10:04:39 +0800 Subject: [PATCH 7/8] comment out the copy --- fuzzers/hfuzz/fuzzer.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fuzzers/hfuzz/fuzzer.py b/fuzzers/hfuzz/fuzzer.py index b1cad8b72..0e97fcc50 100644 --- a/fuzzers/hfuzz/fuzzer.py +++ b/fuzzers/hfuzz/fuzzer.py @@ -327,10 +327,10 @@ def build_vanilla_binary(): if old_lib is not None: os.environ["FUZZER_LIB"] = old_lib - if (not is_build_failed) and fuzz_target: - built_bin = os.path.join(vanilla_dir, os.path.basename(fuzz_target)) - if os.path.exists(built_bin): - shutil.copy(built_bin, os.path.join(out_dir, os.path.basename(fuzz_target))) + # if (not is_build_failed) and fuzz_target: + # built_bin = os.path.join(vanilla_dir, os.path.basename(fuzz_target)) + # if os.path.exists(built_bin): + # shutil.copy(built_bin, os.path.join(out_dir, os.path.basename(fuzz_target))) return (not is_build_failed) From a4e7344871f91a85a4802ed558152b05d80bf833 Mon Sep 17 00:00:00 2001 From: Yuchong Xie <82574337+Yu3H0@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:04:14 +0800 Subject: [PATCH 8/8] Update ensemble_runner.py --- fuzzers/hfuzz/ensemble_runner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fuzzers/hfuzz/ensemble_runner.py b/fuzzers/hfuzz/ensemble_runner.py index 2be2ef01a..0cb3cf3c1 100644 --- a/fuzzers/hfuzz/ensemble_runner.py +++ b/fuzzers/hfuzz/ensemble_runner.py @@ -52,9 +52,9 @@ # Timeout strategies (in seconds) TMOUT_CMPLOG = 60 * 60 # 90 minutes TIMEOUT_HFUZZ3 = 60 * 60 -TMOUT_HFUZZ1 = 8 * 60 * 60 # 120 minutes +TMOUT_HFUZZ1 = 4 * 60 * 60 # 120 minutes TMOUT_HFUZZ2 = 60 * 60 # 120 minutes -TIMEOUT_LIBAFL = 60 * 60 # 1 minute +TIMEOUT_LIBAFL = 4 * 60 * 60 # 1 minute def time_s():