aboutsummaryrefslogtreecommitdiff
path: root/infra/helper.py
diff options
context:
space:
mode:
Diffstat (limited to 'infra/helper.py')
-rwxr-xr-xinfra/helper.py110
1 files changed, 63 insertions, 47 deletions
diff --git a/infra/helper.py b/infra/helper.py
index 8a0a640c1..e24df4ded 100755
--- a/infra/helper.py
+++ b/infra/helper.py
@@ -22,7 +22,6 @@ from multiprocessing.dummy import Pool as ThreadPool
import argparse
import datetime
import errno
-import multiprocessing
import os
import pipes
import re
@@ -59,15 +58,61 @@ CORPUS_BACKUP_URL_FORMAT = (
PROJECT_LANGUAGE_REGEX = re.compile(r'\s*language\s*:\s*([^\s]+)')
# Languages from project.yaml that have code coverage support.
-LANGUAGES_WITH_COVERAGE_SUPPORT = ['c', 'c++', 'go']
+LANGUAGES_WITH_COVERAGE_SUPPORT = ['c', 'c++', 'go', 'rust']
+# pylint: disable=too-many-lines
-def main(): # pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
+
+def main(): # pylint: disable=too-many-branches,too-many-return-statements
"""Get subcommand from program arguments and do it."""
os.chdir(OSS_FUZZ_DIR)
if not os.path.exists(BUILD_DIR):
os.mkdir(BUILD_DIR)
+ args = parse_args()
+
+ # We have different default values for `sanitizer` depending on the `engine`.
+ # Some commands do not have `sanitizer` argument, so `hasattr` is necessary.
+ if hasattr(args, 'sanitizer') and not args.sanitizer:
+ if args.engine == 'dataflow':
+ args.sanitizer = 'dataflow'
+ else:
+ args.sanitizer = 'address'
+
+ if args.command == 'generate':
+ return generate(args)
+ if args.command == 'build_image':
+ return build_image(args)
+ if args.command == 'build_fuzzers':
+ return build_fuzzers(args)
+ if args.command == 'check_build':
+ return check_build(args)
+ if args.command == 'download_corpora':
+ return download_corpora(args)
+ if args.command == 'run_fuzzer':
+ return run_fuzzer(args)
+ if args.command == 'coverage':
+ return coverage(args)
+ if args.command == 'reproduce':
+ return reproduce(args)
+ if args.command == 'shell':
+ return shell(args)
+ if args.command == 'pull_images':
+ return pull_images(args)
+
+ return 0
+
+
+def parse_args(args=None):
+ """Parses args using argparser and returns parsed args."""
+ # Use default argument None for args so that in production, argparse does its
+ # normal behavior, but unittesting is easier.
+ parser = get_parser()
+ return parser.parse_args(args)
+
+
+def get_parser(): # pylint: disable=too-many-statements
+ """Returns an argparse parser."""
parser = argparse.ArgumentParser('helper.py', description='oss-fuzz helpers')
subparsers = parser.add_subparsers(dest='command')
@@ -112,8 +157,9 @@ def main(): # pylint: disable=too-many-branches,too-many-return-statements,too-
_add_engine_args(
check_build_parser,
choices=['libfuzzer', 'afl', 'honggfuzz', 'dataflow', 'none'])
- _add_sanitizer_args(check_build_parser,
- choices=['address', 'memory', 'undefined', 'dataflow'])
+ _add_sanitizer_args(
+ check_build_parser,
+ choices=['address', 'memory', 'undefined', 'dataflow', 'thread'])
_add_environment_args(check_build_parser)
check_build_parser.add_argument('project_name', help='name of the project')
check_build_parser.add_argument('fuzzer_name',
@@ -189,39 +235,7 @@ def main(): # pylint: disable=too-many-branches,too-many-return-statements,too-
_add_environment_args(shell_parser)
subparsers.add_parser('pull_images', help='Pull base images.')
-
- args = parser.parse_args()
-
- # We have different default values for `sanitizer` depending on the `engine`.
- # Some commands do not have `sanitizer` argument, so `hasattr` is necessary.
- if hasattr(args, 'sanitizer') and not args.sanitizer:
- if args.engine == 'dataflow':
- args.sanitizer = 'dataflow'
- else:
- args.sanitizer = 'address'
-
- if args.command == 'generate':
- return generate(args)
- if args.command == 'build_image':
- return build_image(args)
- if args.command == 'build_fuzzers':
- return build_fuzzers(args)
- if args.command == 'check_build':
- return check_build(args)
- if args.command == 'download_corpora':
- return download_corpora(args)
- if args.command == 'run_fuzzer':
- return run_fuzzer(args)
- if args.command == 'coverage':
- return coverage(args)
- if args.command == 'reproduce':
- return reproduce(args)
- if args.command == 'shell':
- return shell(args)
- if args.command == 'pull_images':
- return pull_images(args)
-
- return 0
+ return parser
def is_base_image(image_name):
@@ -335,7 +349,7 @@ def _add_engine_args(parser,
def _add_sanitizer_args(parser,
choices=('address', 'memory', 'undefined', 'coverage',
- 'dataflow')):
+ 'dataflow', 'thread')):
"""Add common sanitizer args."""
parser.add_argument(
'--sanitizer',
@@ -632,7 +646,7 @@ def check_build(args):
]
if args.fuzzer_name:
- run_args += ['test_one', os.path.join('/out', args.fuzzer_name)]
+ run_args += ['test_one.py', args.fuzzer_name]
else:
run_args.append('test_all.py')
@@ -672,14 +686,14 @@ def _get_latest_corpus(project_name, fuzz_target, base_corpus_dir):
fuzz_target=fuzz_target)
command = ['gsutil', 'ls', corpus_backup_url]
- corpus_listing = subprocess.Popen(command,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- output, error = corpus_listing.communicate()
+ # Don't capture stderr. We want it to print in real time, in case gsutil is
+ # asking for two-factor authentication.
+ corpus_listing = subprocess.Popen(command, stdout=subprocess.PIPE)
+ output, _ = corpus_listing.communicate()
# Some fuzz targets (e.g. new ones) may not have corpus yet, just skip those.
if corpus_listing.returncode:
- print('WARNING: corpus for {0} not found:\n{1}'.format(fuzz_target, error),
+ print('WARNING: corpus for {0} not found:\n'.format(fuzz_target),
file=sys.stderr)
return
@@ -736,7 +750,7 @@ def download_corpora(args):
print('Downloading corpora for %s project to %s' %
(args.project_name, corpus_dir))
- thread_pool = ThreadPool(multiprocessing.cpu_count())
+ thread_pool = ThreadPool()
return all(thread_pool.map(_download_for_single_target, fuzz_targets))
@@ -956,9 +970,11 @@ def shell(args):
'FUZZING_ENGINE=' + args.engine,
'SANITIZER=' + args.sanitizer,
'ARCHITECTURE=' + args.architecture,
- 'FUZZING_LANGUAGE=' + _get_project_language(args.project_name),
]
+ if args.project_name != 'base-runner-debug':
+ env.append('FUZZING_LANGUAGE=' + _get_project_language(args.project_name))
+
if args.e:
env += args.e