diff options
author | jonathanmetzman <31354670+jonathanmetzman@users.noreply.github.com> | 2021-02-19 11:54:15 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-19 11:54:15 -0800 |
commit | 28b35e36fea5284c45f56d92e06153cc5b502945 (patch) | |
tree | 5c591387c20e1ea129a74fd8070ef4b9711f1e65 /infra | |
parent | bf0720d322057c505eb462bab697d874e27e5e98 (diff) | |
download | oss-fuzz-28b35e36fea5284c45f56d92e06153cc5b502945.tar.gz |
[CIFuzz] Support languages non-C++ projects (e.g. Python projects) (#5222)
Allow use of non-C++ projects by specifying the language in the workflow file.
Fixes #5195
Diffstat (limited to 'infra')
-rw-r--r-- | infra/cifuzz/actions/build_fuzzers/action.yml | 5 | ||||
-rw-r--r-- | infra/cifuzz/actions/run_fuzzers/action.yml | 5 | ||||
-rw-r--r-- | infra/cifuzz/build_fuzzers.py | 12 | ||||
-rw-r--r-- | infra/cifuzz/build_fuzzers_entrypoint.py | 3 | ||||
-rw-r--r-- | infra/cifuzz/build_fuzzers_test.py | 17 | ||||
-rw-r--r-- | infra/cifuzz/config_utils.py | 21 | ||||
-rw-r--r-- | infra/cifuzz/config_utils_test.py | 29 |
7 files changed, 77 insertions, 15 deletions
diff --git a/infra/cifuzz/actions/build_fuzzers/action.yml b/infra/cifuzz/actions/build_fuzzers/action.yml index 2919db40e..35ff010b3 100644 --- a/infra/cifuzz/actions/build_fuzzers/action.yml +++ b/infra/cifuzz/actions/build_fuzzers/action.yml @@ -5,6 +5,10 @@ inputs: oss-fuzz-project-name: description: 'Name of the corresponding OSS-Fuzz project.' required: true + language: + description: 'Programming language project is written in.' + required: false + default: 'c++' dry-run: description: 'If set, run the action without actually reporting a failure.' default: false @@ -25,6 +29,7 @@ runs: image: '../../../build_fuzzers.Dockerfile' env: OSS_FUZZ_PROJECT_NAME: ${{ inputs.oss-fuzz-project-name }} + LANGUAGE: ${{ inputs.language }} DRY_RUN: ${{ inputs.dry-run}} ALLOWED_BROKEN_TARGETS_PERCENTAGE: ${{ inputs.allowed-broken-targets-percentage}} SANITIZER: ${{ inputs.sanitizer }} diff --git a/infra/cifuzz/actions/run_fuzzers/action.yml b/infra/cifuzz/actions/run_fuzzers/action.yml index 582133c74..aec899608 100644 --- a/infra/cifuzz/actions/run_fuzzers/action.yml +++ b/infra/cifuzz/actions/run_fuzzers/action.yml @@ -5,6 +5,10 @@ inputs: oss-fuzz-project-name: description: 'The OSS-Fuzz project name.' required: true + language: + description: 'Programming language project is written in.' + required: false + default: 'c++' fuzz-seconds: description: 'The total time allotted for fuzzing in seconds.' required: true @@ -31,6 +35,7 @@ runs: image: '../../../run_fuzzers.Dockerfile' env: OSS_FUZZ_PROJECT_NAME: ${{ inputs.oss-fuzz-project-name }} + LANGUAGE: ${{ inputs.language }} FUZZ_SECONDS: ${{ inputs.fuzz-seconds }} DRY_RUN: ${{ inputs.dry-run}} SANITIZER: ${{ inputs.sanitizer }} diff --git a/infra/cifuzz/build_fuzzers.py b/infra/cifuzz/build_fuzzers.py index a4342a413..2dae6c986 100644 --- a/infra/cifuzz/build_fuzzers.py +++ b/infra/cifuzz/build_fuzzers.py @@ -77,7 +77,8 @@ class Builder: # pylint: disable=too-many-instance-attributes def build_fuzzers(self): """Moves the source code we want to fuzz into the project builder and builds the fuzzers from that source code. Returns True on success.""" - docker_args = get_common_docker_args(self.config.sanitizer) + docker_args = get_common_docker_args(self.config.sanitizer, + self.config.language) container = utils.get_container_name() if container: @@ -185,7 +186,7 @@ def build_fuzzers(config): return builder.build() -def get_common_docker_args(sanitizer): +def get_common_docker_args(sanitizer, language): """Returns a list of common docker arguments.""" return [ '--cap-add', @@ -199,12 +200,13 @@ def get_common_docker_args(sanitizer): '-e', 'CIFUZZ=True', '-e', - 'FUZZING_LANGUAGE=c++', # FIXME: Add proper support. + 'FUZZING_LANGUAGE=' + language, ] def check_fuzzer_build(out_dir, - sanitizer='address', + sanitizer, + language, allowed_broken_targets_percentage=None): """Checks the integrity of the built fuzzers. @@ -222,7 +224,7 @@ def check_fuzzer_build(out_dir, logging.error('No fuzzers found in out directory: %s.', out_dir) return False - command = get_common_docker_args(sanitizer) + command = get_common_docker_args(sanitizer, language) if allowed_broken_targets_percentage is not None: command += [ diff --git a/infra/cifuzz/build_fuzzers_entrypoint.py b/infra/cifuzz/build_fuzzers_entrypoint.py index 9c4b98215..ddae68197 100644 --- a/infra/cifuzz/build_fuzzers_entrypoint.py +++ b/infra/cifuzz/build_fuzzers_entrypoint.py @@ -75,7 +75,8 @@ def main(): # yapf: disable if build_fuzzers.check_fuzzer_build( out_dir, - sanitizer=config.sanitizer, + config.sanitizer, + config.language, allowed_broken_targets_percentage=config.allowed_broken_targets_percentage ): # yapf: enable diff --git a/infra/cifuzz/build_fuzzers_test.py b/infra/cifuzz/build_fuzzers_test.py index 2d27356d2..2329894b9 100644 --- a/infra/cifuzz/build_fuzzers_test.py +++ b/infra/cifuzz/build_fuzzers_test.py @@ -251,6 +251,9 @@ class BuildFuzzersIntegrationTest(unittest.TestCase): class CheckFuzzerBuildTest(unittest.TestCase): """Tests the check_fuzzer_build function in the cifuzz module.""" + SANITIZER = 'address' + LANGUAGE = 'c++' + def setUp(self): self.tmp_dir_obj = tempfile.TemporaryDirectory() self.test_files_path = os.path.join(self.tmp_dir_obj.name, 'test_files') @@ -262,15 +265,21 @@ class CheckFuzzerBuildTest(unittest.TestCase): def test_correct_fuzzer_build(self): """Checks check_fuzzer_build function returns True for valid fuzzers.""" test_fuzzer_dir = os.path.join(self.test_files_path, 'out') - self.assertTrue(build_fuzzers.check_fuzzer_build(test_fuzzer_dir)) + self.assertTrue( + build_fuzzers.check_fuzzer_build(test_fuzzer_dir, self.SANITIZER, + self.LANGUAGE)) def test_not_a_valid_fuzz_path(self): """Tests that False is returned when a bad path is given.""" - self.assertFalse(build_fuzzers.check_fuzzer_build('not/a/valid/path')) + self.assertFalse( + build_fuzzers.check_fuzzer_build('not/a/valid/path', self.SANITIZER, + self.LANGUAGE)) def test_not_a_valid_fuzzer(self): """Checks a directory that exists but does not have fuzzers is False.""" - self.assertFalse(build_fuzzers.check_fuzzer_build(self.test_files_path)) + self.assertFalse( + build_fuzzers.check_fuzzer_build(self.test_files_path, self.SANITIZER, + self.LANGUAGE)) @mock.patch('helper.docker_run') def test_allow_broken_fuzz_targets_percentage(self, mocked_docker_run): @@ -279,6 +288,8 @@ class CheckFuzzerBuildTest(unittest.TestCase): mocked_docker_run.return_value = 0 test_fuzzer_dir = os.path.join(TEST_FILES_PATH, 'out') build_fuzzers.check_fuzzer_build(test_fuzzer_dir, + self.SANITIZER, + self.LANGUAGE, allowed_broken_targets_percentage='0') self.assertIn('-e ALLOWED_BROKEN_TARGETS_PERCENTAGE=0', ' '.join(mocked_docker_run.call_args[0][0])) diff --git a/infra/cifuzz/config_utils.py b/infra/cifuzz/config_utils.py index fd1871497..7ee3444b3 100644 --- a/infra/cifuzz/config_utils.py +++ b/infra/cifuzz/config_utils.py @@ -62,6 +62,19 @@ def get_project_src_path(workspace): return os.path.join(workspace, path) +DEFAULT_LANGUAGE = 'c++' + + +def _get_language(): + """Returns the project language.""" + # Get language from environment. We took this approach because the convenience + # given to OSS-Fuzz users by not making them specify the language again (and + # getting it from the project.yaml) is outweighed by the complexity in + # implementing this. A lot of the complexity comes from our unittests not + # setting a proper projet at this point. + return os.getenv('LANGUAGE', DEFAULT_LANGUAGE) + + # pylint: disable=too-few-public-methods,too-many-instance-attributes @@ -81,14 +94,20 @@ class BaseConfig: self.dry_run = _is_dry_run() self.sanitizer = _get_sanitizer() self.build_integration_path = os.getenv('BUILD_INTEGRATION_PATH') + self.language = _get_language() event_path = os.getenv('GITHUB_EVENT_PATH') self.is_github = bool(event_path) logging.debug('Is github: %s.', self.is_github) @property + def is_internal(self): + """Returns True if this is an OSS-Fuzz project.""" + return not self.build_integration_path + + @property def platform(self): """Returns the platform CIFuzz is runnning on.""" - if self.build_integration_path: + if not self.is_internal: return self.Platform.EXTERNAL_GITHUB if self.is_github: return self.Platform.INTERNAL_GITHUB diff --git a/infra/cifuzz/config_utils_test.py b/infra/cifuzz/config_utils_test.py index 71e7450fa..6f87bd4c5 100644 --- a/infra/cifuzz/config_utils_test.py +++ b/infra/cifuzz/config_utils_test.py @@ -13,19 +13,38 @@ # limitations under the License. """Module for getting the configuration CIFuzz needs to run.""" import os -import sys import unittest import config_utils - -# pylint: disable=wrong-import-position,import-error -sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) - import test_helpers # pylint: disable=no-self-use +class BaseConfigTest(unittest.TestCase): + """Tests for BaseConfig.""" + + def setUp(self): + test_helpers.patch_environ(self) + + def _create_config(self): + return config_utils.BuildFuzzersConfig() + + def test_language_default(self): + """Tests that the correct default language is set.""" + os.environ['BUILD_INTEGRATION_PATH'] = '/path' + config = self._create_config() + self.assertEqual(config.language, 'c++') + + def test_language(self): + """Tests that the correct language is set.""" + os.environ['BUILD_INTEGRATION_PATH'] = '/path' + language = 'python' + os.environ['LANGUAGE'] = language + config = self._create_config() + self.assertEqual(config.language, language) + + class BuildFuzzersConfigTest(unittest.TestCase): """Tests for BuildFuzzersConfig.""" |