mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 05:23:41 +08:00
22a8575199
Keep official openpilot ancestry and dependency licenses. Store resources directly in Git, remove LFS setup requirements, and leave the downloadable big model outside the source tree.
82 lines
2.7 KiB
Python
82 lines
2.7 KiB
Python
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()
|