luau/tools/fuzzfilter.py
Lily Brown e5ec0cdff3
Sync to upstream/release/601 (#1084)
## What's changed

- `bit32.byteswap` added
([RFC](4f543ec23b/docs/function-bit32-byteswap.md))
- Buffer library implementation
([RFC](4f543ec23b/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 14:18:41 -07:00

47 lines
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)}")