1import sys 2 3import traceback 4 5from cffi import api as _api 6 7 8sys.modules['ssl'] = None 9sys.modules['_hashlib'] = None 10 11 12_ffi = _api.FFI() 13_ffi.cdef( 14 """ 15 void *malloc(size_t size); 16 void free(void *ptr); 17 void *realloc(void *ptr, size_t size); 18 19 int CRYPTO_set_mem_functions(void *(*m)(size_t),void *(*r)(void *,size_t), void (*f)(void *)); 20 21 int backtrace(void **buffer, int size); 22 char **backtrace_symbols(void *const *buffer, int size); 23 void backtrace_symbols_fd(void *const *buffer, int size, int fd); 24 """) # noqa 25_api = _ffi.verify( 26 """ 27 #include <openssl/crypto.h> 28 #include <stdlib.h> 29 #include <execinfo.h> 30 """, libraries=["crypto"]) 31C = _ffi.dlopen(None) 32 33verbose = False 34 35 36def log(s): 37 if verbose: 38 print(s) 39 40 41def _backtrace(): 42 buf = _ffi.new("void*[]", 64) 43 result = _api.backtrace(buf, len(buf)) 44 strings = _api.backtrace_symbols(buf, result) 45 stack = [_ffi.string(strings[i]) for i in range(result)] 46 C.free(strings) 47 return stack 48 49 50@_ffi.callback("void*(*)(size_t)") 51def malloc(n): 52 memory = C.malloc(n) 53 python_stack = traceback.extract_stack(limit=3) 54 c_stack = _backtrace() 55 heap[memory] = [(n, python_stack, c_stack)] 56 log("malloc(%d) -> %s" % (n, memory)) 57 return memory 58 59 60@_ffi.callback("void*(*)(void*, size_t)") 61def realloc(p, n): 62 memory = C.realloc(p, n) 63 old = heap.pop(p) 64 65 python_stack = traceback.extract_stack(limit=3) 66 c_stack = _backtrace() 67 68 old.append((n, python_stack, c_stack)) 69 heap[memory] = old 70 log("realloc(0x%x, %d) -> %s" % (int(_ffi.cast("int", p)), n, memory)) 71 return memory 72 73 74@_ffi.callback("void(*)(void*)") 75def free(p): 76 if p != _ffi.NULL: 77 C.free(p) 78 del heap[p] 79 log("free(0x%x)" % (int(_ffi.cast("int", p)),)) 80 81 82if _api.CRYPTO_set_mem_functions(malloc, realloc, free): 83 log('Enabled memory debugging') 84 heap = {} 85else: 86 log('Failed to enable memory debugging') 87 heap = None 88