In my books, computers are the best machines humans have ever built. A big wave to Alan Turing, you are the thinker I may resent if at all (well Paul Dirac and Darwin are in the same league). All Turing machines (i.e computers) have tape to read from and to write to, like so

The purpose of this blog-post is to understand the implications of “how” the tape is read. Based on this notion of “how” variety of “meanings” (software data-types) emerge if considered at low enough level of abstraction (assembly language).
We will take a live example from Karma, where we have a UObject pool allocator. The idea is to allocate a block of memory for UObject, for instance, AActor spawn (which is done in the routine SpawnActor()). Another example is UClass (which is great grand child class of UObject). Our pool allocator, GUObjectAllocator, allocates the space from the blue strip, representing Karma’s pre-allocated memory, and returns the address in red, meaning the subsequent block of memory addresses, determined by the size of UClass, have been reserved.

However, the following error message (pardon the Normal block address which is not specific to the example I have in mind, written above) started appearing on application close (or, to be precise, on freeing the blue block of memory at application close)

Thus began my search for the grand resolution of the issue. I posted the error message in CppIndia Discord Server. In the response, I was suggested to use Address Sanitizer (ASAN) to look out for the cause of such issue. And sure enough, Xcode ASAN greeted me with the following
==36231==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x00012ad047f8 at pc 0x00010084d208 bp 0x00016fdfcc20 sp 0x00016fdfc3e0
WRITE of size 64 at 0x00012ad047f8 thread T0
#0 0x10084d204 in __asan_memset+0x104 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x41204) (BuildId: f0a7ac5c49bc3abc851181b6f92b308a32000000200000000100000000000b00)
#1 0x102a971d4 in Karma::FGenericPlatformMemory::Memzero(void*, unsigned long) GenericPlatformMemory.h:72
#2 Callstack .....
0x00012ad047f8 is located 8 bytes to the left of 1280000-byte region [0x00012ad04800,0x00012ae3d000)
allocated by thread T0 here:
#0 0x10084ee68 in wrap_malloc+0x94 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x42e68) (BuildId: f0a7ac5c49bc3abc851181b6f92b308a32000000200000000100000000000b00)
#1 0x102aa5b08 in Karma::FMemory::SystemMalloc(unsigned long) KarmaMemory.h:124
#2 0x102aa5a24 in Karma::KarmaSmriti::StartUp() KarmaSmriti.cpp:25
#3 0x1029ab45c in Karma::Application::PrepareMemorySoftBed() Application.cpp:65
#4 0x1029aade8 in Karma::Application::PrepareApplicationForRun() Application.cpp:54
#5 0x10000772c in main EntryPoint.h:79
#6 0x195923f24 (<unknown module>)
Some report on Heap Overflow
==36231==ABORTING
I have put bold font to the text of interest. The FGenericPlatformMemory::MemZero() is doing the “illegal” writing to the block of memory at address 0x00012ad047f8 which was not the address, 0x00012ad04800, returned by GUobjectAllocator. Furthermore this fact is reinforced by the message “0x00012ad047f8 is located 8 bytes to the left of 1280000-byte region [0x00012ad04800,0x00012ae3d000)”. So who or rather how is this offset of 8 bytes is being introduced?
The typecasting done while generating the UClass object, here
ReturnClass = (UClass*)GUObjectAllocator.AllocateUObject(sizeof(UClass), alignof(UClass), true);
is the reason for the offset of 8 bytes leading to the error message because of writing in the place that is not supposed to be written by the app. I have marked the “illegal” block of memory with pink in the cartoon above. The rectification is simple enough
ReturnClass = reinterpret_cast<UClass*>(GUObjectAllocator.AllocateUObject(sizeof(UClass), alignof(UClass), true));
The reinterpret_cast basically type casts the data type without introducing offsets in the address. Thus the conversion from UObjectBase* to UClass* is achieved with ReturnClass having the address value of 0x00012ad04800, which is the legal block of memory reserved by Karma’s pool allocator.
This might raise a question on the comparative working of reinterpret_cast and C-style cast that we leave to the future. A thing that can be said is for that we will be needing assembly language equivalent of the code, something along the lines of this article.





