2020-01-13 23:25:12 +00:00
|
|
|
# Copyright 2020 Google LLC
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
"""Builds and runs specific OSS-Fuzz project's fuzzers for CI tools."""
|
2020-01-29 19:03:43 +00:00
|
|
|
import logging
|
2020-01-13 23:25:12 +00:00
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
|
2020-01-29 19:03:43 +00:00
|
|
|
# pylint: disable=wrong-import-position
|
2020-02-03 23:35:04 +00:00
|
|
|
# pylint: disable=import-error
|
2020-01-29 19:03:43 +00:00
|
|
|
sys.path.append(os.path.join(os.environ['OSS_FUZZ_ROOT'], 'infra', 'cifuzz'))
|
|
|
|
import cifuzz
|
|
|
|
|
|
|
|
# TODO: Turn default logging to INFO when CIFuzz is stable
|
|
|
|
logging.basicConfig(
|
|
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
|
|
level=logging.DEBUG)
|
|
|
|
|
2020-01-13 23:25:12 +00:00
|
|
|
|
|
|
|
def main():
|
2020-01-29 19:03:43 +00:00
|
|
|
"""Runs OSS-Fuzz project's fuzzers for CI tools.
|
|
|
|
This script is used to kick off the Github Actions CI tool. It is the
|
|
|
|
entrypoint of the Dockerfile in this directory. This action can be added to
|
|
|
|
any OSS-Fuzz project's workflow that uses Github.
|
|
|
|
|
|
|
|
Required environment variables:
|
|
|
|
PROJECT_NAME: The name of OSS-Fuzz project.
|
|
|
|
FUZZ_TIME: The length of time in seconds that fuzzers are to be run.
|
|
|
|
GITHUB_REPOSITORY: The name of the Github repo that called this script.
|
|
|
|
GITHUB_SHA: The commit SHA that triggered this script.
|
2020-01-31 23:31:18 +00:00
|
|
|
GITHUB_REF: The pull request reference that triggered this script.
|
|
|
|
GITHUB_EVENT_NAME: The name of the hook event that triggered this script.
|
2020-01-29 19:03:43 +00:00
|
|
|
|
|
|
|
Returns:
|
|
|
|
0 on success or 1 on Failure.
|
|
|
|
"""
|
|
|
|
oss_fuzz_project_name = os.environ.get('PROJECT_NAME')
|
|
|
|
fuzz_seconds = int(os.environ.get('FUZZ_SECONDS', 360))
|
|
|
|
github_repo_name = os.path.basename(os.environ.get('GITHUB_REPOSITORY'))
|
2020-01-31 23:31:18 +00:00
|
|
|
pr_ref = os.environ.get('GITHUB_REF')
|
2020-01-29 19:03:43 +00:00
|
|
|
commit_sha = os.environ.get('GITHUB_SHA')
|
2020-01-31 23:31:18 +00:00
|
|
|
event = os.environ.get('GITHUB_EVENT_NAME')
|
2020-01-29 19:03:43 +00:00
|
|
|
workspace = os.environ.get('GITHUB_WORKSPACE')
|
2020-02-03 23:35:04 +00:00
|
|
|
|
|
|
|
# Check if failures should not be reported.
|
|
|
|
dry_run = (os.environ.get('DRY_RUN').lower() == 'true')
|
|
|
|
|
|
|
|
# The default return code when an error occurs.
|
|
|
|
error_code = 1
|
|
|
|
if dry_run:
|
|
|
|
# A testcase file is required in order for CIFuzz to surface bugs.
|
|
|
|
# If the file does not exist, the action will crash attempting to upload it.
|
|
|
|
# The dry run needs this file because it is set to upload a test case both
|
|
|
|
# on successful runs and on failures.
|
|
|
|
out_dir = os.path.join(workspace, 'out')
|
|
|
|
os.makedirs(out_dir, exist_ok=True)
|
|
|
|
file_handle = open(os.path.join(out_dir, 'testcase'), 'w')
|
|
|
|
file_handle.write('No bugs detected.')
|
|
|
|
file_handle.close()
|
|
|
|
|
|
|
|
# Sets the default return code on error to success.
|
|
|
|
error_code = 0
|
|
|
|
|
2020-01-29 19:03:43 +00:00
|
|
|
if not workspace:
|
|
|
|
logging.error('This script needs to be run in the Github action context.')
|
2020-02-03 23:35:04 +00:00
|
|
|
return error_code
|
2020-01-13 23:25:12 +00:00
|
|
|
|
2020-01-31 23:31:18 +00:00
|
|
|
if event == 'push' and not cifuzz.build_fuzzers(
|
|
|
|
oss_fuzz_project_name, github_repo_name, workspace,
|
|
|
|
commit_sha=commit_sha):
|
|
|
|
logging.error('Error building fuzzers for project %s with commit %s.',
|
|
|
|
oss_fuzz_project_name, commit_sha)
|
2020-02-03 23:35:04 +00:00
|
|
|
return error_code
|
2020-01-31 23:31:18 +00:00
|
|
|
if event == 'pull_request' and not cifuzz.build_fuzzers(
|
|
|
|
oss_fuzz_project_name, github_repo_name, workspace, pr_ref=pr_ref):
|
|
|
|
logging.error('Error building fuzzers for project %s with pull request %s.',
|
|
|
|
oss_fuzz_project_name, pr_ref)
|
2020-02-03 23:35:04 +00:00
|
|
|
return error_code
|
2020-01-13 23:25:12 +00:00
|
|
|
|
|
|
|
# Run the specified project's fuzzers from the build.
|
2020-01-29 19:03:43 +00:00
|
|
|
run_status, bug_found = cifuzz.run_fuzzers(oss_fuzz_project_name,
|
2020-01-31 23:31:18 +00:00
|
|
|
fuzz_seconds, workspace)
|
2020-01-29 19:03:43 +00:00
|
|
|
if not run_status:
|
|
|
|
logging.error('Error occured while running fuzzers for project %s.',
|
|
|
|
oss_fuzz_project_name)
|
2020-02-03 23:35:04 +00:00
|
|
|
return error_code
|
2020-01-29 19:03:43 +00:00
|
|
|
if bug_found:
|
|
|
|
logging.info('Bug found.')
|
2020-02-03 23:35:04 +00:00
|
|
|
if not dry_run:
|
|
|
|
# Return 2 when a bug was found by a fuzzer causing the CI to fail.
|
|
|
|
return 2
|
2020-01-13 23:25:12 +00:00
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
sys.exit(main())
|