aboutsummaryrefslogtreecommitdiff
path: root/infra/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'infra/utils.py')
-rw-r--r--infra/utils.py122
1 files changed, 122 insertions, 0 deletions
diff --git a/infra/utils.py b/infra/utils.py
new file mode 100644
index 000000000..8f0e4e287
--- /dev/null
+++ b/infra/utils.py
@@ -0,0 +1,122 @@
+# 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.
+"""Utilities for OSS-Fuzz infrastructure."""
+
+import os
+import re
+import stat
+import subprocess
+
+import helper
+
+ALLOWED_FUZZ_TARGET_EXTENSIONS = ['', '.exe']
+FUZZ_TARGET_SEARCH_STRING = 'LLVMFuzzerTestOneInput'
+VALID_TARGET_NAME = re.compile(r'^[a-zA-Z0-9_-]+$')
+
+
+def chdir_to_root():
+ """Changes cwd to OSS-Fuzz root directory."""
+ # Change to oss-fuzz main directory so helper.py runs correctly.
+ if os.getcwd() != helper.OSSFUZZ_DIR:
+ os.chdir(helper.OSSFUZZ_DIR)
+
+
+def execute(command, location=None, check_result=False):
+ """ Runs a shell command in the specified directory location.
+
+ Args:
+ command: The command as a list to be run.
+ location: The directory the command is run in.
+ check_result: Should an exception be thrown on failed command.
+
+ Returns:
+ The stdout of the command, the error code.
+
+ Raises:
+ RuntimeError: running a command resulted in an error.
+ """
+
+ if not location:
+ location = os.getcwd()
+ process = subprocess.Popen(command, stdout=subprocess.PIPE, cwd=location)
+ out, err = process.communicate()
+ if check_result and (process.returncode or err):
+ raise RuntimeError('Error: %s\n Command: %s\n Return code: %s\n Out: %s' %
+ (err, command, process.returncode, out))
+ if out is not None:
+ out = out.decode('ascii').rstrip()
+ return out, process.returncode
+
+
+def get_fuzz_targets(path):
+ """Get list of fuzz targets in a directory.
+
+ Args:
+ path: A path to search for fuzz targets in.
+
+ Returns:
+ A list of paths to fuzzers or an empty list if None.
+ """
+ if not os.path.exists(path):
+ return []
+ fuzz_target_paths = []
+ for root, _, _ in os.walk(path):
+ for filename in os.listdir(path):
+ file_path = os.path.join(root, filename)
+ if is_fuzz_target_local(file_path):
+ fuzz_target_paths.append(file_path)
+
+ return fuzz_target_paths
+
+
+def get_container_name():
+ """Gets the name of the current docker container you are in.
+ /proc/self/cgroup can be used to check control groups e.g. Docker.
+ See: https://docs.docker.com/config/containers/runmetrics/ for more info.
+
+ Returns:
+ Container name or None if not in a container.
+ """
+ with open('/proc/self/cgroup') as file_handle:
+ if 'docker' not in file_handle.read():
+ return None
+ with open('/etc/hostname') as file_handle:
+ return file_handle.read().strip()
+
+
+def is_fuzz_target_local(file_path):
+ """Returns whether |file_path| is a fuzz target binary (local path).
+ Copied from clusterfuzz src/python/bot/fuzzers/utils.py
+ with slight modifications.
+ """
+ filename, file_extension = os.path.splitext(os.path.basename(file_path))
+ if not VALID_TARGET_NAME.match(filename):
+ # Check fuzz target has a valid name (without any special chars).
+ return False
+
+ if file_extension not in ALLOWED_FUZZ_TARGET_EXTENSIONS:
+ # Ignore files with disallowed extensions (to prevent opening e.g. .zips).
+ return False
+
+ if not os.path.exists(file_path) or not os.access(file_path, os.X_OK):
+ return False
+
+ if filename.endswith('_fuzzer'):
+ return True
+
+ if os.path.exists(file_path) and not stat.S_ISREG(os.stat(file_path).st_mode):
+ return False
+
+ with open(file_path, 'rb') as file_handle:
+ return file_handle.read().find(FUZZ_TARGET_SEARCH_STRING.encode()) != -1