diff --git a/dqn.h b/dqn.h index d204306..4331805 100644 --- a/dqn.h +++ b/dqn.h @@ -246,6 +246,11 @@ // // DQN_ASAN_VET_POISON 1 // +// - Define this macro to the size of the guard memory reserved before and after +// allocations made that are poisoned to protect against out-of-bounds memory +// accesses. By default the library sets the guard to 128 bytes. +// +// DQN_ASAN_POISON_GUARD_SIZE 128 // NOTE: Dqn_Strings =============================================================================== // [$CSTR] Dqn_CString8 | | C-string helpers diff --git a/dqn_debug.h b/dqn_debug.h index 069258a..77eda87 100644 --- a/dqn_debug.h +++ b/dqn_debug.h @@ -38,9 +38,13 @@ #define DQN_ASAN_POISON_VET 0 #endif -#if !defined(DQN_ASAN_POISON_ALIGNMENT) - #define DQN_ASAN_POISON_ALIGNMENT 8 +#define DQN_ASAN_POISON_ALIGNMENT 8 +#if !defined(DQN_ASAN_POISON_GUARD_SIZE) + #define DQN_ASAN_POISON_GUARD_SIZE 128 #endif +static_assert(Dqn_IsPowerOfTwoAligned(DQN_ASAN_POISON_GUARD_SIZE, DQN_ASAN_POISON_ALIGNMENT), + "ASAN poison guard size must be a power-of-two and aligned to ASAN's alignment" + "requirement (8 bytes)"); // NOTE: MSVC does not support the feature detection macro for instance so we // compile it out @@ -48,7 +52,7 @@ #define __has_feature(x) 0 #endif -// NOTE: [$ASAN] Dqn_Asan ========================================================================== === +// NOTE: [$ASAN] Dqn_Asan ========================================================================== #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) #include #endif diff --git a/dqn_helpers.cpp b/dqn_helpers.cpp index b54a35b..e4b7f3e 100644 --- a/dqn_helpers.cpp +++ b/dqn_helpers.cpp @@ -844,8 +844,10 @@ DQN_API Dqn_Library *Dqn_Library_Init() Dqn_Log_DebugF("Dqn Library initialised:\n"); Dqn_Print_StdLnF(Dqn_PrintStd_Err, " OS Page Size/Alloc Granularity: %$$_I32u/%$$_I32u", result->os_page_size, result->os_alloc_granularity); - if (DQN_ASAN_POISON) + if (DQN_ASAN_POISON) { Dqn_Print_StdLnF(Dqn_PrintStd_Err, " ASAN manual poisoning%s", DQN_ASAN_VET_POISON ? " (+vet sanity checks)" : ""); + Dqn_Print_StdLnF(Dqn_PrintStd_Err, " ASAN poison guard size: %$$_I32u", DQN_ASAN_POISON_GUARD_SIZE); + } #if defined(DQN_LEAK_TRACING) Dqn_Print_StdLnF(Dqn_PrintStd_Err, " Allocation leak tracing"); diff --git a/dqn_memory.cpp b/dqn_memory.cpp index 8a82b3b..57c0cb1 100644 --- a/dqn_memory.cpp +++ b/dqn_memory.cpp @@ -179,7 +179,7 @@ DQN_API Dqn_MemBlockSizeRequiredResult Dqn_MemBlock_SizeRequired(Dqn_MemBlock co // is always guarded with poison-ed memory to prevent read/writes behind // the block of memory. if ((block_flags & Dqn_MemBlockFlag_AllocsAreContiguous) == 0) { - result.alloc_size = Dqn_AlignUpPowerOfTwo(size + g_dqn_library->os_page_size, DQN_ASAN_POISON_ALIGNMENT); + result.alloc_size = Dqn_AlignUpPowerOfTwo(size + DQN_ASAN_POISON_GUARD_SIZE, DQN_ASAN_POISON_ALIGNMENT); } ptr_alignment = DQN_MAX(alignment, DQN_ASAN_POISON_ALIGNMENT); } @@ -199,8 +199,8 @@ DQN_API Dqn_MemBlockSizeRequiredResult Dqn_MemBlock_SizeRequired(Dqn_MemBlock co Dqn_usize Dqn_MemBlock_MetadataSize() { - Dqn_usize init_poison_page = DQN_ASAN_POISON ? g_dqn_library->os_page_size : 0; - Dqn_usize poison_alignment = DQN_ASAN_POISON ? DQN_ASAN_POISON_ALIGNMENT : 0; + Dqn_usize init_poison_page = DQN_ASAN_POISON ? DQN_ASAN_POISON_GUARD_SIZE : 0; + Dqn_usize poison_alignment = DQN_ASAN_POISON ? DQN_ASAN_POISON_ALIGNMENT : 0; Dqn_usize result = Dqn_AlignUpPowerOfTwo(sizeof(Dqn_MemBlock), poison_alignment) + init_poison_page; return result; } @@ -236,7 +236,7 @@ DQN_API Dqn_MemBlock *Dqn_MemBlock_Init(Dqn_usize reserve, Dqn_usize commit, uin DQN_ASSERT(Dqn_IsPowerOfTwoAligned(result->data, DQN_ASAN_POISON_ALIGNMENT)); DQN_ASSERT(Dqn_IsPowerOfTwoAligned(result->size, DQN_ASAN_POISON_ALIGNMENT)); void *poison_ptr = DQN_CAST(void *)Dqn_AlignUpPowerOfTwo(DQN_CAST(char *)result + sizeof(Dqn_MemBlock), DQN_ASAN_POISON_ALIGNMENT); - Dqn_usize bytes_to_poison = g_dqn_library->os_page_size + result->size; + Dqn_usize bytes_to_poison = DQN_ASAN_POISON_GUARD_SIZE + result->size; Dqn_ASAN_PoisonMemoryRegion(poison_ptr, bytes_to_poison); } }