mirror of
https://github.com/luau-lang/luau.git
synced 2025-01-09 21:09:10 +00:00
47 lines
No EOL
1.4 KiB
Python
47 lines
No EOL
1.4 KiB
Python
#!/usr/bin/python3
|
|
# This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
|
|
# Given a fuzzer binary and a list of crashing programs, this tool collects unique crash reasons and prints reproducers.
|
|
|
|
import re
|
|
import sys
|
|
import subprocess
|
|
|
|
def get_crash_reason(binary, file):
|
|
res = subprocess.run([binary, file], stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
|
|
if res.returncode == 0:
|
|
print(f"Warning: {binary} {file} returned 0")
|
|
return None
|
|
err = res.stderr.decode("utf-8")
|
|
|
|
if (pos := err.find("ERROR: libFuzzer:")) != -1:
|
|
return err[pos:]
|
|
|
|
print(f"Warning: {binary} {file} returned unrecognized error {err}")
|
|
return None
|
|
|
|
def get_crash_fingerprint(reason):
|
|
# Due to ASLR addresses are different every time, so we filter them out
|
|
reason = re.sub(r"0x[0-9a-f]+", "0xXXXX", reason)
|
|
return reason
|
|
|
|
binary = sys.argv[1]
|
|
files = sys.argv[2:]
|
|
|
|
seen = set()
|
|
|
|
for index, file in enumerate(files):
|
|
reason = get_crash_reason(binary, file)
|
|
if reason is None:
|
|
continue
|
|
fingerprint = get_crash_fingerprint(reason)
|
|
if fingerprint in seen:
|
|
# print a spinning ASCII wheel to indicate that we're making progress
|
|
print("-\|/"[index % 4] + "\r", end="")
|
|
continue
|
|
seen.add(fingerprint)
|
|
print(f"Reproducer: {binary} {file}")
|
|
print(f"Crash reason: {reason}")
|
|
print()
|
|
|
|
print(f"Total unique crash reasons: {len(seen)}") |