diff --git a/fuzzing/Jamfile b/fuzzing/Jamfile index 4739898ac..31dda6a58 100644 --- a/fuzzing/Jamfile +++ b/fuzzing/Jamfile @@ -1,27 +1,50 @@ -# -# Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) # Copyright (c) 2024 Matt Borland +# Copyright (c) 2025 Alexander Grund # -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -# +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt. + import common ; +import path ; +import python ; import regex ; +import toolset ; + +path-constant HERE : . ; local all_fuzzers = [ regex.replace-list [ glob "fuzz_*.cpp" ] : ".cpp" : "" ] ; +if ! [ python.configured ] +{ + using python ; +} + +.make-corpus-script = $(HERE)/make-corpus.py ; + +rule make-corpus ( target : sources + : properties * ) +{ + RUNNER on $(target) = [ path.native $(.make-corpus-script) ] ; +} +actions make-corpus +{ + "$(PYTHON:E=python)" "$(RUNNER)" $(<) $(>) +} +toolset.flags $(__name__).make-corpus PYTHON ; + for local fuzzer in $(all_fuzzers) { - # These two fuzzers are the most complex ones. The rest are really - # simple, so less time is enough - local fuzz_time = 30 ; + local fuzz_time = 60 ; + local corpus = /tmp/corpus/$(fuzzer) ; + local min_corpus = /tmp/mincorpus/$(fuzzer) ; + local seed_corpus = $(HERE)/seedcorpus/$(fuzzer) ; + local seed_files = [ glob "$(seed_corpus)/*" ] ; # Create the output corpus directories - make /tmp/corpus/$(fuzzer) : : common.MkDir ; - make /tmp/mincorpus/$(fuzzer) : : common.MkDir ; + make $(corpus) : $(seed_files) : make-corpus ; + make $(min_corpus) : : common.MkDir ; # Build the fuzzer exe $(fuzzer) @@ -36,31 +59,21 @@ for local fuzzer in $(all_fuzzers) -fsanitize=fuzzer ; - # Make sure that any old crashes are run without problems - local old_crashes = [ glob-tree-ex old_crashes/$(fuzzer) : * ] ; - if $(old_crashes) - { - run $(fuzzer) - : target-name $(fuzzer)-old-crashes - : input-files [ SORT $(old_crashes) ] - ; - } - # Run the fuzzer for a short while run $(fuzzer) - : "seedcorpus/$(fuzzer) -max_total_time=$(fuzz_time)" + : "$(corpus) -max_total_time=$(fuzz_time)" : target-name $(fuzzer)-fuzzing : requirements - /tmp/corpus/$(fuzzer) + $(corpus) ; # Minimize the corpus run $(fuzzer) - : "/tmp/mincorpus/$(fuzzer) /tmp/corpus/$(fuzzer) -merge=1" + : "$(min_corpus) $(corpus) -merge=1" : target-name $(fuzzer)-minimize-corpus : requirements $(fuzzer)-fuzzing - /tmp/corpus/$(fuzzer) - /tmp/mincorpus/$(fuzzer) + $(corpus) + $(min_corpus) ; } diff --git a/fuzzing/make-corpus.py b/fuzzing/make-corpus.py new file mode 100644 index 000000000..93d6d0da2 --- /dev/null +++ b/fuzzing/make-corpus.py @@ -0,0 +1,32 @@ +#!/bin/env python + +# Copyright (c) 2025 Alexander Grund +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt. + +import os +import sys + +def get_samples(input_files): + for file_name in input_files: + if not os.path.isfile(file_name): + raise RuntimeError("Not a file: " + file_name) + with open(file_name, 'r') as input_file: + yield from input_file + + +def process_files(output_folder, input_files): + if not os.path.exists(output_folder): + os.makedirs(output_folder) + + for i, sample in enumerate(get_samples(input_files)): + with open(os.path.join(output_folder, str(i) + ".txt"), 'w') as output_file: + output_file.write(sample) + + +if __name__ == "__main__": + if len(sys.argv) < 3: + print("Usage: python script.py [ ...]") + sys.exit(1) + + process_files(output_folder=sys.argv[1], input_files=sys.argv[2:])