Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 36 additions & 21 deletions fuzzing/Jamfile
Original file line number Diff line number Diff line change
@@ -1,27 +1,52 @@
#
# 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 <python.interpreter> ;

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 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 : <dependency>$(.make-corpus-script) ;
make $(min_corpus) : : common.MkDir ;

# Build the fuzzer
exe $(fuzzer)
Expand All @@ -37,31 +62,21 @@ for local fuzzer in $(all_fuzzers)
<library>/boost/charconv//boost_charconv
;

# 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)
: <testing.arg>"seedcorpus/$(fuzzer) -max_total_time=$(fuzz_time)"
: <testing.arg>"$(corpus) -max_total_time=$(fuzz_time)"
: target-name $(fuzzer)-fuzzing
: requirements
<dependency>/tmp/corpus/$(fuzzer)
<dependency>$(corpus)
;

# Minimize the corpus
run $(fuzzer)
: <testing.arg>"/tmp/mincorpus/$(fuzzer) /tmp/corpus/$(fuzzer) -merge=1"
: <testing.arg>"$(min_corpus) $(corpus) -merge=1"
: target-name $(fuzzer)-minimize-corpus
: requirements
<dependency>$(fuzzer)-fuzzing
<dependency>/tmp/corpus/$(fuzzer)
<dependency>/tmp/mincorpus/$(fuzzer)
<dependency>$(corpus)
<dependency>$(min_corpus)
;
}
32 changes: 32 additions & 0 deletions fuzzing/make-corpus.py
Original file line number Diff line number Diff line change
@@ -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 <output_folder> <input_file1> [<input_file2> ...]")
sys.exit(1)

process_files(output_folder=sys.argv[1], input_files=sys.argv[2:])
Loading