diff options
author | Christian Poveda <christian.poveda@ferrous-systems.com> | 2022-09-23 21:36:14 -0500 |
---|---|---|
committer | Christian Poveda <christian.poveda@ferrous-systems.com> | 2022-10-04 20:47:17 -0500 |
commit | 0296f9e86c7756e718b6b82836ce1e09b5f8d08a (patch) | |
tree | b5954c6680b243c0b1671a80ea973ef90877e462 /csmith-fuzzing/driver.py | |
parent | a900f8f863d1313ad76603234aaeea22bb9ba7b3 (diff) |
split the repo into a workspace
remove `clap` dependency :tada:
update the book installation instructions
Diffstat (limited to 'csmith-fuzzing/driver.py')
-rwxr-xr-x | csmith-fuzzing/driver.py | 284 |
1 files changed, 0 insertions, 284 deletions
diff --git a/csmith-fuzzing/driver.py b/csmith-fuzzing/driver.py deleted file mode 100755 index 1d3af540..00000000 --- a/csmith-fuzzing/driver.py +++ /dev/null @@ -1,284 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import re -import shlex -import sys -from subprocess import run, SubprocessError, DEVNULL, PIPE -from tempfile import NamedTemporaryFile - -DESC = """ - -A `csmith` fuzzing driver for `bindgen`. - -Generates random C source files with `csmith` and then passes them to `bindgen` -(via `predicate.py`). If `bindgen` can't emit bindings, `rustc` can't compile -those bindings, or the compiled bindings' layout tests fail, then the driver has -found a bug, and will report the problematic test case to you. - -""" - -parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - description=DESC.strip()) - -parser.add_argument( - "--keep-going", - action="store_true", - help="Do not stop after finding a test case that exhibits a bug in `bindgen`. Instead, keep going.") - -CSMITH_ARGS="\ ---no-checksum \ ---nomain \ ---max-block-size 1 \ ---max-block-depth 1" - -parser.add_argument( - "--csmith-args", - type=str, - default=CSMITH_ARGS, - help="Pass this argument string to `csmith`. By default, very small functions are generated.") - -BINDGEN_ARGS = "--with-derive-partialeq \ ---with-derive-eq \ ---with-derive-partialord \ ---with-derive-ord \ ---with-derive-hash \ ---with-derive-default" - -parser.add_argument( - "--bindgen-args", - type=str, - default=BINDGEN_ARGS, - help="Pass this argument string to `bindgen`. By default, all traits are derived.") - -parser.add_argument( - "--no-creduce", - action="store_false", - dest="creduce", - help="Do not run `creduce` on any buggy test case(s) discovered.") - -################################################################################ - -def cat(path, title=None): - if not title: - title = path - print("-------------------- {} --------------------".format(title)) - print() - print() - run(["cat", path]) - -def decode(f): - return f.decode(encoding="utf-8", errors="ignore") - -def run_logged(cmd): - result = run(cmd, stdin=DEVNULL, stdout=PIPE, stderr=PIPE) - result.stdout = decode(result.stdout) - result.stderr = decode(result.stderr) - if result.returncode != 0: - print() - print() - print("Error: {} exited with code {}".format(cmd, result.returncode)) - print() - print() - for line in result.stdout.splitlines(): - sys.stdout.write("+") - sys.stdout.write(line) - sys.stdout.write("\n") - for line in result.stderr.splitlines(): - sys.stderr.write("+") - sys.stderr.write(line) - sys.stderr.write("\n") - return result - -def main(): - os.environ["RUST_BACKTRACE"] = "full" - args = parser.parse_args() - - bindgen_args = args.bindgen_args - if bindgen_args.find(" -- ") == -1: - bindgen_args = bindgen_args + " -- " - bindgen_args = bindgen_args + " -I{}".format(os.path.abspath(os.path.dirname(sys.argv[0]))) - args.bindgen_args = bindgen_args - - print() - print() - print("Fuzzing `bindgen` with C-Smith...") - print() - print() - - iterations = 0 - while True: - print("\rIteration: {}".format(iterations), end="", flush=True) - iterations += 1 - - input = NamedTemporaryFile(delete=False, prefix="input-", suffix=".h") - input.close() - result = run_logged(["csmith", "-o", input.name] + shlex.split(args.csmith_args)) - if result.returncode != 0: - exit(1) - - predicate_command = [ - "./predicate.py", - "--bindgen-args", - args.bindgen_args, - input.name - ] - result = run_logged(predicate_command) - - if result.returncode != 0: - print() - print() - cat(input.name, title="Failing test case: {}".format(input.name)) - print() - print() - - if args.creduce: - creduce(args, input.name, result) - - print_issue_template(args, input.name, predicate_command, result) - - if args.keep_going: - continue - exit(1) - - os.remove(input.name) - -RUSTC_ERROR_REGEX = re.compile(r".*(error\[.*].*)") -LAYOUT_TEST_FAILURE = re.compile(r".*(test bindgen_test_layout_.* \.\.\. FAILED)") - -def creduce(args, failing_test_case, result): - print() - print() - print("Reducing failing test case with `creduce`...") - - match = re.search(RUSTC_ERROR_REGEX, result.stderr) - if match: - error_msg = match.group(1) - print("...searching for \"{}\".".format(error_msg)) - return creduce_with_predicate_flags( - args, - failing_test_case, - "--bindgen-args '{}' --expect-compile-fail --rustc-grep '{}'".format( - args.bindgen_args, - re.escape(error_msg) - ) - ) - - match = re.search(LAYOUT_TEST_FAILURE, result.stdout) - if match: - layout_failure = match.group(1) - struct_name = layout_failure[len("test bindgen_test_layout_"):layout_failure.rindex(" ... FAILED")] - print("...searching for \"{}\".".format(layout_failure)) - return creduce_with_predicate_flags( - args, - failing_test_case, - "--bindgen-args '{}' --expect-layout-tests-fail --bindings-grep '{}' --layout-tests-grep '{}'".format( - args.bindgen_args, - re.escape(struct_name), - re.escape(layout_failure) - ) - ) - - print("...nevermind, don't know how to `creduce` this bug. Skipping.") - -def creduce_with_predicate_flags(args, failing_test_case, predicate_flags): - predicate = """ -#!/usr/bin/env bash -set -eu -{} {} {} - """.format( - os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "predicate.py")), - predicate_flags, - os.path.basename(failing_test_case) - ) - - print("...and reducing with this script:") - print() - print() - print(predicate) - print() - print() - - predicate_path = failing_test_case + ".predicate.sh" - with open(predicate_path, "w") as p: - p.write(predicate) - os.chmod(predicate_path, 0o755) - - creduce_command = ["creduce", "--n", str(os.cpu_count()), predicate_path, failing_test_case] - print("Running:", creduce_command) - result = run(creduce_command) - if result.returncode == 0: - print() - print() - print("`creduce` reduced the failing test case to:") - print() - print() - cat(failing_test_case) - print() - print() - else: - print() - print() - print("`creduce` failed!") - if not args.keep_going: - sys.exit(1) - -def print_issue_template(args, failing_test_case, predicate_command, result): - test_case_contents = None - with open(failing_test_case, "r") as f: - test_case_contents = f.read() - - print(""" - -! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! -! File this issue at https://github.com/rust-lang/rust-bindgen/issues/new ! -! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! - - --------------- 8< --------------- 8< --------------- 8< --------------- - -This bug was found with `csmith` and `driver.py`. - -### Input Header - -```c -{} -``` - -### `bindgen` Invocation - -``` -$ {} -``` - -### Actual Results - -<details> - -``` -{} -``` - -</details> - -### Expected Results - -`bindgen` emits bindings OK, then `rustc` compiles those bindings OK, then the -compiled bindings' layout tests pass OK. - - --------------- 8< --------------- 8< --------------- 8< --------------- - - <3 <3 <3 Thank you! <3 <3 <3 - """.format( - test_case_contents, - " ".join(map(lambda s: "'{}'".format(s), predicate_command)), - result.stdout + result.stderr - )) - -if __name__ == "__main__": - try: - os.chdir(os.path.abspath(os.path.dirname(sys.argv[0]))) - main() - except KeyboardInterrupt: - exit() |