summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlois Klink <alois@aloisklink.com>2022-12-12 18:30:46 +0000
committerAndreas Schneider <asn@cryptomilk.org>2022-12-23 15:21:16 +0100
commit0559ef6e8ea2acdeaea9d224f634a54b2258cb42 (patch)
tree927e48afab816e42b9f25afe348e200f29d41570
parent426784f40564ffccbf83284b7ed6ac627652a6b1 (diff)
downloadcmocka-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.cmake3
-rw-r--r--src/cmocka.c16
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);