3 # SPDX-License-Identifier: BSD-2-Clause
5 # Copyright (c) 2018-2021 Gavin D. Howard and contributors.
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are met:
10 # * Redistributions of source code must retain the above copyright notice, this
11 # list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above copyright notice,
14 # this list of conditions and the following disclaimer in the documentation
15 # and/or other materials provided with the distribution.
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
36 print("usage: {} [--asan] dir [results_dir [exe options...]]".format(script))
39 def check_crash(exebase, out, error, file, type, test):
41 print("\n{} crashed ({}) on {}:\n".format(exebase, -error, type))
42 print(" {}".format(test))
43 print("\nCopying to \"{}\"".format(out))
44 shutil.copy2(file, out)
48 def run_test(cmd, exebase, tout, indata, out, file, type, test, environ=None):
50 p = subprocess.run(cmd, timeout=tout, input=indata, stdout=subprocess.PIPE,
51 stderr=subprocess.PIPE, env=environ)
52 check_crash(exebase, out, p.returncode, file, type, test)
53 except subprocess.TimeoutExpired:
54 print("\n {} timed out. Continuing...\n".format(exebase))
56 def create_test(file, tout, environ=None):
58 print(" {}".format(file))
60 base = os.path.basename(file)
62 if base == "README.txt":
65 with open(file, "rb") as f:
68 print(" Running whole file...")
70 run_test(exe + [ file ], exebase, tout, halt.encode(), out, file, "file", file, environ)
72 print(" Running file through stdin...")
74 with open(file, "rb") as f:
77 run_test(exe, exebase, tout, content, out, file,
78 "running {} through stdin".format(file), file, environ)
81 def get_children(dir, get_files):
83 with os.scandir(dir) as it:
85 if not entry.name.startswith('.') and \
86 ((entry.is_dir() and not get_files) or \
87 (entry.is_file() and get_files)):
88 dirs.append(entry.name)
94 return "bc" if d == "bc1" or d == "bc2" or d == "bc3" else "dc"
97 testdir = os.path.dirname(script)
99 if __name__ != "__main__":
104 if len(sys.argv) < 2:
109 exedir = sys.argv[idx]
111 asan = (exedir == "--asan")
115 if len(sys.argv) < idx + 1:
117 exedir = sys.argv[idx]
119 print("exedir: {}".format(exedir))
121 if len(sys.argv) >= idx + 2:
122 resultsdir = sys.argv[idx + 1]
125 resultsdir = testdir + "/fuzzing/bc_outputs1"
126 elif exedir == "bc2":
127 resultsdir = testdir + "/fuzzing/bc_outputs2"
128 elif exedir == "bc3":
129 resultsdir = testdir + "/fuzzing/bc_outputs3"
131 resultsdir = testdir + "/fuzzing/dc_outputs"
133 print("resultsdir: {}".format(resultsdir))
135 if len(sys.argv) >= idx + 3:
136 exe = sys.argv[idx + 2]
138 exe = testdir + "/../bin/" + exe_name(exedir)
140 exebase = os.path.basename(exe)
149 if len(sys.argv) >= idx + 4:
150 exe = [ exe, sys.argv[idx + 3:], options ]
152 exe = [ exe, options ]
153 for i in range(4, len(sys.argv)):
154 exe.append(sys.argv[i])
156 out = testdir + "/../.test.txt"
158 print(os.path.realpath(os.getcwd()))
160 dirs = get_children(resultsdir, False)
163 env = os.environ.copy()
164 env['ASAN_OPTIONS'] = 'abort_on_error=1:allocator_may_return_null=1'
168 d = resultsdir + "/" + d
172 files = get_children(d + "/crashes/", True)
175 file = d + "/crashes/" + file
176 create_test(file, timeout)
181 files = get_children(d + "/queue/", True)
184 file = d + "/queue/" + file
185 create_test(file, timeout * 2, env)