diff options
author | Alois Klink <alois@aloisklink.com> | 2022-12-12 18:30:46 +0000 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2022-12-23 15:21:16 +0100 |
commit | 0559ef6e8ea2acdeaea9d224f634a54b2258cb42 (patch) | |
tree | 927e48afab816e42b9f25afe348e200f29d41570 | |
parent | 426784f40564ffccbf83284b7ed6ac627652a6b1 (diff) | |
download | cmocka-0559ef6e8ea2acdeaea9d224f634a54b2258cb42.zip cmocka-0559ef6e8ea2acdeaea9d224f634a54b2258cb42.tar.gz cmocka-0559ef6e8ea2acdeaea9d224f634a54b2258cb42.tar.bz2 |
src: use __builtin_align_down, if available
In _test_malloc, we manually align a pointer to MALLOC_ALIGNMENT
using `& ~(MALLOC_ALIGNMENT - 1)`. However, this has two problems:
1. We're casting the pointer to `size_t`, which isn't guaranteed
to hold a pointer. Instead, we should cast to `uintptr_t`.
2. Modifying a pointer as a integer is undefined behavior, and on
some platforms (e.g. CHERI), this does not work.
C++11 has std::align that does this for us, but unfortunately, there
isn't a way to do this in ISO C that is guaranteed to work, except for
in Clang v10+, which has a builtin extension called
__builtin_align_down that can align pointers safely for us.
See:
https://clang.llvm.org/docs/LanguageExtensions.html#alignment-builtins
on-behalf-of: @nqminds <info@nqminds.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
-rw-r--r-- | ConfigureChecks.cmake | 3 | ||||
-rw-r--r-- | src/cmocka.c | 16 |
2 files changed, 15 insertions, 4 deletions
diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 028774f..f010e54 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -1,5 +1,6 @@ include(CheckIncludeFile) include(CheckSymbolExists) +include(CheckCSourceCompiles) include(CheckFunctionExists) include(CheckLibraryExists) include(CheckTypeSize) @@ -89,6 +90,8 @@ check_function_exists(signal HAVE_SIGNAL) check_function_exists(strsignal HAVE_STRSIGNAL) check_function_exists(strcmp HAVE_STRCMP) check_function_exists(clock_gettime HAVE_CLOCK_GETTIME) +# Supported by Clang v10+ +check_c_source_compiles("int main(void) { int a = 1; return __builtin_align_down(&a, 8);}" HAVE_BUILTIN_ALIGN_DOWN) if (WIN32) check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S) diff --git a/src/cmocka.c b/src/cmocka.c index bc8f335..f23b6bf 100644 --- a/src/cmocka.c +++ b/src/cmocka.c @@ -2327,9 +2327,16 @@ static void vcm_free_error(char *err_msg) libc_free(err_msg); } +/* Rounds the given pointer down to a multiple of the given alignment. */ +#ifdef HAVE_BUILTIN_ALIGN_DOWN +#define ALIGN_DOWN(x, a) (__builtin_align_down((x), (a))) +#else +#define ALIGN_DOWN(x, a) ((uintptr_t)(x) & ~((a)-1)) +#endif + /* Use the real malloc in this function. */ #undef malloc -void* _test_malloc(const size_t size, const char* file, const int line) { +void* _test_malloc(const size_t size, const char *file, const int line) { char *ptr = NULL; MallocBlockInfo block_info; ListNode * const block_list = get_allocated_blocks_list(); @@ -2344,9 +2351,10 @@ void* _test_malloc(const size_t size, const char* file, const int line) { assert_non_null(block); /* Calculate the returned address. */ - ptr = (char*)(((size_t)block + MALLOC_GUARD_SIZE + - sizeof(struct MallocBlockInfoData) + - MALLOC_ALIGNMENT) & ~(MALLOC_ALIGNMENT - 1)); + ptr = (char *)(ALIGN_DOWN((block + MALLOC_GUARD_SIZE + + sizeof(struct MallocBlockInfoData) + + MALLOC_ALIGNMENT), + MALLOC_ALIGNMENT)); /* Initialize the guard blocks. */ memset(ptr - MALLOC_GUARD_SIZE, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE); |