forked from IQ.Lvbs/IQ.Pilot
IQ.Pilot Release Commit @ 5bc9cd3
This commit is contained in:
81
tinygrad_repo/test/external/external_fuzz_tlsf.py
vendored
Normal file
81
tinygrad_repo/test/external/external_fuzz_tlsf.py
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
import random
|
||||
from typing import Dict, Optional
|
||||
from tinygrad.helpers import getenv
|
||||
from tinygrad.runtime.support.memory import TLSFAllocator
|
||||
|
||||
class AllocatorFuzzer:
|
||||
def __init__(self, total_size):
|
||||
self.total_size = total_size
|
||||
self.alloc_payload = 0
|
||||
self.mv = memoryview(bytearray(total_size))
|
||||
self.alloctor = TLSFAllocator(total_size, block_size=16)
|
||||
|
||||
self.allocations: Dict[int, tuple[int, int]] = {} # ptr -> (size, pattern)
|
||||
|
||||
self.min_alloc_size = 16
|
||||
self.max_alloc_size = int(total_size * 0.3)
|
||||
self.alloc_probability = 0.7
|
||||
|
||||
def generate_pattern(self, ptr: int, size: int) -> int: return (ptr * 31 + size * 17) & 0xFF
|
||||
|
||||
def fill_memory(self, ptr: int, size: int, pattern: int):
|
||||
for i in range(min(size, 32)):
|
||||
self.mv[ptr + i] = pattern
|
||||
self.mv[ptr + (size - 1 - i)] = pattern
|
||||
|
||||
def verify_memory(self, ptr: int, size: int, pattern: int) -> bool:
|
||||
for i in range(min(size, 32)):
|
||||
assert self.mv[ptr + i] == pattern
|
||||
assert self.mv[ptr + (size - 1 - i)] == pattern
|
||||
return True
|
||||
|
||||
def random_alloc(self) -> Optional[int]:
|
||||
if self.total_size - self.alloc_payload < self.min_alloc_size: return None
|
||||
|
||||
size = random.randint(self.min_alloc_size, min(self.max_alloc_size, self.total_size - self.alloc_payload))
|
||||
|
||||
try:
|
||||
ptr = self.alloctor.alloc(size)
|
||||
except MemoryError:
|
||||
print(f"Failed to allocate {size} bytes. Payload size is {self.alloc_payload}, so fragmenation is {(size / self.total_size)*100.0:.2f}%")
|
||||
return None
|
||||
|
||||
pattern = self.generate_pattern(ptr, size)
|
||||
self.fill_memory(ptr, size, pattern)
|
||||
self.allocations[ptr] = (size, pattern)
|
||||
self.alloc_payload += size
|
||||
print(f"Allocated {size} bytes at {ptr:x}, pattern: {pattern:02x}")
|
||||
return ptr
|
||||
|
||||
def random_free(self) -> bool:
|
||||
if not self.allocations: return False
|
||||
|
||||
ptr = random.choice(list(self.allocations.keys()))
|
||||
size, pattern = self.allocations[ptr]
|
||||
|
||||
# Verify pattern before freeing
|
||||
if not self.verify_memory(ptr, size, pattern):
|
||||
raise RuntimeError(f"Memory corruption detected at {ptr:x}!")
|
||||
|
||||
print(f"Freeing {size} bytes at {ptr:x}, pattern verified: {pattern:02x}")
|
||||
self.alloc_payload -= size
|
||||
self.alloctor.free(ptr)
|
||||
del self.allocations[ptr]
|
||||
return True
|
||||
|
||||
def run(self):
|
||||
for i in range(getenv("ITERS", 100000)):
|
||||
if (random.random() < self.alloc_probability or not self.allocations): self.random_alloc()
|
||||
else: self.random_free()
|
||||
|
||||
print("\nCleaning up remaining allocations...")
|
||||
while self.allocations: self.random_free()
|
||||
|
||||
print("Fuzzing completed successfully!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
SEED = getenv("SEED", 42)
|
||||
random.seed(SEED)
|
||||
|
||||
fuzzer = AllocatorFuzzer(1 << 30)
|
||||
fuzzer.run()
|
||||
Reference in New Issue
Block a user