commit 7d0aa69421e5de41bdaa6bf16b722f57fdb3c1c8 Author: doyle Date: Mon Aug 28 00:33:11 2023 +1000 Initial commit diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..8cdd910 --- /dev/null +++ b/build.bat @@ -0,0 +1,2 @@ +@echo off +cl main.cpp -Z7 -fsanitize=address -nologo -link || exit /b 1 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..8abc67f --- /dev/null +++ b/main.cpp @@ -0,0 +1,182 @@ + +#define WIN32_MEAN_AND_LEAN +#include +#include +#include +#include +#include + +#define IsPowerOfTwo(value, pot) ((((size_t)value) & (((size_t)pot) - 1)) == 0) +#define AsanAlignment 8 + +#define PrintByteSpacing(space) \ + if (index) \ + printf(space); \ + if (index && (index % 8 == 0)) \ + printf("| ") + +static void PrintByteArray(char const *array, size_t array_size) +{ + printf(" Byte Array "); + for (size_t index = 0 ; index < array_size; index++) { + PrintByteSpacing(" "); + printf("%02zu", index); + } + printf("\n"); +} + +static void PrintPoisonedBytes(int step, char const *array, size_t array_size) +{ + printf("%d. __asan_address_is_poisoned ", step); + for (size_t index = 0 ; index < array_size; index++) { + PrintByteSpacing(" "); + printf("%c", __asan_address_is_poisoned(array + index) ? 'x' : ' '); + } + printf("\n"); +} + +static void PrintPoisonMemoryIndex(int step, char const *array, size_t array_size, size_t poison_index) +{ + printf("%d. __asan_poison_memory_region ", step); + for (size_t index = 0; index < array_size; index++) { + PrintByteSpacing(" "); + printf("%c ", index == poison_index ? 'x' : ' '); + } + printf("\n"); +} + +static void PrintPoisonMemoryRegion(int step, char const *array, size_t array_size, size_t poison_start_index, size_t poison_end_index) +{ + printf("%d. __asan_poison_memory_region ", step); + for (size_t index = 0; index < array_size; index++) { + PrintByteSpacing(" "); + printf("%c ", index >= poison_start_index && index <= poison_end_index ? 'x' : ' '); + } + printf("\n"); +} + +int main() +{ + printf("Here we demonstrate that ASAN poison-ing will only poison the\n" + "byte region if the region meets an 8 byte boundary. It will only\n" + "poison bytes upto the 8 byte boundary, any bytes that straddle\n" + "the boundary that do not hit the next 8 byte boundary are not\n" + "poison-ed.\n\n"); + + uint32_t const ASAN_ALIGNMENT = 8; + uint32_t const REGION_WINDOW = 7; + char array[16] = {}; + for (size_t poison_index = 0; poison_index < sizeof(array) - (REGION_WINDOW - 1); poison_index++) { + assert(IsPowerOfTwo(array, ASAN_ALIGNMENT)); + + // NOTE: Print byte array ================================================================== + + PrintByteArray(array, sizeof(array)); + + // NOTE: Poison the array ================================================================== + + __asan_poison_memory_region(&array[poison_index], REGION_WINDOW); + PrintPoisonMemoryRegion(1 /*step*/, array, sizeof(array), poison_index, poison_index + (REGION_WINDOW - 1)); + + // NOTE: Print the poison-ed bytes ========================================================= + + PrintPoisonedBytes(2 /*step*/, array, sizeof(array)); + + // NOTE: Cleanup =========================================================================== + + __asan_unpoison_memory_region(array, sizeof(array)); + printf("\n"); + } + + printf( + "Now we demonstrate that unpoison-ing 1 byte in the 8 byte window\n" + "will unpoison all bytes prior to it up until the start of the window\n" + "until the previous 8 byte boundary.\n\n"); + + for (size_t unpoison_index = 0; unpoison_index < sizeof(array); unpoison_index++) { + assert(IsPowerOfTwo(array, ASAN_ALIGNMENT)); + + // NOTE: Print byte array ================================================================== + + PrintByteArray(array, sizeof(array)); + + // NOTE: Poison the array ================================================================== + + __asan_poison_memory_region(array, sizeof(array)); + PrintPoisonMemoryRegion(1 /*step*/, array, sizeof(array), 0, sizeof(array) - 1); + + // NOTE: Print the poison-ed bytes ========================================================= + + PrintPoisonedBytes(2 /*step*/, array, sizeof(array)); + + // NOTE: Unpoison byte at each position separately ========================================= + + printf("3. __asan_unpoison_memory_region "); + __asan_unpoison_memory_region(array + unpoison_index, 1); + + for (size_t index = 0 ; index < sizeof(array); index++) { + PrintByteSpacing(" "); + printf("%c", index == unpoison_index ? 'x' : ' '); + } + printf("\n"); + + // NOTE: Print the poison-ed bytes ========================================================= + + printf("4. __asan_address_is_poisoned "); + for (size_t index = 0 ; index < sizeof(array); index++) { + PrintByteSpacing(" "); + printf("%c", __asan_address_is_poisoned(array + index) ? 'x' : ' '); + } + printf("\n\n"); + + // NOTE: Cleanup =========================================================================== + + __asan_unpoison_memory_region(array, sizeof(array)); + } + + printf( + "Unpoison-ing across 8 byte boundaries may lead to undesired\n" + "behaviour, with all bytes on the left side of the boundary being\n" + "unpoisoned\n\n"); + { + // NOTE: Print byte array ================================================================== + + char array[16] = {}; + PrintByteArray(array, sizeof(array)); + + // NOTE: Poison the array ================================================================== + + __asan_poison_memory_region(array, sizeof(array)); + PrintPoisonMemoryRegion(1 /*step*/, array, sizeof(array), 0, sizeof(array) - 1); + + // NOTE: Print the poison-ed bytes ========================================================= + + PrintPoisonedBytes(2 /*step*/, array, sizeof(array)); + + // NOTE: Unpoison across the 8 byte boundary =============================================== + + printf("3. __asan_unpoison_memory_region "); + uint32_t const start_poison_index = 7; + uint32_t const bytes_to_unpoison = 2; + uint32_t const end_poison_index = start_poison_index + (bytes_to_unpoison - 1); + __asan_unpoison_memory_region(array + start_poison_index, bytes_to_unpoison); + + for (size_t index = 0 ; index < sizeof(array); index++) { + PrintByteSpacing(" "); + printf("%c", index >= start_poison_index && index <= end_poison_index ? 'x' : ' '); + } + printf("\n"); + + // NOTE: Print the poison-ed bytes ========================================================= + + PrintPoisonedBytes(4 /*step*/, array, sizeof(array)); + } + + printf("\n\nTLDR:\n" + " __asan_poison_memory_region(ptr, size)\n" + " Poisons the byte region [ptr, AlignDown(ptr+size, 8))\n\n" + " __asan_unpoison_memory_region(ptr, size)\n" + " Unpoisons the byte region [AlignDown(ptr, 8), ptr+size)\n\n" + ); + return 0; +}