Recommit: Stop intercepting some malloc-related functions on FreeBSD and

macOS

Summary:
In https://bugs.freebsd.org/215125 I was notified that some configure
scripts attempt to test for the Linux-specific `mallinfo` and `mallopt`
functions by compiling and linking small programs which references the
functions, and observing whether that results in errors.

FreeBSD and macOS do not have the `mallinfo` and `mallopt` functions, so
normally these tests would fail, but when sanitizers are enabled, they
incorrectly succeed, because the sanitizers define interceptors for
these functions.  This also applies to some other malloc-related
functions, such as `memalign`, `pvalloc` and `cfree`.

Fix this by not intercepting `mallinfo`, `mallopt`, `memalign`,
`pvalloc` and `cfree` for FreeBSD and macOS, in all sanitizers.

Also delete the non-functional `cfree` wrapper for Windows, to fix the
test cases on that platform.

Reviewers: emaste, kcc, rnk

Subscribers: timurrrr, eugenis, hans, joerg, llvm-commits, kubamracek

Differential Revision: https://reviews.llvm.org/D27654

llvm-svn: 293536
This commit is contained in:
Dimitry Andric 2017-01-30 19:06:13 +00:00
parent a9df941403
commit f2ac1d1df2
6 changed files with 92 additions and 24 deletions

View File

@ -50,12 +50,14 @@ INTERCEPTOR(void, free, void *ptr) {
asan_free(ptr, &stack, FROM_MALLOC); asan_free(ptr, &stack, FROM_MALLOC);
} }
#if SANITIZER_INTERCEPT_CFREE
INTERCEPTOR(void, cfree, void *ptr) { INTERCEPTOR(void, cfree, void *ptr) {
GET_STACK_TRACE_FREE; GET_STACK_TRACE_FREE;
if (UNLIKELY(IsInDlsymAllocPool(ptr))) if (UNLIKELY(IsInDlsymAllocPool(ptr)))
return; return;
asan_free(ptr, &stack, FROM_MALLOC); asan_free(ptr, &stack, FROM_MALLOC);
} }
#endif // SANITIZER_INTERCEPT_CFREE
INTERCEPTOR(void*, malloc, uptr size) { INTERCEPTOR(void*, malloc, uptr size) {
if (UNLIKELY(!asan_inited)) if (UNLIKELY(!asan_inited))
@ -91,22 +93,24 @@ INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
return asan_realloc(ptr, size, &stack); return asan_realloc(ptr, size, &stack);
} }
#if SANITIZER_INTERCEPT_MEMALIGN
INTERCEPTOR(void*, memalign, uptr boundary, uptr size) { INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
GET_STACK_TRACE_MALLOC; GET_STACK_TRACE_MALLOC;
return asan_memalign(boundary, size, &stack, FROM_MALLOC); return asan_memalign(boundary, size, &stack, FROM_MALLOC);
} }
INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) {
GET_STACK_TRACE_MALLOC;
return asan_memalign(boundary, size, &stack, FROM_MALLOC);
}
INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) { INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) {
GET_STACK_TRACE_MALLOC; GET_STACK_TRACE_MALLOC;
void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC); void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC);
DTLS_on_libc_memalign(res, size); DTLS_on_libc_memalign(res, size);
return res; return res;
} }
#endif // SANITIZER_INTERCEPT_MEMALIGN
INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) {
GET_STACK_TRACE_MALLOC;
return asan_memalign(boundary, size, &stack, FROM_MALLOC);
}
INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
GET_CURRENT_PC_BP_SP; GET_CURRENT_PC_BP_SP;
@ -114,6 +118,7 @@ INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
return asan_malloc_usable_size(ptr, pc, bp); return asan_malloc_usable_size(ptr, pc, bp);
} }
#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
// We avoid including malloc.h for portability reasons. // We avoid including malloc.h for portability reasons.
// man mallinfo says the fields are "long", but the implementation uses int. // man mallinfo says the fields are "long", but the implementation uses int.
// It doesn't matter much -- we just need to make sure that the libc's mallinfo // It doesn't matter much -- we just need to make sure that the libc's mallinfo
@ -131,6 +136,7 @@ INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
INTERCEPTOR(int, mallopt, int cmd, int value) { INTERCEPTOR(int, mallopt, int cmd, int value) {
return -1; return -1;
} }
#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
GET_STACK_TRACE_MALLOC; GET_STACK_TRACE_MALLOC;
@ -143,10 +149,12 @@ INTERCEPTOR(void*, valloc, uptr size) {
return asan_valloc(size, &stack); return asan_valloc(size, &stack);
} }
#if SANITIZER_INTERCEPT_PVALLOC
INTERCEPTOR(void*, pvalloc, uptr size) { INTERCEPTOR(void*, pvalloc, uptr size) {
GET_STACK_TRACE_MALLOC; GET_STACK_TRACE_MALLOC;
return asan_pvalloc(size, &stack); return asan_pvalloc(size, &stack);
} }
#endif // SANITIZER_INTERCEPT_PVALLOC
INTERCEPTOR(void, malloc_stats, void) { INTERCEPTOR(void, malloc_stats, void) {
__asan_print_accumulated_stats(); __asan_print_accumulated_stats();

View File

@ -55,11 +55,6 @@ void _free_base(void *ptr) {
free(ptr); free(ptr);
} }
ALLOCATION_FUNCTION_ATTRIBUTE
void cfree(void *ptr) {
CHECK(!"cfree() should not be used on Windows");
}
ALLOCATION_FUNCTION_ATTRIBUTE ALLOCATION_FUNCTION_ATTRIBUTE
void *malloc(size_t size) { void *malloc(size_t size) {
GET_STACK_TRACE_MALLOC; GET_STACK_TRACE_MALLOC;

View File

@ -19,6 +19,7 @@
#include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_linux.h" #include "sanitizer_common/sanitizer_linux.h"
#include "sanitizer_common/sanitizer_platform_interceptors.h"
#include "sanitizer_common/sanitizer_platform_limits_posix.h" #include "sanitizer_common/sanitizer_platform_limits_posix.h"
#include "sanitizer_common/sanitizer_tls_get_addr.h" #include "sanitizer_common/sanitizer_tls_get_addr.h"
#include "lsan.h" #include "lsan.h"
@ -86,11 +87,26 @@ INTERCEPTOR(void*, realloc, void *q, uptr size) {
return Reallocate(stack, q, size, 1); return Reallocate(stack, q, size, 1);
} }
#if SANITIZER_INTERCEPT_MEMALIGN
INTERCEPTOR(void*, memalign, uptr alignment, uptr size) { INTERCEPTOR(void*, memalign, uptr alignment, uptr size) {
ENSURE_LSAN_INITED; ENSURE_LSAN_INITED;
GET_STACK_TRACE_MALLOC; GET_STACK_TRACE_MALLOC;
return Allocate(stack, size, alignment, kAlwaysClearMemory); return Allocate(stack, size, alignment, kAlwaysClearMemory);
} }
#define LSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
INTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) {
ENSURE_LSAN_INITED;
GET_STACK_TRACE_MALLOC;
void *res = Allocate(stack, size, alignment, kAlwaysClearMemory);
DTLS_on_libc_memalign(res, size);
return res;
}
#define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
#else
#define LSAN_MAYBE_INTERCEPT_MEMALIGN
#define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
#endif // SANITIZER_INTERCEPT_MEMALIGN
INTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) { INTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) {
ENSURE_LSAN_INITED; ENSURE_LSAN_INITED;
@ -106,14 +122,6 @@ INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
return 0; return 0;
} }
INTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) {
ENSURE_LSAN_INITED;
GET_STACK_TRACE_MALLOC;
void *res = Allocate(stack, size, alignment, kAlwaysClearMemory);
DTLS_on_libc_memalign(res, size);
return res;
}
INTERCEPTOR(void*, valloc, uptr size) { INTERCEPTOR(void*, valloc, uptr size) {
ENSURE_LSAN_INITED; ENSURE_LSAN_INITED;
GET_STACK_TRACE_MALLOC; GET_STACK_TRACE_MALLOC;
@ -127,6 +135,7 @@ INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
return GetMallocUsableSize(ptr); return GetMallocUsableSize(ptr);
} }
#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
struct fake_mallinfo { struct fake_mallinfo {
int x[10]; int x[10];
}; };
@ -136,11 +145,18 @@ INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
internal_memset(&res, 0, sizeof(res)); internal_memset(&res, 0, sizeof(res));
return res; return res;
} }
#define LSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
INTERCEPTOR(int, mallopt, int cmd, int value) { INTERCEPTOR(int, mallopt, int cmd, int value) {
return -1; return -1;
} }
#define LSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
#else
#define LSAN_MAYBE_INTERCEPT_MALLINFO
#define LSAN_MAYBE_INTERCEPT_MALLOPT
#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
#if SANITIZER_INTERCEPT_PVALLOC
INTERCEPTOR(void*, pvalloc, uptr size) { INTERCEPTOR(void*, pvalloc, uptr size) {
ENSURE_LSAN_INITED; ENSURE_LSAN_INITED;
GET_STACK_TRACE_MALLOC; GET_STACK_TRACE_MALLOC;
@ -152,8 +168,17 @@ INTERCEPTOR(void*, pvalloc, uptr size) {
} }
return Allocate(stack, size, GetPageSizeCached(), kAlwaysClearMemory); return Allocate(stack, size, GetPageSizeCached(), kAlwaysClearMemory);
} }
#define LSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
#else
#define LSAN_MAYBE_INTERCEPT_PVALLOC
#endif // SANITIZER_INTERCEPT_PVALLOC
#if SANITIZER_INTERCEPT_CFREE
INTERCEPTOR(void, cfree, void *p) ALIAS(WRAPPER_NAME(free)); INTERCEPTOR(void, cfree, void *p) ALIAS(WRAPPER_NAME(free));
#define LSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
#else
#define LSAN_MAYBE_INTERCEPT_CFREE
#endif // SANITIZER_INTERCEPT_CFREE
#define OPERATOR_NEW_BODY \ #define OPERATOR_NEW_BODY \
ENSURE_LSAN_INITED; \ ENSURE_LSAN_INITED; \
@ -277,17 +302,18 @@ namespace __lsan {
void InitializeInterceptors() { void InitializeInterceptors() {
INTERCEPT_FUNCTION(malloc); INTERCEPT_FUNCTION(malloc);
INTERCEPT_FUNCTION(free); INTERCEPT_FUNCTION(free);
INTERCEPT_FUNCTION(cfree); LSAN_MAYBE_INTERCEPT_CFREE;
INTERCEPT_FUNCTION(calloc); INTERCEPT_FUNCTION(calloc);
INTERCEPT_FUNCTION(realloc); INTERCEPT_FUNCTION(realloc);
INTERCEPT_FUNCTION(memalign); LSAN_MAYBE_INTERCEPT_MEMALIGN;
LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN;
INTERCEPT_FUNCTION(aligned_alloc);
INTERCEPT_FUNCTION(posix_memalign); INTERCEPT_FUNCTION(posix_memalign);
INTERCEPT_FUNCTION(__libc_memalign);
INTERCEPT_FUNCTION(valloc); INTERCEPT_FUNCTION(valloc);
INTERCEPT_FUNCTION(pvalloc); LSAN_MAYBE_INTERCEPT_PVALLOC;
INTERCEPT_FUNCTION(malloc_usable_size); INTERCEPT_FUNCTION(malloc_usable_size);
INTERCEPT_FUNCTION(mallinfo); LSAN_MAYBE_INTERCEPT_MALLINFO;
INTERCEPT_FUNCTION(mallopt); LSAN_MAYBE_INTERCEPT_MALLOPT;
INTERCEPT_FUNCTION(pthread_create); INTERCEPT_FUNCTION(pthread_create);
INTERCEPT_FUNCTION(pthread_join); INTERCEPT_FUNCTION(pthread_join);

View File

@ -316,4 +316,9 @@
#define SANITIZER_INTERCEPT_UTMP SI_NOT_WINDOWS && !SI_MAC && !SI_FREEBSD #define SANITIZER_INTERCEPT_UTMP SI_NOT_WINDOWS && !SI_MAC && !SI_FREEBSD
#define SANITIZER_INTERCEPT_UTMPX SI_LINUX_NOT_ANDROID || SI_MAC || SI_FREEBSD #define SANITIZER_INTERCEPT_UTMPX SI_LINUX_NOT_ANDROID || SI_MAC || SI_FREEBSD
#define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO (!SI_FREEBSD && !SI_MAC)
#define SANITIZER_INTERCEPT_MEMALIGN (!SI_FREEBSD && !SI_MAC)
#define SANITIZER_INTERCEPT_PVALLOC (!SI_FREEBSD && !SI_MAC)
#define SANITIZER_INTERCEPT_CFREE (!SI_FREEBSD && !SI_MAC)
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H

View File

@ -139,6 +139,7 @@ void *realloc(void *p, size_t size) {
return p; return p;
} }
#if SANITIZER_INTERCEPT_MEMALIGN
void *memalign(size_t alignment, size_t size) { void *memalign(size_t alignment, size_t size) {
if (UNLIKELY(!thread_inited)) if (UNLIKELY(!thread_inited))
thread_init(); thread_init();
@ -146,6 +147,7 @@ void *memalign(size_t alignment, size_t size) {
SANITIZER_MALLOC_HOOK(p, size); SANITIZER_MALLOC_HOOK(p, size);
return p; return p;
} }
#endif // SANITIZER_INTERCEPT_MEMALIGN
int posix_memalign(void **memptr, size_t alignment, size_t size) { int posix_memalign(void **memptr, size_t alignment, size_t size) {
if (UNLIKELY(!thread_inited)) if (UNLIKELY(!thread_inited))
@ -165,18 +167,26 @@ void *valloc(size_t size) {
return p; return p;
} }
#if SANITIZER_INTERCEPT_CFREE
void cfree(void *p) ALIAS("free"); void cfree(void *p) ALIAS("free");
#endif // SANITIZER_INTERCEPT_CFREE
#if SANITIZER_INTERCEPT_PVALLOC
void *pvalloc(size_t size) ALIAS("valloc"); void *pvalloc(size_t size) ALIAS("valloc");
#endif // SANITIZER_INTERCEPT_PVALLOC
#if SANITIZER_INTERCEPT_MEMALIGN
void *__libc_memalign(size_t alignment, size_t size) ALIAS("memalign"); void *__libc_memalign(size_t alignment, size_t size) ALIAS("memalign");
#endif // SANITIZER_INTERCEPT_MEMALIGN
void malloc_usable_size() { void malloc_usable_size() {
} }
#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
void mallinfo() { void mallinfo() {
} }
void mallopt() { void mallopt() {
} }
#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
} // extern "C" } // extern "C"
namespace std { namespace std {

View File

@ -0,0 +1,24 @@
// Test that on non-glibc platforms, a number of malloc-related functions are
// not intercepted.
// RUN: not %clang_asan -Dtestfunc=mallinfo %s -o %t
// RUN: not %clang_asan -Dtestfunc=mallopt %s -o %t
// RUN: not %clang_asan -Dtestfunc=memalign %s -o %t
// RUN: not %clang_asan -Dtestfunc=pvalloc %s -o %t
// RUN: not %clang_asan -Dtestfunc=cfree %s -o %t
#include <stdlib.h>
// For glibc, cause link failures by referencing a nonexistent function.
#ifdef __GLIBC__
#undef testfunc
#define testfunc nonexistent_function
#endif
void testfunc(void);
int main(void)
{
testfunc();
return 0;
}