-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Add optional flag --propagage_exit_codes to reproduce #13133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -242,6 +242,8 @@ def main(): # pylint: disable=too-many-branches,too-many-return-statements | |
result = introspector(args) | ||
elif args.command == 'reproduce': | ||
result = reproduce(args) | ||
if args.propagate_exit_codes: | ||
return result | ||
elif args.command == 'shell': | ||
result = shell(args) | ||
elif args.command == 'pull_images': | ||
|
@@ -482,6 +484,14 @@ def get_parser(): # pylint: disable=too-many-statements,too-many-locals | |
reproduce_parser.add_argument('--valgrind', | ||
action='store_true', | ||
help='run with valgrind') | ||
reproduce_parser.add_argument('--propagate_exit_codes', | ||
action='store_true', | ||
default=False, | ||
help='return underlying exit codes instead of True/False.') | ||
reproduce_parser.add_argument('--err_result', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than introduce another flag, perhaps we can just hardcode and document a specific error code for this? i.e. EXIT_CODE_FUZZER_NOT_EXISTS = 199 (probably need to pick an error code here is unlikely to clash generally) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That sounds good to me! I will leave it up to you guys to decide on an exit code default, as I'm sure you're more aware of potential code conflicts. |
||
help='exit code override for missing harness / fuzz targets ' | ||
'(default err_result = 1).', | ||
type=int) | ||
reproduce_parser.add_argument('project', | ||
help='name of the project or path (external)') | ||
reproduce_parser.add_argument('fuzzer_name', help='name of the fuzzer') | ||
|
@@ -717,7 +727,7 @@ def prepare_aarch64_emulation(): | |
subprocess.check_call(['docker', 'buildx', 'use', ARM_BUILDER_NAME]) | ||
|
||
|
||
def docker_run(run_args, print_output=True, architecture='x86_64'): | ||
def docker_run(run_args, print_output=True, architecture='x86_64', propagate_exit_codes=False): | ||
"""Calls `docker run`.""" | ||
platform = 'linux/arm64' if architecture == 'aarch64' else 'linux/amd64' | ||
command = [ | ||
|
@@ -740,12 +750,14 @@ def docker_run(run_args, print_output=True, architecture='x86_64'): | |
if not print_output: | ||
stdout = open(os.devnull, 'w') | ||
|
||
exit_code = 0 | ||
|
||
try: | ||
subprocess.check_call(command, stdout=stdout, stderr=subprocess.STDOUT) | ||
except subprocess.CalledProcessError: | ||
return False | ||
|
||
return True | ||
except subprocess.CalledProcessError as e: | ||
print(f'subprocess command returned a non-zero exit status: {e.returncode}') | ||
exit_code = e.returncode | ||
return exit_code if propagate_exit_codes else exit_code == 0 | ||
|
||
|
||
def docker_build(build_args): | ||
|
@@ -1532,7 +1544,8 @@ def fuzzbench_measure(args): | |
def reproduce(args): | ||
"""Reproduces a specific test case from a specific project.""" | ||
return reproduce_impl(args.project, args.fuzzer_name, args.valgrind, args.e, | ||
args.fuzzer_args, args.testcase_path, args.architecture) | ||
args.fuzzer_args, args.testcase_path, args.architecture, | ||
args.propagate_exit_codes, args.err_result) | ||
|
||
|
||
def reproduce_impl( # pylint: disable=too-many-arguments | ||
|
@@ -1543,14 +1556,16 @@ def reproduce_impl( # pylint: disable=too-many-arguments | |
fuzzer_args, | ||
testcase_path, | ||
architecture='x86_64', | ||
run_function=docker_run, | ||
err_result=False): | ||
propagate_exit_codes=False, | ||
err_result=1, | ||
run_function=docker_run): | ||
"""Reproduces a testcase in the container.""" | ||
|
||
if not check_project_exists(project): | ||
return err_result | ||
return err_result if propagate_exit_codes else False | ||
|
||
if not _check_fuzzer_exists(project, fuzzer_name, architecture): | ||
return err_result | ||
return err_result if propagate_exit_codes else False | ||
|
||
debugger = '' | ||
env = ['HELPER=True', 'ARCHITECTURE=' + architecture] | ||
|
@@ -1578,7 +1593,7 @@ def reproduce_impl( # pylint: disable=too-many-arguments | |
'-runs=100', | ||
] + fuzzer_args | ||
|
||
return run_function(run_args, architecture=architecture) | ||
return run_function(run_args, architecture=architecture, propagate_exit_codes=propagate_exit_codes) | ||
|
||
|
||
def _validate_project_name(project_name): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed this with @jonathanmetzman offline -- this should be fine as default behaviour.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll get to updating this to be default behavior when I get the chance!