mirror of
https://github.com/boostorg/json.git
synced 2025-05-10 09:43:52 +00:00
190 lines
4.7 KiB
Plaintext
190 lines
4.7 KiB
Plaintext
#
|
|
# Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
|
# Copyright (c) 2019 Paul Dreik
|
|
# Copyright (c) 2021 Dmitry Arkhipov (grisumbras@gmail.com)
|
|
#
|
|
# 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)
|
|
#
|
|
# Official repository: https://github.com/boostorg/json
|
|
#
|
|
|
|
|
|
import common ;
|
|
import link ;
|
|
import os ;
|
|
import path ;
|
|
import property ;
|
|
import sequence ;
|
|
import testing ;
|
|
|
|
|
|
# set the maximum size of the input, to avoid
|
|
# big inputs which blow up the corpus size
|
|
.MAXLEN = [ os.environ MAXLEN ] ;
|
|
.MAXLEN ?= -max_len=4000 ;
|
|
|
|
# set a timelimit (you may want to adjust this if you run locally)
|
|
.MAXTIME = [ os.environ MAXTIME ] ;
|
|
.MAXTIME ?= -max_total_time=30 ;
|
|
|
|
# If doing fuzzing locally (not in CI), adjust this to utilize more
|
|
# of your cpu.
|
|
#JOBS="-jobs=32"
|
|
.JOBS = [ os.environ JOBS ] ;
|
|
|
|
# make sure ubsan stops in case anything is found
|
|
.UBSAN_OPTIONS = [
|
|
common.variable-setting-command UBSAN_OPTIONS : halt_on_error=1
|
|
] ;
|
|
|
|
local corpus.tar = [ glob-ex . : corpus.tar ] ;
|
|
if $(corpus.tar)
|
|
{
|
|
# if an old corpus exists, use it
|
|
# get it with curl -O --location -J https://bintray.com/pauldreik/boost.json/download_file?file_path=corpus%2Fcorpus.tar
|
|
make old-corpus
|
|
: $(corpus.tar)
|
|
: @untar-corpus
|
|
: <location>oldcorpus
|
|
;
|
|
}
|
|
else
|
|
{
|
|
alias old-corpus ;
|
|
}
|
|
explicit old-corpus ;
|
|
|
|
|
|
local initial-corpus = [ glob-tree-ex ../test : *.json ] ;
|
|
|
|
|
|
local variants = basic_parser parse parser direct_parse ;
|
|
for local variant in basic_parser parse parser direct_parse
|
|
{
|
|
local $(variant)-runs ;
|
|
local fuzzer = fuzzer_$(variant) ;
|
|
lib $(fuzzer) : fuzz_$(variant).cpp /boost/json//boost_json ;
|
|
exe $(fuzzer)
|
|
: fuzz_$(variant).cpp /boost/json//json_sources
|
|
: requirements
|
|
<toolset>clang
|
|
<conditional>@fuzzer-props
|
|
;
|
|
|
|
# make sure the old crashes pass without problems
|
|
local old-runs = [ glob-tree-ex old_crashes/$(variant) : * ] ;
|
|
if $(old-runs)
|
|
{
|
|
run $(fuzzer)
|
|
: target-name $(variant)-run-crashes
|
|
: input-files [ SORT $(old-runs) ]
|
|
;
|
|
$(variant)-runs += $(variant)-run-crashes ;
|
|
}
|
|
|
|
make oldcorpus/$(variant)
|
|
: old-corpus
|
|
: common.MkDir
|
|
: <location>.
|
|
;
|
|
explicit oldcorpus/$(variant) ;
|
|
|
|
# make an initial corpus from the test data already in the repo
|
|
local seed-corpus ;
|
|
for file in $(initial-corpus)
|
|
{
|
|
local copied = $(variant)/$(file:D=) ;
|
|
make $(copied) : $(file) : common.copy : <location>seedcorpus ;
|
|
explicit $(copied) ;
|
|
seed-corpus += $(copied) ;
|
|
}
|
|
make seedcorpus/$(variant)
|
|
: $(seed-corpus)
|
|
: common.MkDir
|
|
: <location>.
|
|
;
|
|
explicit seedcorpus/$(variant) ;
|
|
|
|
# run the fuzzer for a short while
|
|
make out/$(variant)
|
|
: $(fuzzer)
|
|
oldcorpus/$(variant)
|
|
seedcorpus/$(variant)
|
|
: @run-fuzzer
|
|
: <location>.
|
|
<flags>$(.MAXTIME)
|
|
<flags>$(.MAXLEN)
|
|
<flags>$(.JOBS)
|
|
;
|
|
$(variant)-runs += out/$(variant) ;
|
|
|
|
# minimize the corpus
|
|
make cmin/$(variant)
|
|
: $(fuzzer)
|
|
oldcorpus/$(variant)
|
|
out/$(variant)
|
|
: @run-fuzzer
|
|
: <location>.
|
|
<flags>-merge=1
|
|
<flags>$(.MAXLEN)
|
|
;
|
|
$(variant)-runs += cmin/$(variant) ;
|
|
|
|
alias $(variant)-run : $($(variant)-runs) ;
|
|
explicit $($(variant)-runs) ;
|
|
}
|
|
|
|
alias run : $(variants)-run ;
|
|
explicit run $(variants)-run ;
|
|
|
|
|
|
rule fuzzer-props ( props * )
|
|
{
|
|
local toolset = [ property.select toolset : $(props) ] ;
|
|
if clang = $(toolset:G=)
|
|
{
|
|
return
|
|
<debug-symbols>on
|
|
<optimization>speed
|
|
<address-sanitizer>on
|
|
<undefined-sanitizer>norecover
|
|
<cxxflags>-fsanitize=fuzzer
|
|
<linkflags>-fsanitize=fuzzer
|
|
# explicitly set BOOST_JSON_STACK_BUFFER_SIZE small so interesting
|
|
# code paths are taken also for small inputs
|
|
# (see https://github.com/boostorg/json/issues/333)
|
|
<define>BOOST_JSON_STACK_BUFFER_SIZE=64
|
|
;
|
|
}
|
|
else
|
|
{
|
|
return <build>no ;
|
|
}
|
|
}
|
|
|
|
|
|
rule run-fuzzer ( target : sources * : props * )
|
|
{
|
|
local flags = [ property.select flags : $(props) ] ;
|
|
FLAGS on $(target) = $(flags:G=) ;
|
|
|
|
local dir = [ path.make [ on $(target) return $(LOCATE) ] ] ;
|
|
dir = $(dir)/$(target:G=) ;
|
|
common.MkDir $(dir) ;
|
|
DEPENDS $(target) : $(dir) ;
|
|
}
|
|
|
|
actions run-fuzzer
|
|
{
|
|
$(.UBSAN_OPTIONS)
|
|
$(>[1]) $(<) $(>[2]) $(>[3]) $(FLAGS)
|
|
}
|
|
|
|
.TOUCH_FILE = [ common.file-touch-command ] ;
|
|
actions untar-corpus
|
|
{
|
|
tar xf $(>) -C $(<:D)
|
|
$(.TOUCH_FILE) $(<)
|
|
}
|