aboutsummaryrefslogtreecommitdiff
path: root/contrib/bc/scripts/afl.py
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bc/scripts/afl.py')
-rwxr-xr-xcontrib/bc/scripts/afl.py245
1 files changed, 0 insertions, 245 deletions
diff --git a/contrib/bc/scripts/afl.py b/contrib/bc/scripts/afl.py
deleted file mode 100755
index c4312ce84f83..000000000000
--- a/contrib/bc/scripts/afl.py
+++ /dev/null
@@ -1,245 +0,0 @@
-#! /usr/bin/python3 -B
-#
-# SPDX-License-Identifier: BSD-2-Clause
-#
-# Copyright (c) 2018-2021 Gavin D. Howard and contributors.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-
-import os
-import sys
-import shutil
-import subprocess
-
-
-# Print the usage and exit with an error.
-def usage():
- print("usage: {} [--asan] dir [results_dir [exe options...]]".format(script))
- print(" The valid values for dir are: 'bc1', 'bc2', 'bc3', and 'dc'.")
- sys.exit(1)
-
-
-# Check for a crash.
-# @param exebase The calculator that crashed.
-# @param out The file to copy the crash file to.
-# @param error The error code (negative).
-# @param file The crash file.
-# @param type The type of run that caused the crash. This is just a string
-# that would make sense to the user.
-# @param test The contents of the crash file, or which line caused the crash
-# for a run through stdin.
-def check_crash(exebase, out, error, file, type, test):
- if error < 0:
- print("\n{} crashed ({}) on {}:\n".format(exebase, -error, type))
- print(" {}".format(test))
- print("\nCopying to \"{}\"".format(out))
- shutil.copy2(file, out)
- print("\nexiting...")
- sys.exit(error)
-
-
-# Runs a test. This function is used to ensure that if a test times out, it is
-# discarded. Otherwise, some tests result in incredibly long runtimes. We need
-# to ignore those.
-#
-# @param cmd The command to run.
-# @param exebase The calculator to test.
-# @param tout The timeout to use.
-# @param indata The data to push through stdin for the test.
-# @param out The file to copy the test file to if it causes a crash.
-# @param file The test file.
-# @param type The type of test. This is just a string that would make sense
-# to the user.
-# @param test The test. It could be an entire file, or just one line.
-# @param environ The environment to run the command under.
-def run_test(cmd, exebase, tout, indata, out, file, type, test, environ=None):
- try:
- p = subprocess.run(cmd, timeout=tout, input=indata, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE, env=environ)
- check_crash(exebase, out, p.returncode, file, type, test)
- except subprocess.TimeoutExpired:
- print("\n {} timed out. Continuing...\n".format(exebase))
-
-
-# Creates and runs a test. This basically just takes a file, runs it through the
-# appropriate calculator as a whole file, then runs it through the calculator
-# using stdin.
-# @param file The file to test.
-# @param tout The timeout to use.
-# @param environ The environment to run under.
-def create_test(file, tout, environ=None):
-
- print(" {}".format(file))
-
- base = os.path.basename(file)
-
- if base == "README.txt":
- return
-
- with open(file, "rb") as f:
- lines = f.readlines()
-
- print(" Running whole file...")
-
- run_test(exe + [ file ], exebase, tout, halt.encode(), out, file, "file", file, environ)
-
- print(" Running file through stdin...")
-
- with open(file, "rb") as f:
- content = f.read()
-
- run_test(exe, exebase, tout, content, out, file,
- "running {} through stdin".format(file), file, environ)
-
-
-# Get the children of a directory.
-# @param dir The directory to get the children of.
-# @param get_files True if files should be gotten, false if directories should
-# be gotten.
-def get_children(dir, get_files):
- dirs = []
- with os.scandir(dir) as it:
- for entry in it:
- if not entry.name.startswith('.') and \
- ((entry.is_dir() and not get_files) or \
- (entry.is_file() and get_files)):
- dirs.append(entry.name)
- dirs.sort()
- return dirs
-
-
-# Returns the correct executable name for the directory under test.
-# @param d The directory under test.
-def exe_name(d):
- return "bc" if d == "bc1" or d == "bc2" or d == "bc3" else "dc"
-
-
-# Housekeeping.
-script = sys.argv[0]
-scriptdir = os.path.dirname(script)
-
-# Must run this script alone.
-if __name__ != "__main__":
- usage()
-
-timeout = 2.5
-
-if len(sys.argv) < 2:
- usage()
-
-idx = 1
-
-exedir = sys.argv[idx]
-
-asan = (exedir == "--asan")
-
-# We could possibly run under ASan. See later for what that means.
-if asan:
- idx += 1
- if len(sys.argv) < idx + 1:
- usage()
- exedir = sys.argv[idx]
-
-print("exedir: {}".format(exedir))
-
-# Grab the correct directory of AFL++ results.
-if len(sys.argv) >= idx + 2:
- resultsdir = sys.argv[idx + 1]
-else:
- if exedir == "bc1":
- resultsdir = scriptdir + "/../tests/fuzzing/bc_outputs1"
- elif exedir == "bc2":
- resultsdir = scriptdir + "/../tests/fuzzing/bc_outputs2"
- elif exedir == "bc3":
- resultsdir = scriptdir + "/../tests/fuzzing/bc_outputs3"
- elif exedir == "dc":
- resultsdir = scriptdir + "/../tests/fuzzing/dc_outputs"
- else:
- raise ValueError("exedir must be either bc1, bc2, bc3, or dc");
-
-print("resultsdir: {}".format(resultsdir))
-
-# More command-line processing.
-if len(sys.argv) >= idx + 3:
- exe = sys.argv[idx + 2]
-else:
- exe = scriptdir + "/../bin/" + exe_name(exedir)
-
-exebase = os.path.basename(exe)
-
-
-# Use the correct options.
-if exebase == "bc":
- halt = "halt\n"
- options = "-lq"
- seed = ["-e", "seed = 1280937142.20981723890730892738902938071028973408912703984712093", "-f-" ]
-else:
- halt = "q\n"
- options = "-x"
- seed = ["-e", "1280937142.20981723890730892738902938071028973408912703984712093j", "-f-" ]
-
-# More command-line processing.
-if len(sys.argv) >= idx + 4:
- exe = [ exe, sys.argv[idx + 3:], options ] + seed
-else:
- exe = [ exe, options ] + seed
-for i in range(4, len(sys.argv)):
- exe.append(sys.argv[i])
-
-out = scriptdir + "/../.test.txt"
-
-print(os.path.realpath(os.getcwd()))
-
-dirs = get_children(resultsdir, False)
-
-# Set the correct ASAN_OPTIONS.
-if asan:
- env = os.environ.copy()
- env['ASAN_OPTIONS'] = 'abort_on_error=1:allocator_may_return_null=1'
-
-for d in dirs:
-
- d = resultsdir + "/" + d
-
- print(d)
-
- # Check the crash files.
- files = get_children(d + "/crashes/", True)
-
- for file in files:
- file = d + "/crashes/" + file
- create_test(file, timeout)
-
- # If we are running under ASan, we want to check all files. Otherwise, skip.
- if not asan:
- continue
-
- # Check all of the test cases found by AFL++.
- files = get_children(d + "/queue/", True)
-
- for file in files:
- file = d + "/queue/" + file
- create_test(file, timeout * 2, env)
-
-print("Done")