Skip to content

Commit 5c9d408

Browse files
author
MarcoFalke
committed
Merge #18300: fuzz: Add option to merge input dir to test runner
fa3fa27 fuzz: Remove option --export_coverage from test_runner (MarcoFalke) aaaa055 fuzz: Add option to merge input dir to test runner (MarcoFalke) fa4fa88 doc: Remove --disable-ccache from docs (MarcoFalke) Pull request description: This is mainly useful for myself to merge pull requests like bitcoin-core/qa-assets#4 I thought it wouldn't hurt to share the code. Also remove the `--disable-ccache` from the docs to speed up builds when developing fuzzers. Top commit has no ACKs. Tree-SHA512: 818d85a90db86a7f4e8b001cc88342e5b28b02029d2bd4174440b28a8c4cc29b5406bd6348f72ddf909bb3d0f9bf7b1011976f6480e4418c8b7da5ecccae93e8
2 parents e83a1de + fa3fa27 commit 5c9d408

File tree

2 files changed

+37
-19
lines changed

2 files changed

+37
-19
lines changed

doc/fuzzing.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ For macOS you may need to ignore x86 compilation checks when running `make`:
5252
To build Bitcoin Core using AFL instrumentation (this assumes that the
5353
`AFLPATH` was set as above):
5454
```
55-
./configure --disable-ccache --disable-shared --enable-tests --enable-fuzz CC=${AFLPATH}/afl-gcc CXX=${AFLPATH}/afl-g++
55+
./configure --disable-shared --enable-tests --enable-fuzz CC=${AFLPATH}/afl-gcc CXX=${AFLPATH}/afl-g++
5656
export AFL_HARDEN=1
5757
make
5858
```
5959

6060
If you are using clang you will need to substitute `afl-gcc` with `afl-clang`
6161
and `afl-g++` with `afl-clang++`, so the first line above becomes:
6262
```
63-
./configure --disable-ccache --disable-shared --enable-tests --enable-fuzz CC=${AFLPATH}/afl-clang CXX=${AFLPATH}/afl-clang++
63+
./configure --disable-shared --enable-tests --enable-fuzz CC=${AFLPATH}/afl-clang CXX=${AFLPATH}/afl-clang++
6464
```
6565

6666
We disable ccache because we don't want to pollute the ccache with instrumented
@@ -102,7 +102,7 @@ libFuzzer is needed (all found in the `compiler-rt` runtime libraries package).
102102
To build all fuzz targets with libFuzzer, run
103103

104104
```
105-
./configure --disable-ccache --enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=clang CXX=clang++
105+
./configure --enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=clang CXX=clang++
106106
make
107107
```
108108

@@ -134,5 +134,5 @@ clang does not come first in your path.
134134

135135
Full configure that was tested on macOS Catalina with `brew` installed `llvm`:
136136
```
137-
./configure --disable-ccache --enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=/usr/local/opt/llvm/bin/clang CXX=/usr/local/opt/llvm/bin/clang++ --disable-asm
137+
./configure --enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=/usr/local/opt/llvm/bin/clang CXX=/usr/local/opt/llvm/bin/clang++ --disable-asm
138138
```

test/fuzz/test_runner.py

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,17 @@
1414

1515

1616
def main():
17-
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
17+
parser = argparse.ArgumentParser(
18+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
19+
description='''Run the fuzz targets with all inputs from the seed_dir once.''',
20+
)
1821
parser.add_argument(
1922
"-l",
2023
"--loglevel",
2124
dest="loglevel",
2225
default="INFO",
2326
help="log events at this level and higher to the console. Can be set to DEBUG, INFO, WARNING, ERROR or CRITICAL. Passing --loglevel DEBUG will output all logs to console.",
2427
)
25-
parser.add_argument(
26-
'--export_coverage',
27-
action='store_true',
28-
help='If true, export coverage information to files in the seed corpus',
29-
)
3028
parser.add_argument(
3129
'--valgrind',
3230
action='store_true',
@@ -46,6 +44,10 @@ def main():
4644
nargs='*',
4745
help='The target(s) to run. Default is to run all targets.',
4846
)
47+
parser.add_argument(
48+
'--m_dir',
49+
help='Merge inputs from this directory into the seed_dir. Needs /target subdirectory.',
50+
)
4951

5052
args = parser.parse_args()
5153

@@ -122,16 +124,39 @@ def main():
122124
logging.error("subprocess timed out: Currently only libFuzzer is supported")
123125
sys.exit(1)
124126

127+
if args.m_dir:
128+
merge_inputs(
129+
corpus=args.seed_dir,
130+
test_list=test_list_selection,
131+
build_dir=config["environment"]["BUILDDIR"],
132+
merge_dir=args.m_dir,
133+
)
134+
125135
run_once(
126136
corpus=args.seed_dir,
127137
test_list=test_list_selection,
128138
build_dir=config["environment"]["BUILDDIR"],
129-
export_coverage=args.export_coverage,
130139
use_valgrind=args.valgrind,
131140
)
132141

133142

134-
def run_once(*, corpus, test_list, build_dir, export_coverage, use_valgrind):
143+
def merge_inputs(*, corpus, test_list, build_dir, merge_dir):
144+
logging.info("Merge the inputs in the passed dir into the seed_dir. Passed dir {}".format(merge_dir))
145+
for t in test_list:
146+
args = [
147+
os.path.join(build_dir, 'src', 'test', 'fuzz', t),
148+
'-merge=1',
149+
os.path.join(corpus, t),
150+
os.path.join(merge_dir, t),
151+
]
152+
os.makedirs(os.path.join(corpus, t), exist_ok=True)
153+
os.makedirs(os.path.join(merge_dir, t), exist_ok=True)
154+
logging.debug('Run {} with args {}'.format(t, args))
155+
output = subprocess.run(args, check=True, stderr=subprocess.PIPE, universal_newlines=True).stderr
156+
logging.debug('Output: {}'.format(output))
157+
158+
159+
def run_once(*, corpus, test_list, build_dir, use_valgrind):
135160
for t in test_list:
136161
corpus_path = os.path.join(corpus, t)
137162
os.makedirs(corpus_path, exist_ok=True)
@@ -155,13 +180,6 @@ def run_once(*, corpus, test_list, build_dir, export_coverage, use_valgrind):
155180
logging.info(e.stderr)
156181
logging.info("Target \"{}\" failed with exit code {}: {}".format(t, e.returncode, " ".join(args)))
157182
sys.exit(1)
158-
if not export_coverage:
159-
continue
160-
for l in output.splitlines():
161-
if 'INITED' in l:
162-
with open(os.path.join(corpus, t + '_coverage'), 'w', encoding='utf-8') as cov_file:
163-
cov_file.write(l)
164-
break
165183

166184

167185
def parse_test_list(makefile):

0 commit comments

Comments
 (0)