luau/tools/fuzzfilter.py

47 lines
1.4 KiB
Python
Raw Normal View History

Sync to upstream/release/601 (#1084) ## What's changed - `bit32.byteswap` added ([RFC](https://github.com/luau-lang/rfcs/blob/4f543ec23b6a1b53396e0803dd253c83041bae62/docs/function-bit32-byteswap.md)) - Buffer library implementation ([RFC](https://github.com/luau-lang/rfcs/blob/4f543ec23b6a1b53396e0803dd253c83041bae62/docs/type-byte-buffer.md)) - Fixed a missing `stdint.h` include - Fixed parser limiter for recursive type annotations being kind of weird (fixes #645) ### Native Codegen - Fixed a pair of issues when lowering `bit32.extract` - Fixed a narrow edge case that could result in an infinite loop without an interruption - Fixed a negative array out-of-bounds access issue - Temporarily reverted linear block predecessor value propagation ### New type solver - We now type check assignments to annotated variables - Fixed some test cases under local type inference - Moved `isPending` checks for type families to improve performance - Optimized our process for testing if a free type is sufficiently solved - Removed "none ptr" from lea instruction disassembly logging ### Build system & tooling - CMake configuration now validates dependencies to maintain separation between components - Improvements to the fuzzer coverage - Deduplicator for fuzzed callstacks --------- Co-authored-by: Arseny Kapoulkine <arseny.kapoulkine@gmail.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com> Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Aaron Weiss <aaronweiss@roblox.com> Co-authored-by: Vighnesh Vijay <vvijay@roblox.com>
2023-10-27 22:18:41 +01:00
#!/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)}")