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 ( " \n Cleaning 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 ( )