Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
59 changes: 37 additions & 22 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)" $(<) $(>)
Comment thread
mborland marked this conversation as resolved.
Outdated
}
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 fuzz_time = 60 ;
local corpus = /tmp/corpus/$(fuzzer) ;
local min_corpus = /tmp/mincorpus/$(fuzzer) ;
Comment thread
mborland marked this conversation as resolved.
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 ;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like adding a dependency to the script make rules run. As it reruns the targets if it's only the script that changes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean by this, or how to implement the suggestion

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would that be this?

Suggested change
make $(corpus) : $(seed_files) : make-corpus ;
make $(corpus) : $(seed_files) : make-corpus <dependency> $(.make-corpus-script) ;

BTW: Does it automatically add a dependency on the input files?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Flamefire yes that would be it. And yes, the make rule adds dependencies for inputs (all B2 rules do).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops.. There should be an additional : there.. make-corpus : <dependency> $(.make-corpus-script)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is giving the error

error: '/home/runner/work/charconv/boost-root/libs/charconv/fuzzing/make-corpus.py' is not a valid property specification

https://github.com/boostorg/charconv/actions/runs/12792451062/job/35662937747?pr=256#step:7:44

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There shouldn't be a space in the dependency. It should be <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:])