mirror of
https://github.com/radareorg/radare2.git
synced 2024-10-06 18:13:46 +00:00
add libFuzzer integration, r_run_parseline test ##fuzz
This commit is contained in:
parent
52b9b7b703
commit
e319a7a71e
5
.gitignore
vendored
5
.gitignore
vendored
@ -140,4 +140,7 @@ libr/include/sdb
|
||||
**/d/*.out
|
||||
**/d/*.inc
|
||||
# Artifacts
|
||||
/dist/artifacts
|
||||
/dist/artifacts
|
||||
# libFuzzer
|
||||
crash-*
|
||||
corpus*
|
||||
|
@ -622,6 +622,10 @@ R_API bool r_sys_aslr(int val) {
|
||||
|
||||
#if __UNIX__ && HAVE_SYSTEM
|
||||
R_API int r_sys_cmd_str_full(const char *cmd, const char *input, int ilen, char **output, int *len, char **sterr) {
|
||||
if (!r_sandbox_check (R_SANDBOX_GRAIN_EXEC)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char *mysterr = NULL;
|
||||
if (!sterr) {
|
||||
sterr = &mysterr;
|
||||
|
@ -645,6 +645,7 @@ if get_option('use_webui')
|
||||
endif
|
||||
|
||||
subdir('test/unit')
|
||||
subdir('test/fuzz')
|
||||
|
||||
install_data(
|
||||
'doc/fortunes.fun',
|
||||
|
@ -47,4 +47,5 @@ option('want_ptrace_wrap', type: 'boolean', value: true)
|
||||
option('nogpl', type: 'boolean', value: false)
|
||||
option('use_webui', type: 'boolean', value: true, description: 'install different WebUIs for radare2')
|
||||
option('enable_tests', type: 'boolean', value: true, description: 'Build unit tests in test/unit')
|
||||
option('enable_libfuzzer', type: 'boolean', value: false, description: 'Build libFuzzer targets in test/fuzz')
|
||||
option('enable_r2r', type: 'boolean', value: true, description: 'Build r2r executable for regression ')
|
||||
|
11
sys/meson.py
11
sys/meson.py
@ -168,6 +168,8 @@ def build(args):
|
||||
options.append('-Duse_webui=true')
|
||||
if args.local:
|
||||
options.append('-Dlocal=true')
|
||||
if args.fuzz:
|
||||
options.append('-Denable_libfuzzer=true')
|
||||
if not os.path.exists(r2_builddir):
|
||||
meson('setup', builddir=r2_builddir, prefix=args.prefix, backend=args.backend,
|
||||
release=args.release, shared=args.shared, options=options)
|
||||
@ -198,6 +200,8 @@ def main():
|
||||
parser.add_argument('--sanitize', nargs='?',
|
||||
const='address,undefined,signed-integer-overflow', metavar='sanitizers',
|
||||
help='Build radare2 with sanitizer support (default: %(const)s)')
|
||||
parser.add_argument('--fuzz', action='store_true',
|
||||
help='Build radare2 with libFuzzer support')
|
||||
parser.add_argument('--project', action='store_true',
|
||||
help='Create a visual studio project and do not build.')
|
||||
parser.add_argument('--release', action='store_true',
|
||||
@ -237,15 +241,18 @@ def main():
|
||||
if os.uname().sysname == 'OpenBSD':
|
||||
log.error("Sanitizers unsupported under OpenBSD")
|
||||
sys.exit(1)
|
||||
sanitizers = args.sanitize
|
||||
if args.fuzz and 'fuzzer' not in sanitizers:
|
||||
sanitizers = "fuzzer," + sanitizers
|
||||
cflags = os.environ.get('CFLAGS')
|
||||
if not cflags:
|
||||
cflags = ''
|
||||
os.environ['CFLAGS'] = cflags + ' -fsanitize=' + args.sanitize
|
||||
os.environ['CFLAGS'] = cflags + ' -fsanitize=' + sanitizers
|
||||
if os.uname().sysname != 'Darwin':
|
||||
ldflags = os.environ.get('LDFLAGS')
|
||||
if not ldflags:
|
||||
ldflags = ''
|
||||
os.environ['LDFLAGS'] = ldflags + ' -fsanitize=' + args.sanitize
|
||||
os.environ['LDFLAGS'] = ldflags + ' -fsanitize=' + sanitizers
|
||||
|
||||
# Check arguments
|
||||
if args.pull:
|
||||
|
61
test/fuzz/README.md
Normal file
61
test/fuzz/README.md
Normal file
@ -0,0 +1,61 @@
|
||||
# libFuzzer tests
|
||||
|
||||
## Setup
|
||||
|
||||
Get libFuzzer-capable clang
|
||||
|
||||
```shell
|
||||
# Linux
|
||||
export CC=clang-14
|
||||
# macOS
|
||||
export CC="$(brew --prefix llvm@14)/bin/clang"
|
||||
```
|
||||
|
||||
Clean project
|
||||
|
||||
```shell
|
||||
rm -rf build
|
||||
```
|
||||
|
||||
Build project with libFuzzer and sanitizers
|
||||
|
||||
```shell
|
||||
# If you want to debug crashes
|
||||
export CFLAGS="-g"
|
||||
# Build project with test/fuzz
|
||||
python3 ./sys/meson.py --fuzz --sanitize address,leak
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
Refer to https://llvm.org/docs/LibFuzzer.html
|
||||
|
||||
**Show help**
|
||||
|
||||
```
|
||||
./build/test/fuzz/fuzz_r_run_parseline -help=1
|
||||
```
|
||||
|
||||
**Run fuzzer**
|
||||
|
||||
```
|
||||
mkdir corpus_parseline
|
||||
./build/test/fuzz/fuzz_r_run_parseline \
|
||||
-workers=1 -runs=50000 -timeout=3 \
|
||||
corpus_parseline
|
||||
```
|
||||
|
||||
**Replay crashes**
|
||||
|
||||
```
|
||||
./build/test/fuzz/fuzz_r_run_parseline crash-*
|
||||
```
|
||||
|
||||
## Adding a new target
|
||||
|
||||
- add your test to /test/fuzz/meson.build
|
||||
- add `/test/fuzz/fuzz_<name>.c` file
|
||||
- add system setup to `LLVMFuzzerInitialize` (disable logging, enable sandbox, etc)
|
||||
- add fuzz target to `LLVMFuzzerTestOneInput`
|
||||
- make sure input is short (ideally no longer than 256 bytes)
|
||||
- make sure no memory leaks are present
|
32
test/fuzz/fuzz_r_run_parseline.c
Normal file
32
test/fuzz/fuzz_r_run_parseline.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <r_types.h>
|
||||
#include <r_socket.h>
|
||||
#include <r_util/r_log.h>
|
||||
#include <r_util/r_sys.h>
|
||||
#include <r_util/r_sandbox.h>
|
||||
|
||||
int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
||||
r_sys_clearenv ();
|
||||
r_sandbox_enable (true);
|
||||
r_sandbox_grain (R_SANDBOX_GRAIN_NONE);
|
||||
r_log_set_quiet (true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const ut8 *data, size_t len) {
|
||||
r_sys_clearenv ();
|
||||
r_sandbox_enable (true);
|
||||
|
||||
char *str = malloc (len + 1);
|
||||
memcpy (str, data, len);
|
||||
str[len] = 0;
|
||||
|
||||
RRunProfile *p = r_run_new (NULL);
|
||||
r_run_parseline (p, str);
|
||||
free (str);
|
||||
r_run_free (p);
|
||||
r_sys_clearenv ();
|
||||
|
||||
return 0;
|
||||
}
|
17
test/fuzz/meson.build
Normal file
17
test/fuzz/meson.build
Normal file
@ -0,0 +1,17 @@
|
||||
if get_option('enable_libfuzzer')
|
||||
targets = [
|
||||
'r_run_parseline',
|
||||
]
|
||||
|
||||
foreach target : targets
|
||||
exe = executable('fuzz_@0@'.format(target), 'fuzz_@0@.c'.format(target),
|
||||
include_directories: [platform_inc],
|
||||
dependencies: [
|
||||
r_util_dep,
|
||||
r_socket_dep,
|
||||
],
|
||||
install: false,
|
||||
implicit_include_directories: false,
|
||||
)
|
||||
endforeach
|
||||
endif
|
Loading…
Reference in New Issue
Block a user