Skip to content

Commit 5fdab9f

Browse files
authored
Merge pull request #789 from cppalliance/fuzzing
Improved Fuzzing
2 parents 113de3d + b978857 commit 5fdab9f

File tree

2 files changed

+70
-25
lines changed

2 files changed

+70
-25
lines changed

fuzzing/Jamfile

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,50 @@
1-
#
2-
# Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
31
# Copyright (c) 2024 Matt Borland
2+
# Copyright (c) 2025 Alexander Grund
43
#
5-
# Distributed under the Boost Software License, Version 1.0. (See accompanying
6-
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7-
#
4+
# Distributed under the Boost Software License, Version 1.0.
5+
# https://www.boost.org/LICENSE_1_0.txt.
6+
87

98
import common ;
9+
import path ;
10+
import python ;
1011
import regex ;
12+
import toolset ;
13+
14+
path-constant HERE : . ;
1115

1216
local all_fuzzers = [ regex.replace-list
1317
[ glob "fuzz_*.cpp" ] : ".cpp" : ""
1418
] ;
1519

20+
if ! [ python.configured ]
21+
{
22+
using python ;
23+
}
24+
25+
.make-corpus-script = $(HERE)/make-corpus.py ;
26+
27+
rule make-corpus ( target : sources + : properties * )
28+
{
29+
RUNNER on $(target) = [ path.native $(.make-corpus-script) ] ;
30+
}
31+
actions make-corpus
32+
{
33+
"$(PYTHON:E=python)" "$(RUNNER)" $(<) $(>)
34+
}
35+
toolset.flags $(__name__).make-corpus PYTHON <python.interpreter> ;
36+
1637
for local fuzzer in $(all_fuzzers)
1738
{
18-
# These two fuzzers are the most complex ones. The rest are really
19-
# simple, so less time is enough
20-
local fuzz_time = 30 ;
39+
local fuzz_time = 60 ;
40+
local corpus = /tmp/corpus/$(fuzzer) ;
41+
local min_corpus = /tmp/mincorpus/$(fuzzer) ;
42+
local seed_corpus = $(HERE)/seedcorpus/$(fuzzer) ;
43+
local seed_files = [ glob "$(seed_corpus)/*" ] ;
2144

2245
# Create the output corpus directories
23-
make /tmp/corpus/$(fuzzer) : : common.MkDir ;
24-
make /tmp/mincorpus/$(fuzzer) : : common.MkDir ;
46+
make $(corpus) : $(seed_files) : make-corpus ;
47+
make $(min_corpus) : : common.MkDir ;
2548

2649
# Build the fuzzer
2750
exe $(fuzzer)
@@ -36,31 +59,21 @@ for local fuzzer in $(all_fuzzers)
3659
<linkflags>-fsanitize=fuzzer
3760
;
3861

39-
# Make sure that any old crashes are run without problems
40-
local old_crashes = [ glob-tree-ex old_crashes/$(fuzzer) : * ] ;
41-
if $(old_crashes)
42-
{
43-
run $(fuzzer)
44-
: target-name $(fuzzer)-old-crashes
45-
: input-files [ SORT $(old_crashes) ]
46-
;
47-
}
48-
4962
# Run the fuzzer for a short while
5063
run $(fuzzer)
51-
: <testing.arg>"seedcorpus/$(fuzzer) -max_total_time=$(fuzz_time)"
64+
: <testing.arg>"$(corpus) -max_total_time=$(fuzz_time)"
5265
: target-name $(fuzzer)-fuzzing
5366
: requirements
54-
<dependency>/tmp/corpus/$(fuzzer)
67+
<dependency>$(corpus)
5568
;
5669

5770
# Minimize the corpus
5871
run $(fuzzer)
59-
: <testing.arg>"/tmp/mincorpus/$(fuzzer) /tmp/corpus/$(fuzzer) -merge=1"
72+
: <testing.arg>"$(min_corpus) $(corpus) -merge=1"
6073
: target-name $(fuzzer)-minimize-corpus
6174
: requirements
6275
<dependency>$(fuzzer)-fuzzing
63-
<dependency>/tmp/corpus/$(fuzzer)
64-
<dependency>/tmp/mincorpus/$(fuzzer)
76+
<dependency>$(corpus)
77+
<dependency>$(min_corpus)
6578
;
6679
}

fuzzing/make-corpus.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/env python
2+
3+
# Copyright (c) 2025 Alexander Grund
4+
# Distributed under the Boost Software License, Version 1.0.
5+
# https://www.boost.org/LICENSE_1_0.txt.
6+
7+
import os
8+
import sys
9+
10+
def get_samples(input_files):
11+
for file_name in input_files:
12+
if not os.path.isfile(file_name):
13+
raise RuntimeError("Not a file: " + file_name)
14+
with open(file_name, 'r') as input_file:
15+
yield from input_file
16+
17+
18+
def process_files(output_folder, input_files):
19+
if not os.path.exists(output_folder):
20+
os.makedirs(output_folder)
21+
22+
for i, sample in enumerate(get_samples(input_files)):
23+
with open(os.path.join(output_folder, str(i) + ".txt"), 'w') as output_file:
24+
output_file.write(sample)
25+
26+
27+
if __name__ == "__main__":
28+
if len(sys.argv) < 3:
29+
print("Usage: python script.py <output_folder> <input_file1> [<input_file2> ...]")
30+
sys.exit(1)
31+
32+
process_files(output_folder=sys.argv[1], input_files=sys.argv[2:])

0 commit comments

Comments
 (0)