From fc0b70a60407e1e65610712a702f8286db3a328c Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Tue, 12 May 2026 21:22:54 +0200 Subject: Work on test code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- libtest/alloc.c | 124 ++++++++++++++++++++++++++++++++++++++++++++ libtest/alloc_have_custom.c | 14 +++++ libtest/common.h | 4 ++ libtest/config.mk | 2 +- libtest/globals.c | 3 ++ libtest/libtest.h | 19 +++++++ libtest/mmap.c | 12 +++-- 7 files changed, 173 insertions(+), 5 deletions(-) (limited to 'libtest') diff --git a/libtest/alloc.c b/libtest/alloc.c index 7752091..f89ba94 100644 --- a/libtest/alloc.c +++ b/libtest/alloc.c @@ -427,6 +427,121 @@ void * } +int +libtest_check_custom_mmap(void) +{ + static _Thread_local int in_check_custom_mmap = 0; + char *volatile test_dummy = NULL; + + if (in_check_custom_mmap) + return libtest_mmap_is_custom; + in_check_custom_mmap = 1; + + if (libtest_mmap_is_custom >= 0 && + libtest_mremap_is_custom >= 0 && + libtest_munmap_is_custom >= 0) { + if (libtest_mmap_is_custom & libtest_mremap_is_custom & libtest_munmap_is_custom) + goto custom; + goto real_deallocated; + } + + test_dummy = mmap(NULL, 1u, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + assert(test_dummy != MAP_FAILED); + assert(test_dummy != NULL); + *test_dummy = 0; + + if (libtest_mmap_is_custom == 0) + goto real; + + if (libtest_mremap_is_custom < 0) { + test_dummy = mremap(test_dummy, 1u, 1u, MREMAP_MAYMOVE); + assert(test_dummy != MAP_FAILED); + assert(test_dummy != NULL); + } + if (libtest_mremap_is_custom == 0) + goto real; + + if (libtest_munmap_is_custom < 0) + assert(!munmap(test_dummy, 1u)); + if (libtest_munmap_is_custom == 0) + goto real_deallocated; + +custom: + in_check_custom_mmap = 0; + return 1; + +real: + assert(!munmap(test_dummy, 1u)); +real_deallocated: + in_check_custom_mmap = 0; + libtest_mmap_is_custom = 0; + libtest_mremap_is_custom = 0; + libtest_munmap_is_custom = 0; + return 0; +} + + +void * +(mmap)(void *addr, size_t len, int prot, int flags, int fd, off_t off) +{ + /* TODO implement tracking */ + + libtest_mmap_is_custom = 1; + if (!libtest_check_custom_mmap()) + goto real; + + if (!libtest_malloc_internal_usage) { + if (libtest_malloc_fail_in && !--libtest_malloc_fail_in) { + errno = ENOMEM; + return MAP_FAILED; + } + } + +real: + return libtest_real_mmap(addr, len, prot, flags, fd, off); +} + + +int +(munmap)(void *addr, size_t len) +{ + libtest_munmap_is_custom = 1; + if (!libtest_check_custom_mmap()) + goto real; + +real: + return libtest_real_munmap(addr, len); +} + + +void * +(mremap)(void *old_addr, size_t old_len, size_t new_len, int flags, ...) +{ + va_list args; + void *new_addr = NULL; + + if (flags & MREMAP_FIXED) { + va_start(args, flags); + new_addr = va_arg(args, void *); + va_end(args); + } + + libtest_mremap_is_custom = 1; + if (!libtest_check_custom_mmap()) + goto real; + + if (!libtest_malloc_internal_usage) { + if (libtest_malloc_fail_in && !--libtest_malloc_fail_in) { + errno = ENOMEM; + return MAP_FAILED; + } + } + +real: + return libtest_real_mremap(old_addr, old_len, new_len, flags, new_addr); +} + #else @@ -454,6 +569,9 @@ char *(strndup)(const char *s, size_t n); wchar_t *(wcsdup)(const wchar_t *s); wchar_t *(wcsndup)(const wchar_t *s, size_t n); void *(memdup)(const void *s, size_t n); +void *(mmap)(void *addr, size_t len, int prot, int flags, int fd, off_t off); +int (munmap)(void *addr, size_t len); +void *(mremap)(void *old_addr, size_t old_len, size_t new_len, int flags, ...); static void @@ -599,6 +717,8 @@ check(int use_free) free(p); else free_aligned_sized(p, sizeof(void *), 11u); + + /* TODO mmap, munmap, mremap */ } @@ -696,6 +816,8 @@ check_successfuls(void) assert(GET_MEMINFO(w)->requested_alloc_size == 3u * sizeof(wchar_t)); EXPECT(!memcmp(w, (wchar_t[]){11, 22, 0}, 3u * sizeof(wchar_t))); free(w); + + /* TODO mmap, munmap, mremap */ } @@ -802,6 +924,8 @@ check_failures(void) EXPECT(!memdup("x", 1u)); EXPECT(errno == ENOMEM); EXPECT(!libtest_get_alloc_failure_in()); + + /* TODO mmap, munmap, mremap */ } diff --git a/libtest/alloc_have_custom.c b/libtest/alloc_have_custom.c index 9c213bb..0800e5e 100644 --- a/libtest/alloc_have_custom.c +++ b/libtest/alloc_have_custom.c @@ -26,6 +26,9 @@ char *(strndup)(const char *s, size_t n); wchar_t *(wcsdup)(const wchar_t *s); wchar_t *(wcsndup)(const wchar_t *s, size_t n); void *(memdup)(const void *s, size_t n); +void *(mmap)(void *addr, size_t len, int prot, int flags, int fd, off_t off); +int (munmap)(void *addr, size_t len); +void *(mremap)(void *old_addr, size_t old_len, size_t new_len, int flags, ...); #if defined(__GNUC__) # pragma GCC diagnostic pop @@ -210,6 +213,16 @@ libtest_have_custom_free_aligned_sized(void) } +int +libtest_have_custom_mmap(void) +{ + static int r = -1; + if (r < 0) + r = libtest_check_custom_mmap(); + return r; +} + + #else @@ -243,6 +256,7 @@ main(void) CHECK(libtest_have_custom_wcsdup); CHECK(libtest_have_custom_wcsndup); CHECK(libtest_have_custom_memdup); + CHECK(libtest_have_custom_mmap); return 0; } diff --git a/libtest/common.h b/libtest/common.h index b78b69d..8d22b5b 100644 --- a/libtest/common.h +++ b/libtest/common.h @@ -147,6 +147,9 @@ extern volatile int libtest_strndup_is_custom; extern volatile int libtest_wcsdup_is_custom; extern volatile int libtest_wcsndup_is_custom; extern volatile int libtest_memdup_is_custom; +extern volatile int libtest_mmap_is_custom; +extern volatile int libtest_munmap_is_custom; +extern volatile int libtest_mremap_is_custom; extern struct meminfo libtest_allocs_head; extern struct meminfo libtest_allocs_tail; @@ -174,6 +177,7 @@ libtest_base_pointer(void *ptr) HIDDEN size_t libtest_get_pagesize(void); HIDDEN void *libtest_alloc(struct meminfo *); HIDDEN void libtest_free(void *, enum libtest_zero_check); +HIDDEN int libtest_check_custom_mmap(void); #ifdef WITH_BACKTRACE HIDDEN void libtest_print_backtrace(FILE *, const char *prefix, const char *indent, diff --git a/libtest/config.mk b/libtest/config.mk index aa20790..6dff8a9 100644 --- a/libtest/config.mk +++ b/libtest/config.mk @@ -1,5 +1,5 @@ WITH_BACKTRACE = true -IMPLEMENT_MMAP = false +IMPLEMENT_MMAP = true TEST_CONFIGFILE = config_backtraces=$(WITH_BACKTRACE).mk include $(TEST_INCLUDE_PREFIX)$(TEST_CONFIGFILE) diff --git a/libtest/globals.c b/libtest/globals.c index 430f037..cf8164e 100644 --- a/libtest/globals.c +++ b/libtest/globals.c @@ -21,6 +21,9 @@ volatile int libtest_strndup_is_custom = -1; volatile int libtest_wcsdup_is_custom = -1; volatile int libtest_wcsndup_is_custom = -1; volatile int libtest_memdup_is_custom = -1; +volatile int libtest_mmap_is_custom = -1; +volatile int libtest_munmap_is_custom = -1; +volatile int libtest_mremap_is_custom = -1; struct meminfo libtest_allocs_head; struct meminfo libtest_allocs_tail; diff --git a/libtest/libtest.h b/libtest/libtest.h index 41d1a41..9fa7e56 100644 --- a/libtest/libtest.h +++ b/libtest/libtest.h @@ -324,6 +324,25 @@ int libtest_have_custom_free_sized(void); */ int libtest_have_custom_free_aligned_sized(void); +/** + * Test whether mmap(3), munmap(3), and mremap(3) has + * been overridden, allowing allocations to be tracked, + * and memory allocation failures to be injected + * + * Tools like valgrind(1) prevent resource allocation + * functions from being overridden as they may override + * such functions themselves in order to detect leaks + * and invalid memory access patterns + * + * @return 1 if all three overridden, + * 0 if none have been overridden + * + * The case that only some of the three functions have + * been overriden, those will redirect to the real + * implementation and identify as non-overridden + */ +int libtest_have_custom_mmap(void); + /** * Print a stack trace, to standard error, provided diff --git a/libtest/mmap.c b/libtest/mmap.c index 62ef06e..c3b3067 100644 --- a/libtest/mmap.c +++ b/libtest/mmap.c @@ -24,6 +24,7 @@ void * libtest_real_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) { size_t pagesize = libtest_get_pagesize(); + uintptr_t ret; IF_MMAP2(assert(pagesize == 4096u)); if (off < 0 || off % (off_t)pagesize) @@ -34,10 +35,11 @@ libtest_real_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off goto einval; #ifdef SYS_mmap2 - return (void *)syscall(SYS_mmap2, addr, len, prot, flags, fd, off); + ret = (uintptr_t)syscall(SYS_mmap2, addr, len, prot, flags, fd, off); #else - return (void *)syscall(SYS_mmap, addr, len, prot, flags, fd, off); + ret = (uintptr_t)syscall(SYS_mmap, addr, len, prot, flags, fd, off); #endif + return (void *)ret; einval: errno = EINVAL; @@ -48,7 +50,7 @@ einval: int libtest_real_munmap(void *addr, size_t len) { - return syscall(SYS_munmap, addr, len); + return (int)syscall(SYS_munmap, addr, len); } @@ -57,6 +59,7 @@ libtest_real_mremap(void *old_addr, size_t old_len, size_t new_len, int flags, . { va_list args; void *new_addr = NULL; + uintptr_t ret; if (flags & MREMAP_FIXED) { va_start(args, flags); @@ -64,7 +67,8 @@ libtest_real_mremap(void *old_addr, size_t old_len, size_t new_len, int flags, . va_end(args); } - return (void *)syscall(SYS_mremap, old_addr, old_len, new_len, flags, new_addr); + ret = (uintptr_t)syscall(SYS_mremap, old_addr, old_len, new_len, flags, new_addr); + return (void *)ret; } -- cgit v1.2.3-70-g09d2