diff --git a/.travis.yml b/.travis.yml index d1083ce25..5d0f44be7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,4 +10,33 @@ before_install: install: - pip install -r infra/travis/requirements.txt +matrix: + include: + - name: "libfuzzer address x86_64" + env: + - TRAVIS_ENGINE=libfuzzer + - TRAVIS_SANITIZER=address + - TRAVIS_ARCHITECTURE=x86_64 + - name: "libfuzzer memory x86_64" + env: + - TRAVIS_ENGINE=libfuzzer + - TRAVIS_SANITIZER=memory + - TRAVIS_ARCHITECTURE=x86_64 + - name: "libfuzzer undefined x86_64" + env: + - TRAVIS_SANITIZER=undefined + - TRAVIS_ENGINE=libfuzzer + - TRAVIS_ARCHITECTURE=x86_64 + - name: "afl address x86_64" + env: + - TRAVIS_ENGINE=afl + - TRAVIS_SANITIZER=address + - TRAVIS_ARCHITECTURE=x86_64 + - name: "none address x86_64" + env: + - TRAVIS_ENGINE=none + - TRAVIS_SANITIZER=address + - TRAVIS_ARCHITECTURE=x86_64 + # TODO(metzman) Add a libfuzzer address i386 job. + script: ./infra/travis/travis_build.py diff --git a/infra/travis/travis_build.py b/infra/travis/travis_build.py index eb190ea6e..32b2358fd 100755 --- a/infra/travis/travis_build.py +++ b/infra/travis/travis_build.py @@ -23,7 +23,8 @@ import re import subprocess import yaml -DEFAULT_FUZZING_ENGINES = ['afl', 'libfuzzer'] +DEFAULT_ARCHITECTURES = ['x86_64'] +DEFAULT_ENGINES = ['afl', 'libfuzzer'] DEFAULT_SANITIZERS = ['address', 'undefined'] @@ -53,57 +54,62 @@ def execute_helper_command(helper_command): subprocess.check_call(command) -def build_fuzzers(project, sanitizer, engine, architecture='x86_64'): +def build_fuzzers(project, engine, sanitizer, architecture): """Execute helper.py's build_fuzzers command on |project|. Build the fuzzers - with |sanitizer| and |engine|.""" + with |engine| and |sanitizer| for |architecture|.""" execute_helper_command([ 'build_fuzzers', project, '--engine', engine, '--sanitizer', sanitizer, '--architecture', architecture ]) -def check_build(project, sanitizer, engine, architecture='x86_64'): +def check_build(project, engine, sanitizer, architecture): """Execute helper.py's check_build command on |project|, assuming it was most - recently built with |sanitizer| and |engine|.""" + recently built with |engine| and |sanitizer| for |architecture|.""" execute_helper_command([ 'check_build', project, '--engine', engine, '--sanitizer', sanitizer, '--architecture', architecture ]) +def should_build(project_yaml): + """Is the build specified by travis enabled in the |project_yaml|?""" + def is_enabled(env_var, yaml_name, defaults): + """Is the value of |env_var| enabled in |project_yaml| (in the |yaml_name| + section)? Uses |defaults| if |yaml_name| section is unspecified.""" + return os.getenv(env_var) in project_yaml.get(yaml_name, defaults) + + return (is_enabled('TRAVIS_ENGINE', 'fuzzing_engines', DEFAULT_ENGINES) and + is_enabled('TRAVIS_SANITIZER', 'sanitizers', DEFAULT_SANITIZERS) and + is_enabled( + 'TRAVIS_ARCHITECTURE', 'architectures', DEFAULT_ARCHITECTURES)) + def build_project(project): - """Do all build of |project|.""" - print('Building project', project) + """Do the build of |project| that is specified by the TRAVIS_* environment + variables (TRAVIS_SANITIZER, TRAVIS_ENGINE, and TRAVIS_ARCHITECTURE).""" root = get_oss_fuzz_root() project_yaml_path = os.path.join(root, 'projects', project, 'project.yaml') with open(project_yaml_path) as fp: project_yaml = yaml.safe_load(fp) if project_yaml.get('disabled', False): + print('Project {0} is disabled, not building.'.format(project)) return - fuzzing_engines = project_yaml.get('fuzzing_engines', DEFAULT_FUZZING_ENGINES) - if 'none' in fuzzing_engines: - # no engine builds always use ASAN. - build_fuzzers(project, 'address', 'none') + engine = os.getenv('TRAVIS_ENGINE') + sanitizer = os.getenv('TRAVIS_SANITIZER') + architecture = os.getenv('TRAVIS_ARCHITECTURE') + + if not should_build(project_yaml): + print(('Specified build: engine: {0}, sanitizer: {1}, architecture: {2} ' + 'not enabled for this project: {3}. Not building.').format( + engine, sanitizer, architecture, project)) + return - if 'afl' in fuzzing_engines: - # AFL builds always use ASAN. - build_fuzzers(project, 'address', 'afl') - check_build(project, 'address', 'afl') - - if 'libfuzzer' not in fuzzing_engines: - return - - for sanitizer in project_yaml.get('sanitizers', DEFAULT_SANITIZERS): - build_fuzzers(project, sanitizer, 'libfuzzer') - check_build(project, sanitizer, 'libfuzzer') - - if 'i386' in project_yaml.get('architectures', []): - # i386 builds always use libFuzzer and ASAN. - build_fuzzers(project, 'address', 'libfuzzer', 'i386') - check_build(project, 'address', 'libfuzzer', 'i386') + print('Building project', project) + build_fuzzers(project, engine, sanitizer, architecture) + check_build(project, engine, sanitizer, architecture) def main():