From cdbd50800730b62be30d594a31ab91c662a3eb10 Mon Sep 17 00:00:00 2001 From: derselbst Date: Thu, 12 Apr 2018 18:26:12 +0200 Subject: [PATCH] add fluid_align_ptr() for aligning pointers --- src/utils/fluid_sys.h | 16 ++++++++++++++++ test/CMakeLists.txt | 1 + test/test_pointer_alignment.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 test/test_pointer_alignment.c diff --git a/src/utils/fluid_sys.h b/src/utils/fluid_sys.h index 210225c1..821e24ce 100644 --- a/src/utils/fluid_sys.h +++ b/src/utils/fluid_sys.h @@ -602,4 +602,20 @@ void fluid_clear_fpe_i386(void); /* System control */ void fluid_msleep(unsigned int msecs); +/** + * Advances the given \c ptr to the next \c alignment byte boundary. + * Make sure you've allocated an extra of \c alignment bytes to avoid a buffer overflow. + * + * @return Returned pointer is guarenteed to be aligned to \c alignment boundary and in range \f[ ptr <= returned_ptr < ptr + alignment \f]. + */ +static FLUID_INLINE void* fluid_align_ptr(const void* ptr, unsigned int alignment) +{ + uintptr_t ptr_int = (uintptr_t)ptr; + unsigned int offset = ptr_int % alignment; + unsigned int add = offset == 0 ? 0 // is already aligned, dont advance, else buffer overrun + : alignment - offset; // advance the pointer to the next alignment boundary + ptr_int += add; + return (void*)ptr_int; +} + #endif /* _FLUID_SYS_H */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fa8e9c00..c48069da 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -13,6 +13,7 @@ ADD_FLUID_TEST(test_sample_cache) ADD_FLUID_TEST(test_sfont_loading) ADD_FLUID_TEST(test_sample_rate_change) ADD_FLUID_TEST(test_preset_sample_loading) +ADD_FLUID_TEST(test_pointer_alignment) if ( LIBSNDFILE_HASVORBIS ) ADD_FLUID_TEST(test_sf3_sfont_loading) diff --git a/test/test_pointer_alignment.c b/test/test_pointer_alignment.c new file mode 100644 index 00000000..a7447912 --- /dev/null +++ b/test/test_pointer_alignment.c @@ -0,0 +1,31 @@ + +#include "test.h" +#include "utils/fluid_sys.h" + + +// test for fluid_align_ptr() +int main(void) +{ + unsigned int align; + uintptr_t ptr, aligned_ptr; + + for(align = 32; align <= 4*1024u; align <<= 1) + { + for(ptr = 0; ptr <= (align<<10); ptr++) + { + char* tmp = fluid_align_ptr((char*)ptr, align); + aligned_ptr = (uintptr_t)tmp; + + // pointer must be aligned properly + TEST_ASSERT(aligned_ptr % align == 0); + + // aligned pointer must not be smaller than ptr + TEST_ASSERT(aligned_ptr >= ptr); + + // aligned pointer must not be bigger than alignment + TEST_ASSERT(aligned_ptr < ptr + align); + } + } + + return EXIT_SUCCESS; +}