Vendor import of compiler-rt trunk r304460:
https://llvm.org/svn/llvm-project/compiler-rt/trunk@304460
This commit is contained in:
parent
224c1c721b
commit
06eabdc027
|
@ -32,9 +32,6 @@ extern "C" {
|
|||
// descriptor. Returns -1 on failure, or if coverage dumping is disabled.
|
||||
// This is intended for use by sandboxing code.
|
||||
intptr_t __sanitizer_maybe_open_cov_file(const char *name);
|
||||
// Get the number of unique covered blocks (or edges).
|
||||
// This can be useful for coverage-directed in-process fuzzers.
|
||||
uintptr_t __sanitizer_get_total_unique_coverage();
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
@ -47,8 +47,6 @@ static u32 RZSize2Log(u32 rz_size) {
|
|||
return res;
|
||||
}
|
||||
|
||||
static AsanAllocator &get_allocator();
|
||||
|
||||
// The memory chunk allocated from the underlying allocator looks like this:
|
||||
// L L L L L L H H U U U U U U R R
|
||||
// L -- left redzone words (0 or more bytes)
|
||||
|
@ -719,7 +717,7 @@ struct Allocator {
|
|||
|
||||
static Allocator instance(LINKER_INITIALIZED);
|
||||
|
||||
static AsanAllocator &get_allocator() {
|
||||
AsanAllocator &get_allocator() {
|
||||
return instance.allocator;
|
||||
}
|
||||
|
||||
|
|
|
@ -213,5 +213,7 @@ void asan_mz_force_unlock();
|
|||
void PrintInternalAllocatorStats();
|
||||
void AsanSoftRssLimitExceededCallback(bool exceeded);
|
||||
|
||||
AsanAllocator &get_allocator();
|
||||
|
||||
} // namespace __asan
|
||||
#endif // ASAN_ALLOCATOR_H
|
||||
|
|
|
@ -194,6 +194,10 @@ void InitializeFlags() {
|
|||
Report("WARNING: strchr* interceptors are enabled even though "
|
||||
"replace_str=0. Use intercept_strchr=0 to disable them.");
|
||||
}
|
||||
if (!f->replace_str && common_flags()->intercept_strndup) {
|
||||
Report("WARNING: strndup* interceptors are enabled even though "
|
||||
"replace_str=0. Use intercept_strndup=0 to disable them.");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "asan_stats.h"
|
||||
#include "asan_suppressions.h"
|
||||
#include "lsan/lsan_common.h"
|
||||
#include "sanitizer_common/sanitizer_stackdepot.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
|
||||
#if SANITIZER_POSIX
|
||||
|
@ -705,11 +706,27 @@ INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
|
|||
#endif // ASAN_INTERCEPT___CXA_ATEXIT
|
||||
|
||||
#if ASAN_INTERCEPT_FORK
|
||||
static void BeforeFork() {
|
||||
if (SANITIZER_LINUX) {
|
||||
get_allocator().ForceLock();
|
||||
StackDepotLockAll();
|
||||
}
|
||||
}
|
||||
|
||||
static void AfterFork() {
|
||||
if (SANITIZER_LINUX) {
|
||||
StackDepotUnlockAll();
|
||||
get_allocator().ForceUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, fork, void) {
|
||||
ENSURE_ASAN_INITED();
|
||||
BeforeFork();
|
||||
if (common_flags()->coverage) CovBeforeFork();
|
||||
int pid = REAL(fork)();
|
||||
if (common_flags()->coverage) CovAfterFork(pid);
|
||||
AfterFork();
|
||||
return pid;
|
||||
}
|
||||
#endif // ASAN_INTERCEPT_FORK
|
||||
|
|
|
@ -154,6 +154,33 @@ TEST(AddressSanitizer, MAYBE_StrDupOOBTest) {
|
|||
free(str);
|
||||
}
|
||||
|
||||
#if SANITIZER_TEST_HAS_STRNDUP
|
||||
TEST(AddressSanitizer, MAYBE_StrNDupOOBTest) {
|
||||
size_t size = Ident(42);
|
||||
char *str = MallocAndMemsetString(size);
|
||||
char *new_str;
|
||||
// Normal strndup calls.
|
||||
str[size - 1] = '\0';
|
||||
new_str = strndup(str, size - 13);
|
||||
free(new_str);
|
||||
new_str = strndup(str + size - 1, 13);
|
||||
free(new_str);
|
||||
// Argument points to not allocated memory.
|
||||
EXPECT_DEATH(Ident(strndup(str - 1, 13)), LeftOOBReadMessage(1));
|
||||
EXPECT_DEATH(Ident(strndup(str + size, 13)), RightOOBReadMessage(0));
|
||||
// Overwrite the terminating '\0' and hit unallocated memory.
|
||||
str[size - 1] = 'z';
|
||||
EXPECT_DEATH(Ident(strndup(str, size + 13)), RightOOBReadMessage(0));
|
||||
// Check handling of non 0 terminated strings.
|
||||
Ident(new_str = strndup(str + size - 1, 0));
|
||||
free(new_str);
|
||||
Ident(new_str = strndup(str + size - 1, 1));
|
||||
free(new_str);
|
||||
EXPECT_DEATH(Ident(strndup(str + size - 1, 2)), RightOOBReadMessage(0));
|
||||
free(str);
|
||||
}
|
||||
#endif // SANITIZER_TEST_HAS_STRNDUP
|
||||
|
||||
TEST(AddressSanitizer, StrCpyOOBTest) {
|
||||
size_t to_size = Ident(30);
|
||||
size_t from_size = Ident(6); // less than to_size
|
||||
|
|
|
@ -287,8 +287,6 @@ fun:__sanitizer_cov_with_check=uninstrumented
|
|||
fun:__sanitizer_cov_with_check=discard
|
||||
fun:__sanitizer_set_death_callback=uninstrumented
|
||||
fun:__sanitizer_set_death_callback=discard
|
||||
fun:__sanitizer_get_total_unique_coverage=uninstrumented
|
||||
fun:__sanitizer_get_total_unique_coverage=discard
|
||||
fun:__sanitizer_update_counter_bitset_and_clear_counters=uninstrumented
|
||||
fun:__sanitizer_update_counter_bitset_and_clear_counters=discard
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "sanitizer_common/sanitizer_platform_interceptors.h"
|
||||
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
|
||||
#include "sanitizer_common/sanitizer_posix.h"
|
||||
#include "sanitizer_common/sanitizer_stackdepot.h"
|
||||
#include "sanitizer_common/sanitizer_tls_get_addr.h"
|
||||
#include "lsan.h"
|
||||
#include "lsan_allocator.h"
|
||||
|
@ -97,6 +98,28 @@ INTERCEPTOR(void*, valloc, uptr size) {
|
|||
}
|
||||
#endif
|
||||
|
||||
static void BeforeFork() {
|
||||
if (SANITIZER_LINUX) {
|
||||
LockAllocator();
|
||||
StackDepotLockAll();
|
||||
}
|
||||
}
|
||||
|
||||
static void AfterFork() {
|
||||
if (SANITIZER_LINUX) {
|
||||
StackDepotUnlockAll();
|
||||
UnlockAllocator();
|
||||
}
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, fork, void) {
|
||||
ENSURE_LSAN_INITED;
|
||||
BeforeFork();
|
||||
int pid = REAL(fork)();
|
||||
AfterFork();
|
||||
return pid;
|
||||
}
|
||||
|
||||
#if SANITIZER_INTERCEPT_MEMALIGN
|
||||
INTERCEPTOR(void*, memalign, uptr alignment, uptr size) {
|
||||
ENSURE_LSAN_INITED;
|
||||
|
@ -336,6 +359,7 @@ void InitializeInterceptors() {
|
|||
LSAN_MAYBE_INTERCEPT_MALLOPT;
|
||||
INTERCEPT_FUNCTION(pthread_create);
|
||||
INTERCEPT_FUNCTION(pthread_join);
|
||||
INTERCEPT_FUNCTION(fork);
|
||||
|
||||
if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
|
||||
Report("LeakSanitizer: failed to create thread key.\n");
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
// MemorySanitizer allocator.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "sanitizer_common/sanitizer_allocator.h"
|
||||
#include "sanitizer_common/sanitizer_allocator_interface.h"
|
||||
#include "msan.h"
|
||||
#include "msan_allocator.h"
|
||||
#include "msan_origin.h"
|
||||
|
@ -22,102 +20,12 @@
|
|||
|
||||
namespace __msan {
|
||||
|
||||
struct Metadata {
|
||||
uptr requested_size;
|
||||
};
|
||||
|
||||
struct MsanMapUnmapCallback {
|
||||
void OnMap(uptr p, uptr size) const {}
|
||||
void OnUnmap(uptr p, uptr size) const {
|
||||
__msan_unpoison((void *)p, size);
|
||||
|
||||
// We are about to unmap a chunk of user memory.
|
||||
// Mark the corresponding shadow memory as not needed.
|
||||
uptr shadow_p = MEM_TO_SHADOW(p);
|
||||
ReleaseMemoryPagesToOS(shadow_p, shadow_p + size);
|
||||
if (__msan_get_track_origins()) {
|
||||
uptr origin_p = MEM_TO_ORIGIN(p);
|
||||
ReleaseMemoryPagesToOS(origin_p, origin_p + size);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__mips64)
|
||||
static const uptr kMaxAllowedMallocSize = 2UL << 30;
|
||||
static const uptr kRegionSizeLog = 20;
|
||||
static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
|
||||
typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap;
|
||||
|
||||
struct AP32 {
|
||||
static const uptr kSpaceBeg = 0;
|
||||
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
|
||||
static const uptr kMetadataSize = sizeof(Metadata);
|
||||
typedef __sanitizer::CompactSizeClassMap SizeClassMap;
|
||||
static const uptr kRegionSizeLog = __msan::kRegionSizeLog;
|
||||
typedef __msan::ByteMap ByteMap;
|
||||
typedef MsanMapUnmapCallback MapUnmapCallback;
|
||||
static const uptr kFlags = 0;
|
||||
};
|
||||
typedef SizeClassAllocator32<AP32> PrimaryAllocator;
|
||||
#elif defined(__x86_64__)
|
||||
#if SANITIZER_LINUX && !defined(MSAN_LINUX_X86_64_OLD_MAPPING)
|
||||
static const uptr kAllocatorSpace = 0x700000000000ULL;
|
||||
#else
|
||||
static const uptr kAllocatorSpace = 0x600000000000ULL;
|
||||
#endif
|
||||
static const uptr kMaxAllowedMallocSize = 8UL << 30;
|
||||
|
||||
struct AP64 { // Allocator64 parameters. Deliberately using a short name.
|
||||
static const uptr kSpaceBeg = kAllocatorSpace;
|
||||
static const uptr kSpaceSize = 0x40000000000; // 4T.
|
||||
static const uptr kMetadataSize = sizeof(Metadata);
|
||||
typedef DefaultSizeClassMap SizeClassMap;
|
||||
typedef MsanMapUnmapCallback MapUnmapCallback;
|
||||
static const uptr kFlags = 0;
|
||||
};
|
||||
|
||||
typedef SizeClassAllocator64<AP64> PrimaryAllocator;
|
||||
|
||||
#elif defined(__powerpc64__)
|
||||
static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G
|
||||
|
||||
struct AP64 { // Allocator64 parameters. Deliberately using a short name.
|
||||
static const uptr kSpaceBeg = 0x300000000000;
|
||||
static const uptr kSpaceSize = 0x020000000000; // 2T.
|
||||
static const uptr kMetadataSize = sizeof(Metadata);
|
||||
typedef DefaultSizeClassMap SizeClassMap;
|
||||
typedef MsanMapUnmapCallback MapUnmapCallback;
|
||||
static const uptr kFlags = 0;
|
||||
};
|
||||
|
||||
typedef SizeClassAllocator64<AP64> PrimaryAllocator;
|
||||
#elif defined(__aarch64__)
|
||||
static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G
|
||||
static const uptr kRegionSizeLog = 20;
|
||||
static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
|
||||
typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap;
|
||||
|
||||
struct AP32 {
|
||||
static const uptr kSpaceBeg = 0;
|
||||
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
|
||||
static const uptr kMetadataSize = sizeof(Metadata);
|
||||
typedef __sanitizer::CompactSizeClassMap SizeClassMap;
|
||||
static const uptr kRegionSizeLog = __msan::kRegionSizeLog;
|
||||
typedef __msan::ByteMap ByteMap;
|
||||
typedef MsanMapUnmapCallback MapUnmapCallback;
|
||||
static const uptr kFlags = 0;
|
||||
};
|
||||
typedef SizeClassAllocator32<AP32> PrimaryAllocator;
|
||||
#endif
|
||||
typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
|
||||
typedef LargeMmapAllocator<MsanMapUnmapCallback> SecondaryAllocator;
|
||||
typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
|
||||
SecondaryAllocator> Allocator;
|
||||
|
||||
static Allocator allocator;
|
||||
static AllocatorCache fallback_allocator_cache;
|
||||
static SpinMutex fallback_mutex;
|
||||
|
||||
Allocator &get_allocator() { return allocator; }
|
||||
|
||||
void MsanAllocatorInit() {
|
||||
allocator.Init(
|
||||
common_flags()->allocator_may_return_null,
|
||||
|
|
|
@ -15,9 +15,106 @@
|
|||
#define MSAN_ALLOCATOR_H
|
||||
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "sanitizer_common/sanitizer_allocator.h"
|
||||
#include "sanitizer_common/sanitizer_allocator_interface.h"
|
||||
|
||||
namespace __msan {
|
||||
|
||||
struct Metadata {
|
||||
uptr requested_size;
|
||||
};
|
||||
|
||||
struct MsanMapUnmapCallback {
|
||||
void OnMap(uptr p, uptr size) const {}
|
||||
void OnUnmap(uptr p, uptr size) const {
|
||||
__msan_unpoison((void *)p, size);
|
||||
|
||||
// We are about to unmap a chunk of user memory.
|
||||
// Mark the corresponding shadow memory as not needed.
|
||||
uptr shadow_p = MEM_TO_SHADOW(p);
|
||||
ReleaseMemoryPagesToOS(shadow_p, shadow_p + size);
|
||||
if (__msan_get_track_origins()) {
|
||||
uptr origin_p = MEM_TO_ORIGIN(p);
|
||||
ReleaseMemoryPagesToOS(origin_p, origin_p + size);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__mips64)
|
||||
static const uptr kMaxAllowedMallocSize = 2UL << 30;
|
||||
static const uptr kRegionSizeLog = 20;
|
||||
static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
|
||||
typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap;
|
||||
|
||||
struct AP32 {
|
||||
static const uptr kSpaceBeg = 0;
|
||||
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
|
||||
static const uptr kMetadataSize = sizeof(Metadata);
|
||||
typedef __sanitizer::CompactSizeClassMap SizeClassMap;
|
||||
static const uptr kRegionSizeLog = __msan::kRegionSizeLog;
|
||||
typedef __msan::ByteMap ByteMap;
|
||||
typedef MsanMapUnmapCallback MapUnmapCallback;
|
||||
static const uptr kFlags = 0;
|
||||
};
|
||||
typedef SizeClassAllocator32<AP32> PrimaryAllocator;
|
||||
#elif defined(__x86_64__)
|
||||
#if SANITIZER_LINUX && !defined(MSAN_LINUX_X86_64_OLD_MAPPING)
|
||||
static const uptr kAllocatorSpace = 0x700000000000ULL;
|
||||
#else
|
||||
static const uptr kAllocatorSpace = 0x600000000000ULL;
|
||||
#endif
|
||||
static const uptr kMaxAllowedMallocSize = 8UL << 30;
|
||||
|
||||
struct AP64 { // Allocator64 parameters. Deliberately using a short name.
|
||||
static const uptr kSpaceBeg = kAllocatorSpace;
|
||||
static const uptr kSpaceSize = 0x40000000000; // 4T.
|
||||
static const uptr kMetadataSize = sizeof(Metadata);
|
||||
typedef DefaultSizeClassMap SizeClassMap;
|
||||
typedef MsanMapUnmapCallback MapUnmapCallback;
|
||||
static const uptr kFlags = 0;
|
||||
};
|
||||
|
||||
typedef SizeClassAllocator64<AP64> PrimaryAllocator;
|
||||
|
||||
#elif defined(__powerpc64__)
|
||||
static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G
|
||||
|
||||
struct AP64 { // Allocator64 parameters. Deliberately using a short name.
|
||||
static const uptr kSpaceBeg = 0x300000000000;
|
||||
static const uptr kSpaceSize = 0x020000000000; // 2T.
|
||||
static const uptr kMetadataSize = sizeof(Metadata);
|
||||
typedef DefaultSizeClassMap SizeClassMap;
|
||||
typedef MsanMapUnmapCallback MapUnmapCallback;
|
||||
static const uptr kFlags = 0;
|
||||
};
|
||||
|
||||
typedef SizeClassAllocator64<AP64> PrimaryAllocator;
|
||||
#elif defined(__aarch64__)
|
||||
static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G
|
||||
static const uptr kRegionSizeLog = 20;
|
||||
static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
|
||||
typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap;
|
||||
|
||||
struct AP32 {
|
||||
static const uptr kSpaceBeg = 0;
|
||||
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
|
||||
static const uptr kMetadataSize = sizeof(Metadata);
|
||||
typedef __sanitizer::CompactSizeClassMap SizeClassMap;
|
||||
static const uptr kRegionSizeLog = __msan::kRegionSizeLog;
|
||||
typedef __msan::ByteMap ByteMap;
|
||||
typedef MsanMapUnmapCallback MapUnmapCallback;
|
||||
static const uptr kFlags = 0;
|
||||
};
|
||||
typedef SizeClassAllocator32<AP32> PrimaryAllocator;
|
||||
#endif
|
||||
typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
|
||||
typedef LargeMmapAllocator<MsanMapUnmapCallback> SecondaryAllocator;
|
||||
typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
|
||||
SecondaryAllocator> Allocator;
|
||||
|
||||
|
||||
Allocator &get_allocator();
|
||||
|
||||
struct MsanThreadLocalMallocStorage {
|
||||
uptr quarantine_cache[16];
|
||||
// Allocator cache contains atomic_uint64_t which must be 8-byte aligned.
|
||||
|
|
|
@ -341,33 +341,6 @@ INTERCEPTOR(char *, __strdup, char *src) {
|
|||
#define MSAN_MAYBE_INTERCEPT___STRDUP
|
||||
#endif
|
||||
|
||||
INTERCEPTOR(char *, strndup, char *src, SIZE_T n) {
|
||||
ENSURE_MSAN_INITED();
|
||||
GET_STORE_STACK_TRACE;
|
||||
// On FreeBSD strndup() leverages strnlen().
|
||||
InterceptorScope interceptor_scope;
|
||||
SIZE_T copy_size = REAL(strnlen)(src, n);
|
||||
char *res = REAL(strndup)(src, n);
|
||||
CopyShadowAndOrigin(res, src, copy_size, &stack);
|
||||
__msan_unpoison(res + copy_size, 1); // \0
|
||||
return res;
|
||||
}
|
||||
|
||||
#if !SANITIZER_FREEBSD
|
||||
INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) {
|
||||
ENSURE_MSAN_INITED();
|
||||
GET_STORE_STACK_TRACE;
|
||||
SIZE_T copy_size = REAL(strnlen)(src, n);
|
||||
char *res = REAL(__strndup)(src, n);
|
||||
CopyShadowAndOrigin(res, src, copy_size, &stack);
|
||||
__msan_unpoison(res + copy_size, 1); // \0
|
||||
return res;
|
||||
}
|
||||
#define MSAN_MAYBE_INTERCEPT___STRNDUP INTERCEPT_FUNCTION(__strndup)
|
||||
#else
|
||||
#define MSAN_MAYBE_INTERCEPT___STRNDUP
|
||||
#endif
|
||||
|
||||
INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
|
||||
ENSURE_MSAN_INITED();
|
||||
char *res = REAL(gcvt)(number, ndigit, buf);
|
||||
|
@ -1228,6 +1201,7 @@ INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) {
|
|||
}
|
||||
|
||||
static void BeforeFork() {
|
||||
get_allocator().ForceLock();
|
||||
StackDepotLockAll();
|
||||
ChainedOriginDepotLockAll();
|
||||
}
|
||||
|
@ -1235,6 +1209,7 @@ static void BeforeFork() {
|
|||
static void AfterFork() {
|
||||
ChainedOriginDepotUnlockAll();
|
||||
StackDepotUnlockAll();
|
||||
get_allocator().ForceUnlock();
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, fork, void) {
|
||||
|
@ -1371,6 +1346,13 @@ int OnExit() {
|
|||
return __msan_memcpy(to, from, size); \
|
||||
}
|
||||
|
||||
#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \
|
||||
do { \
|
||||
GET_STORE_STACK_TRACE; \
|
||||
CopyShadowAndOrigin(to, from, size, &stack); \
|
||||
__msan_unpoison(to + size, 1); \
|
||||
} while (false)
|
||||
|
||||
#include "sanitizer_common/sanitizer_platform_interceptors.h"
|
||||
#include "sanitizer_common/sanitizer_common_interceptors.inc"
|
||||
|
||||
|
@ -1538,8 +1520,6 @@ void InitializeInterceptors() {
|
|||
INTERCEPT_FUNCTION(stpcpy); // NOLINT
|
||||
INTERCEPT_FUNCTION(strdup);
|
||||
MSAN_MAYBE_INTERCEPT___STRDUP;
|
||||
INTERCEPT_FUNCTION(strndup);
|
||||
MSAN_MAYBE_INTERCEPT___STRNDUP;
|
||||
INTERCEPT_FUNCTION(strncpy); // NOLINT
|
||||
INTERCEPT_FUNCTION(gcvt);
|
||||
INTERCEPT_FUNCTION(strcat); // NOLINT
|
||||
|
|
|
@ -1581,19 +1581,28 @@ TEST(MemorySanitizer, strdup) {
|
|||
TEST(MemorySanitizer, strndup) {
|
||||
char buf[4] = "abc";
|
||||
__msan_poison(buf + 2, sizeof(*buf));
|
||||
char *x = strndup(buf, 3);
|
||||
char *x;
|
||||
EXPECT_UMR(x = strndup(buf, 3));
|
||||
EXPECT_NOT_POISONED(x[0]);
|
||||
EXPECT_NOT_POISONED(x[1]);
|
||||
EXPECT_POISONED(x[2]);
|
||||
EXPECT_NOT_POISONED(x[3]);
|
||||
free(x);
|
||||
// Check handling of non 0 terminated strings.
|
||||
buf[3] = 'z';
|
||||
__msan_poison(buf + 3, sizeof(*buf));
|
||||
EXPECT_UMR(x = strndup(buf + 3, 1));
|
||||
EXPECT_POISONED(x[0]);
|
||||
EXPECT_NOT_POISONED(x[1]);
|
||||
free(x);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, strndup_short) {
|
||||
char buf[4] = "abc";
|
||||
__msan_poison(buf + 1, sizeof(*buf));
|
||||
__msan_poison(buf + 2, sizeof(*buf));
|
||||
char *x = strndup(buf, 2);
|
||||
char *x;
|
||||
EXPECT_UMR(x = strndup(buf, 2));
|
||||
EXPECT_NOT_POISONED(x[0]);
|
||||
EXPECT_POISONED(x[1]);
|
||||
EXPECT_NOT_POISONED(x[2]);
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
// COMMON_INTERCEPTOR_MEMSET_IMPL
|
||||
// COMMON_INTERCEPTOR_MEMMOVE_IMPL
|
||||
// COMMON_INTERCEPTOR_MEMCPY_IMPL
|
||||
// COMMON_INTERCEPTOR_COPY_STRING
|
||||
// COMMON_INTERCEPTOR_STRNDUP_IMPL
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "interception/interception.h"
|
||||
|
@ -217,6 +219,24 @@ bool PlatformHasDifferentMemcpyAndMemmove();
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef COMMON_INTERCEPTOR_COPY_STRING
|
||||
#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {}
|
||||
#endif
|
||||
|
||||
#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL
|
||||
#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size) \
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size); \
|
||||
uptr copy_length = internal_strnlen(s, size); \
|
||||
char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \
|
||||
if (common_flags()->intercept_strndup) { \
|
||||
COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \
|
||||
} \
|
||||
COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \
|
||||
internal_memcpy(new_mem, s, copy_length); \
|
||||
new_mem[copy_length] = '\0'; \
|
||||
return new_mem;
|
||||
#endif
|
||||
|
||||
struct FileMetadata {
|
||||
// For open_memstream().
|
||||
char **addr;
|
||||
|
@ -300,6 +320,26 @@ INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
|
|||
#define INIT_STRNLEN
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_STRNDUP
|
||||
INTERCEPTOR(char*, strndup, const char *s, uptr size) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
|
||||
}
|
||||
#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup)
|
||||
#else
|
||||
#define INIT_STRNDUP
|
||||
#endif // SANITIZER_INTERCEPT_STRNDUP
|
||||
|
||||
#if SANITIZER_INTERCEPT___STRNDUP
|
||||
INTERCEPTOR(char*, __strndup, const char *s, uptr size) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
|
||||
}
|
||||
#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup)
|
||||
#else
|
||||
#define INIT___STRNDUP
|
||||
#endif // SANITIZER_INTERCEPT___STRNDUP
|
||||
|
||||
#if SANITIZER_INTERCEPT_TEXTDOMAIN
|
||||
INTERCEPTOR(char*, textdomain, const char *domainname) {
|
||||
void *ctx;
|
||||
|
@ -6163,6 +6203,8 @@ static void InitializeCommonInterceptors() {
|
|||
INIT_TEXTDOMAIN;
|
||||
INIT_STRLEN;
|
||||
INIT_STRNLEN;
|
||||
INIT_STRNDUP;
|
||||
INIT___STRNDUP;
|
||||
INIT_STRCMP;
|
||||
INIT_STRNCMP;
|
||||
INIT_STRCASECMP;
|
||||
|
|
|
@ -8,14 +8,9 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
// Sanitizer Coverage interface list.
|
||||
//===----------------------------------------------------------------------===//
|
||||
INTERFACE_FUNCTION(__sanitizer_cov)
|
||||
INTERFACE_FUNCTION(__sanitizer_cov_dump)
|
||||
INTERFACE_FUNCTION(__sanitizer_cov_init)
|
||||
INTERFACE_FUNCTION(__sanitizer_cov_module_init)
|
||||
INTERFACE_FUNCTION(__sanitizer_cov_with_check)
|
||||
INTERFACE_FUNCTION(__sanitizer_dump_coverage)
|
||||
INTERFACE_FUNCTION(__sanitizer_dump_trace_pc_guard_coverage)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_total_unique_coverage)
|
||||
INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file)
|
||||
INTERFACE_WEAK_FUNCTION(__sancov_default_options)
|
||||
INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp)
|
||||
|
|
|
@ -155,13 +155,6 @@ void CoverageData::DirectOpen() {
|
|||
|
||||
void CoverageData::Init() {
|
||||
pc_fd = kInvalidFd;
|
||||
|
||||
if (!common_flags()->coverage) return;
|
||||
Printf("**\n***\n***\n");
|
||||
Printf("**WARNING: this implementation of SanitizerCoverage is deprecated\n");
|
||||
Printf("**WARNING: and will be removed in future versions\n");
|
||||
Printf("**WARNING: See https://clang.llvm.org/docs/SanitizerCoverage.html\n");
|
||||
Printf("**\n***\n***\n");
|
||||
}
|
||||
|
||||
void CoverageData::Enable() {
|
||||
|
@ -495,6 +488,12 @@ static void GenerateHtmlReport(const InternalMmapVector<char *> &cov_files) {
|
|||
void CoverageData::DumpOffsets() {
|
||||
auto sym = Symbolizer::GetOrInit();
|
||||
if (!common_flags()->coverage_pcs) return;
|
||||
Printf("**\n***\n***\n");
|
||||
Printf("**WARNING: this implementation of SanitizerCoverage is deprecated\n");
|
||||
Printf("**WARNING: and will be removed in future versions\n");
|
||||
Printf("**WARNING: See https://clang.llvm.org/docs/SanitizerCoverage.html\n");
|
||||
Printf("**\n***\n***\n");
|
||||
|
||||
CHECK_NE(sym, nullptr);
|
||||
InternalMmapVector<uptr> offsets(0);
|
||||
InternalScopedString path(kMaxPathLength);
|
||||
|
@ -607,47 +606,13 @@ void CoverageUpdateMapping() {
|
|||
} // namespace __sanitizer
|
||||
|
||||
extern "C" {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(u32 *guard) {
|
||||
coverage_data.Add(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()),
|
||||
guard);
|
||||
}
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_with_check(u32 *guard) {
|
||||
atomic_uint32_t *atomic_guard = reinterpret_cast<atomic_uint32_t*>(guard);
|
||||
if (static_cast<s32>(
|
||||
__sanitizer::atomic_load(atomic_guard, memory_order_relaxed)) < 0)
|
||||
coverage_data.Add(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()),
|
||||
guard);
|
||||
}
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() {
|
||||
coverage_enabled = true;
|
||||
coverage_dir = common_flags()->coverage_dir;
|
||||
coverage_data.Init();
|
||||
}
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() {
|
||||
coverage_data.DumpAll();
|
||||
__sanitizer_dump_trace_pc_guard_coverage();
|
||||
}
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void
|
||||
__sanitizer_cov_module_init(s32 *guards, uptr npcs, u8 *counters,
|
||||
const char *comp_unit_name) {
|
||||
coverage_data.InitializeGuards(guards, npcs, comp_unit_name, GET_CALLER_PC());
|
||||
if (!common_flags()->coverage_direct) return;
|
||||
if (SANITIZER_ANDROID && coverage_enabled) {
|
||||
// dlopen/dlclose interceptors do not work on Android, so we rely on
|
||||
// Extend() calls to update .sancov.map.
|
||||
CovUpdateMapping(coverage_dir, GET_CALLER_PC());
|
||||
}
|
||||
coverage_data.Extend(npcs);
|
||||
}
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
sptr __sanitizer_maybe_open_cov_file(const char *name) {
|
||||
return (sptr)MaybeOpenCovFile(name);
|
||||
}
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
uptr __sanitizer_get_total_unique_coverage() {
|
||||
return atomic_load(&coverage_counter, memory_order_relaxed);
|
||||
}
|
||||
|
||||
// Default empty implementations (weak). Users should redefine them.
|
||||
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp, void) {}
|
||||
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp1, void) {}
|
||||
|
|
|
@ -49,7 +49,7 @@ static void WriteModuleCoverage(char* file_path, const char* module_name,
|
|||
WriteToFile(fd, &Magic, sizeof(Magic));
|
||||
WriteToFile(fd, pcs, len * sizeof(*pcs));
|
||||
CloseFile(fd);
|
||||
Printf("SanitizerCoverage: %s %zd PCs written\n", file_path, len);
|
||||
Printf("SanitizerCoverage: %s: %zd PCs written\n", file_path, len);
|
||||
}
|
||||
|
||||
static void SanitizerDumpCoverage(const uptr* unsorted_pcs, uptr len) {
|
||||
|
@ -71,7 +71,7 @@ static void SanitizerDumpCoverage(const uptr* unsorted_pcs, uptr len) {
|
|||
if (!pc) continue;
|
||||
|
||||
if (!__sanitizer_get_module_and_offset_for_pc(pc, nullptr, 0, &pcs[i])) {
|
||||
Printf("ERROR: bad pc %x\n", pc);
|
||||
Printf("ERROR: unknown pc 0x%x (may happen if dlclose is used)\n", pc);
|
||||
continue;
|
||||
}
|
||||
uptr module_base = pc - pcs[i];
|
||||
|
|
|
@ -197,6 +197,9 @@ COMMON_FLAG(bool, intercept_strpbrk, true,
|
|||
COMMON_FLAG(bool, intercept_strlen, true,
|
||||
"If set, uses custom wrappers for strlen and strnlen functions "
|
||||
"to find more errors.")
|
||||
COMMON_FLAG(bool, intercept_strndup, true,
|
||||
"If set, uses custom wrappers for strndup functions "
|
||||
"to find more errors.")
|
||||
COMMON_FLAG(bool, intercept_strchr, true,
|
||||
"If set, uses custom wrappers for strchr, strchrnul, and strrchr "
|
||||
"functions to find more errors.")
|
||||
|
|
|
@ -25,6 +25,12 @@
|
|||
# define SI_NOT_WINDOWS 0
|
||||
#endif
|
||||
|
||||
#if SANITIZER_POSIX
|
||||
# define SI_POSIX 1
|
||||
#else
|
||||
# define SI_POSIX 0
|
||||
#endif
|
||||
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
# define SI_LINUX_NOT_ANDROID 1
|
||||
#else
|
||||
|
@ -69,6 +75,12 @@
|
|||
# define SI_UNIX_NOT_MAC 0
|
||||
#endif
|
||||
|
||||
#if SANITIZER_LINUX && !SANITIZER_FREEBSD
|
||||
# define SI_LINUX_NOT_FREEBSD 1
|
||||
# else
|
||||
# define SI_LINUX_NOT_FREEBSD 0
|
||||
#endif
|
||||
|
||||
#define SANITIZER_INTERCEPT_STRLEN 1
|
||||
#define SANITIZER_INTERCEPT_STRNLEN SI_NOT_MAC
|
||||
#define SANITIZER_INTERCEPT_STRCMP 1
|
||||
|
@ -86,6 +98,8 @@
|
|||
#define SANITIZER_INTERCEPT_MEMMOVE 1
|
||||
#define SANITIZER_INTERCEPT_MEMCPY 1
|
||||
#define SANITIZER_INTERCEPT_MEMCMP 1
|
||||
#define SANITIZER_INTERCEPT_STRNDUP SI_POSIX
|
||||
#define SANITIZER_INTERCEPT___STRNDUP SI_LINUX_NOT_FREEBSD
|
||||
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070
|
||||
# define SI_MAC_DEPLOYMENT_BELOW_10_7 1
|
||||
|
|
|
@ -194,7 +194,7 @@ def GetInstrumentedPCs(binary):
|
|||
# - with call or callq,
|
||||
# - directly or via PLT.
|
||||
cmd = "objdump -d %s | " \
|
||||
"grep '^\s\+[0-9a-f]\+:.*\scall\(q\|\)\s\+[0-9a-f]\+ <__sanitizer_cov\(_with_check\|\)\(@plt\|\)>' | " \
|
||||
"grep '^\s\+[0-9a-f]\+:.*\scall\(q\|\)\s\+[0-9a-f]\+ <__sanitizer_cov\(_with_check\|\|_trace_pc_guard\)\(@plt\|\)>' | " \
|
||||
"grep '^\s\+[0-9a-f]\+' -o" % binary
|
||||
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
||||
shell=True)
|
||||
|
|
|
@ -59,6 +59,7 @@ getpagesize U
|
|||
getpid U
|
||||
gettimeofday U
|
||||
ioctl U
|
||||
isalpha U
|
||||
isatty U
|
||||
isprint U
|
||||
isupper U
|
||||
|
|
|
@ -124,4 +124,10 @@ static inline uint32_t my_rand() {
|
|||
# define SANITIZER_TEST_HAS_PRINTF_L 0
|
||||
#endif
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
# define SANITIZER_TEST_HAS_STRNDUP 1
|
||||
#else
|
||||
# define SANITIZER_TEST_HAS_STRNDUP 0
|
||||
#endif
|
||||
|
||||
#endif // SANITIZER_TEST_UTILS_H
|
||||
|
|
|
@ -197,7 +197,7 @@ struct VtablePrefix {
|
|||
};
|
||||
VtablePrefix *getVtablePrefix(void *Vtable) {
|
||||
VtablePrefix *Vptr = reinterpret_cast<VtablePrefix*>(Vtable);
|
||||
if (!Vptr)
|
||||
if (!IsAccessibleMemoryRange((uptr)Vptr, sizeof(VtablePrefix)))
|
||||
return nullptr;
|
||||
VtablePrefix *Prefix = Vptr - 1;
|
||||
if (!Prefix->TypeInfo)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Test for "sancov.py missing ...".
|
||||
|
||||
// First case: coverage from executable. main() is called on every code path.
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t -DFOOBAR -DMAIN
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s -o %t -DFOOBAR -DMAIN
|
||||
// RUN: rm -rf %T/coverage-missing
|
||||
// RUN: mkdir -p %T/coverage-missing
|
||||
// RUN: cd %T/coverage-missing
|
||||
|
@ -27,8 +27,8 @@
|
|||
|
||||
// Second case: coverage from DSO.
|
||||
// cd %T
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %dynamiclib -DFOOBAR -shared -fPIC
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func %s %dynamiclib -o %t -DMAIN
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s -o %dynamiclib -DFOOBAR -shared -fPIC
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s %dynamiclib -o %t -DMAIN
|
||||
// RUN: cd ..
|
||||
// RUN: rm -rf %T/coverage-missing
|
||||
// RUN: mkdir -p %T/coverage-missing
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s -o %t
|
||||
// RUN: rm -rf %T/coverage-fork
|
||||
// RUN: mkdir -p %T/coverage-fork && cd %T/coverage-fork
|
||||
// RUN: %env_asan_opts=coverage=1:coverage_direct=0:verbosity=1 %run %t 2>&1 | FileCheck %s
|
||||
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s
|
||||
//
|
||||
// UNSUPPORTED: android
|
||||
//
|
||||
// Ideally a forked-subprocess should only report it's own coverage,
|
||||
// not parent's one. But trace-pc-guard currently does nothing special for fork,
|
||||
// and thus this test is relaxed.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -32,6 +36,6 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
// CHECK-DAG: Child PID: [[ChildPID:[0-9]+]]
|
||||
// CHECK-DAG: [[ChildPID]].sancov: 1 PCs written
|
||||
// CHECK-DAG: [[ChildPID]].sancov: {{.*}} PCs written
|
||||
// CHECK-DAG: Parent PID: [[ParentPID:[0-9]+]]
|
||||
// CHECK-DAG: [[ParentPID]].sancov: 3 PCs written
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
// Check that unloading a module doesn't break coverage dumping for remaining
|
||||
// modules.
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func -DSHARED %s -shared -o %dynamiclib1 -fPIC
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func -DSHARED %s -shared -o %dynamiclib2 -fPIC
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func %s %libdl -o %t
|
||||
// RUN: mkdir -p %T/coverage-module-unloaded && cd %T/coverage-module-unloaded
|
||||
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t %dynamiclib1 %dynamiclib2 2>&1 | FileCheck %s
|
||||
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t %dynamiclib1 %dynamiclib2 foo 2>&1 | FileCheck %s
|
||||
// RUN: rm -r %T/coverage-module-unloaded
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard -DSHARED %s -shared -o %dynamiclib1 -fPIC
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard -DSHARED %s -shared -o %dynamiclib2 -fPIC
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s %libdl -o %t.exe
|
||||
// RUN: mkdir -p %t.tmp/coverage-module-unloaded && cd %t.tmp/coverage-module-unloaded
|
||||
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t.exe %dynamiclib1 %dynamiclib2 2>&1 | FileCheck %s
|
||||
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t.exe %dynamiclib1 %dynamiclib2 foo 2>&1 | FileCheck %s
|
||||
//
|
||||
// https://code.google.com/p/address-sanitizer/issues/detail?id=263
|
||||
// XFAIL: android
|
||||
|
@ -48,8 +47,5 @@ int main(int argc, char **argv) {
|
|||
#endif
|
||||
|
||||
// CHECK: PID: [[PID:[0-9]+]]
|
||||
// CHECK: [[PID]].sancov: 1 PCs written
|
||||
// CHECK: coverage-module-unloaded{{.*}}1.[[PID]]
|
||||
// CHECK: coverage-module-unloaded{{.*}}2.[[PID]]
|
||||
// Even though we've unloaded one of the libs we still dump the coverage file
|
||||
// for that lib (although the data will be inaccurate, if at all useful)
|
||||
// CHECK-DAG: exe{{.*}}[[PID]].sancov: {{.*}}PCs written
|
||||
// CHECK-DAG: dynamic{{.*}}[[PID]].sancov: {{.*}}PCs written
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
// RUN: %clangxx_asan -fsanitize-coverage=bb -DSHARED %s -shared -o %dynamiclib -fPIC %ld_flags_rpath_so
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t %ld_flags_rpath_exe
|
||||
|
||||
// RUN: rm -rf %T/coverage_sandboxing_test
|
||||
// RUN: mkdir %T/coverage_sandboxing_test && cd %T/coverage_sandboxing_test
|
||||
// RUN: mkdir vanilla && cd vanilla
|
||||
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-vanilla
|
||||
// RUN: mkdir ../sandbox1 && cd ../sandbox1
|
||||
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t a 2>&1 | FileCheck %s --check-prefix=CHECK-sandbox
|
||||
// RUN: %sancov unpack coverage_sandboxing_test.sancov.packed
|
||||
// RUN: mkdir ../sandbox2 && cd ../sandbox2
|
||||
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t a b 2>&1 | FileCheck %s --check-prefix=CHECK-sandbox
|
||||
// RUN: %sancov unpack coverage_sandboxing_test.sancov.packed
|
||||
// RUN: cd ..
|
||||
// RUN: %sancov print vanilla/%xdynamiclib_filename*.sancov > vanilla.txt
|
||||
// RUN: %sancov print sandbox1/%xdynamiclib_filename*.sancov > sandbox1.txt
|
||||
// RUN: %sancov print sandbox2/%xdynamiclib_filename*.sancov > sandbox2.txt
|
||||
// RUN: diff vanilla.txt sandbox1.txt
|
||||
// RUN: diff vanilla.txt sandbox2.txt
|
||||
// RUN: rm -r %T/coverage_sandboxing_test
|
||||
|
||||
// https://code.google.com/p/address-sanitizer/issues/detail?id=263
|
||||
// XFAIL: android
|
||||
// UNSUPPORTED: ios
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sanitizer/coverage_interface.h>
|
||||
|
||||
#define bb0(n) \
|
||||
case n: \
|
||||
fprintf(stderr, "foo: %d\n", n); \
|
||||
break;
|
||||
|
||||
#define bb1(n) bb0(n) bb0(n + 1)
|
||||
#define bb2(n) bb1(n) bb1(n + 2)
|
||||
#define bb3(n) bb2(n) bb2(n + 4)
|
||||
#define bb4(n) bb3(n) bb3(n + 8)
|
||||
#define bb5(n) bb4(n) bb4(n + 16)
|
||||
#define bb6(n) bb5(n) bb5(n + 32)
|
||||
#define bb7(n) bb6(n) bb6(n + 64)
|
||||
#define bb8(n) bb7(n) bb7(n + 128)
|
||||
|
||||
#ifdef SHARED
|
||||
void foo(int i) {
|
||||
switch(i) {
|
||||
// 256 basic blocks
|
||||
bb8(0)
|
||||
}
|
||||
}
|
||||
#else
|
||||
extern void foo(int i);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
assert(argc <= 3);
|
||||
for (int i = 0; i < 256; i++) foo(i);
|
||||
fprintf(stderr, "PID: %d\n", getpid());
|
||||
if (argc == 1) {
|
||||
// Vanilla mode, dump to individual files.
|
||||
return 0;
|
||||
}
|
||||
// Dump to packed file.
|
||||
int fd = creat("coverage_sandboxing_test.sancov.packed", 0660);
|
||||
__sanitizer_sandbox_arguments args = {0};
|
||||
args.coverage_sandboxed = 1;
|
||||
args.coverage_fd = fd;
|
||||
if (argc == 2)
|
||||
// Write to packed file, do not split into blocks.
|
||||
args.coverage_max_block_size = 0;
|
||||
else if (argc == 3)
|
||||
// Write to packed file, split into blocks (as if writing to a socket).
|
||||
args.coverage_max_block_size = 100;
|
||||
__sanitizer_sandbox_on_notify(&args);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// CHECK-vanilla: PID: [[PID:[0-9]+]]
|
||||
// CHECK-vanilla: .so.[[PID]].sancov: 257 PCs written
|
||||
// CHECK-vanilla: [[PID]].sancov: 1 PCs written
|
||||
|
||||
// CHECK-sandbox: PID: [[PID:[0-9]+]]
|
||||
// CHECK-sandbox: 257 PCs written to packed file
|
|
@ -1,5 +1,5 @@
|
|||
// RUN: %clangxx_asan -fsanitize-coverage=func -DSHARED %s -shared -o %dynamiclib -fPIC %ld_flags_rpath_so
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func %s %ld_flags_rpath_exe -o %t
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard -DSHARED %s -shared -o %dynamiclib -fPIC %ld_flags_rpath_so
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s %ld_flags_rpath_exe -o %t
|
||||
// RUN: rm -rf %T/coverage && mkdir -p %T/coverage && cd %T/coverage
|
||||
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-main
|
||||
// RUN: %sancov print coverage.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV1
|
||||
|
@ -20,7 +20,6 @@
|
|||
// XFAIL: android
|
||||
// UNSUPPORTED: ios
|
||||
|
||||
#include <sanitizer/coverage_interface.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -38,12 +37,8 @@ int G[4];
|
|||
int main(int argc, char **argv) {
|
||||
fprintf(stderr, "PID: %d\n", getpid());
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "foo")) {
|
||||
uintptr_t old_coverage = __sanitizer_get_total_unique_coverage();
|
||||
if (!strcmp(argv[i], "foo"))
|
||||
foo();
|
||||
uintptr_t new_coverage = __sanitizer_get_total_unique_coverage();
|
||||
assert(new_coverage > old_coverage);
|
||||
}
|
||||
if (!strcmp(argv[i], "bar"))
|
||||
bar();
|
||||
}
|
||||
|
@ -64,12 +59,12 @@ int main(int argc, char **argv) {
|
|||
// CHECK-foo-NOT: .so.[[PID]]
|
||||
//
|
||||
// CHECK-bar: PID: [[PID:[0-9]+]]
|
||||
// CHECK-bar: .so.[[PID]].sancov: 1 PCs written
|
||||
// CHECK-bar: [[PID]].sancov: 1 PCs written
|
||||
// CHECK-bar-DAG: .so.[[PID]].sancov: 1 PCs written
|
||||
// CHECK-bar-DAG: [[PID]].sancov: 1 PCs written
|
||||
//
|
||||
// CHECK-foo-bar: PID: [[PID:[0-9]+]]
|
||||
// CHECK-foo-bar: so.[[PID]].sancov: 1 PCs written
|
||||
// CHECK-foo-bar: [[PID]].sancov: 2 PCs written
|
||||
// CHECK-foo-bar-DAG: so.[[PID]].sancov: 1 PCs written
|
||||
// CHECK-foo-bar-DAG: [[PID]].sancov: 2 PCs written
|
||||
//
|
||||
// CHECK-report: AddressSanitizer: global-buffer-overflow
|
||||
// CHECK-report: PCs written
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
|
||||
// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s
|
||||
// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s
|
||||
// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
|
||||
|
||||
// When built as C on Linux, strndup is transformed to __strndup.
|
||||
// RUN: %clangxx_asan -O3 -xc %s -o %t && not %run %t 2>&1 | FileCheck %s
|
||||
|
||||
// Unwind problem on arm: "main" is missing from the allocation stack trace.
|
||||
// UNSUPPORTED: win32,s390,armv7l-unknown-linux-gnueabihf
|
||||
|
||||
#include <string.h>
|
||||
|
||||
char kString[] = "foo";
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *copy = strndup(kString, 2);
|
||||
int x = copy[2 + argc]; // BOOM
|
||||
// CHECK: AddressSanitizer: heap-buffer-overflow
|
||||
// CHECK: #0 {{.*}}main {{.*}}strndup_oob_test.cc:[[@LINE-2]]
|
||||
// CHECK-LABEL: allocated by thread T{{.*}} here:
|
||||
// CHECK: #{{[01]}} {{.*}}strndup
|
||||
// CHECK: #{{.*}}main {{.*}}strndup_oob_test.cc:[[@LINE-6]]
|
||||
// CHECK-LABEL: SUMMARY
|
||||
// CHECK: strndup_oob_test.cc:[[@LINE-7]]
|
||||
return x;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// RUN: %clang_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
|
||||
// RUN: %clang_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s
|
||||
// RUN: %clang_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s
|
||||
// RUN: %clang_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
|
||||
|
||||
// When built as C on Linux, strndup is transformed to __strndup.
|
||||
// RUN: %clang_asan -O3 -xc %s -o %t && not %run %t 2>&1 | FileCheck %s
|
||||
|
||||
// Unwind problem on arm: "main" is missing from the allocation stack trace.
|
||||
// UNSUPPORTED: win32,s390,armv7l-unknown-linux-gnueabihf
|
||||
|
||||
#include <string.h>
|
||||
|
||||
char kChars[] = { 'f', 'o', 'o' };
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *copy = strndup(kChars, 3);
|
||||
copy = strndup(kChars, 10);
|
||||
// CHECK: AddressSanitizer: global-buffer-overflow
|
||||
// CHECK: {{.*}}main {{.*}}.cc:[[@LINE-2]]
|
||||
return *copy;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
// Make sure coverage is dumped even if there are reported leaks.
|
||||
//
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s -o %t
|
||||
//
|
||||
// RUN: rm -rf %T/coverage-and-lsan
|
||||
//
|
||||
|
@ -17,4 +17,4 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
// CHECK: LeakSanitizer: detected memory leaks
|
||||
// CHECK: CovDump:
|
||||
// CHECK: SanitizerCoverage: {{.*}}PCs written
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
// Test coverage_order_pcs=1 flag which orders the PCs by their appearance.
|
||||
// RUN: DIR=%T/coverage-order-pcs
|
||||
// RUN: rm -rf $DIR
|
||||
// RUN: mkdir $DIR
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t
|
||||
// RUN: %env_asan_opts=coverage_dir=$DIR:coverage=1:coverage_order_pcs=0 %run %t
|
||||
// RUN: mv $DIR/*sancov $DIR/A
|
||||
|
||||
// RUN: %env_asan_opts=coverage_dir=$DIR:coverage=1:coverage_order_pcs=0 %run %t 1
|
||||
// RUN: mv $DIR/*sancov $DIR/B
|
||||
|
||||
// RUN: %env_asan_opts=coverage_dir=$DIR:coverage=1:coverage_order_pcs=1 %run %t
|
||||
// RUN: mv $DIR/*sancov $DIR/C
|
||||
|
||||
// RUN: %env_asan_opts=coverage_dir=$DIR:coverage=1:coverage_order_pcs=1 %run %t 1
|
||||
// RUN: mv $DIR/*sancov $DIR/D
|
||||
//
|
||||
// RUN: (%sancov print $DIR/A; %sancov print $DIR/B; %sancov print $DIR/C; %sancov print $DIR/D) | FileCheck %s
|
||||
//
|
||||
// RUN: rm -rf $DIR
|
||||
// Ordering works only in 64-bit mode for now.
|
||||
// REQUIRES: asan-64-bits, shell
|
||||
// UNSUPPORTED: android
|
||||
#include <stdio.h>
|
||||
|
||||
void foo() { fprintf(stderr, "FOO\n"); }
|
||||
void bar() { fprintf(stderr, "BAR\n"); }
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc == 2) {
|
||||
foo();
|
||||
bar();
|
||||
} else {
|
||||
bar();
|
||||
foo();
|
||||
}
|
||||
}
|
||||
|
||||
// Run A: no ordering
|
||||
// CHECK: [[FOO:0x[0-9a-f]*]]
|
||||
// CHECK-NEXT: [[BAR:0x[0-9a-f]*]]
|
||||
// CHECK-NEXT: [[MAIN:0x[0-9a-f]*]]
|
||||
//
|
||||
// Run B: still no ordering
|
||||
// CHECK-NEXT: [[FOO]]
|
||||
// CHECK-NEXT: [[BAR]]
|
||||
// CHECK-NEXT: [[MAIN]]
|
||||
//
|
||||
// Run C: MAIN, BAR, FOO
|
||||
// CHECK-NEXT: [[MAIN]]
|
||||
// CHECK-NEXT: [[BAR]]
|
||||
// CHECK-NEXT: [[FOO]]
|
||||
//
|
||||
// Run D: MAIN, FOO, BAR
|
||||
// CHECK-NEXT: [[MAIN]]
|
||||
// CHECK-NEXT: [[FOO]]
|
||||
// CHECK-NEXT: [[BAR]]
|
|
@ -0,0 +1,28 @@
|
|||
// RUN: %clangxx_msan %s -o %t && not %run %t 2>&1 | FileCheck --check-prefix=ON %s
|
||||
// RUN: %clangxx_msan %s -o %t && MSAN_OPTIONS=intercept_strndup=0 %run %t 2>&1 | FileCheck --check-prefix=OFF --allow-empty %s
|
||||
|
||||
// When built as C on Linux, strndup is transformed to __strndup.
|
||||
// RUN: %clangxx_msan -O3 -xc %s -o %t && not %run %t 2>&1 | FileCheck --check-prefix=ON %s
|
||||
|
||||
// UNSUPPORTED: win32
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sanitizer/msan_interface.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char kString[4] = "abc";
|
||||
__msan_poison(kString + 2, 1);
|
||||
char *copy = strndup(kString, 4); // BOOM
|
||||
assert(__msan_test_shadow(copy, 4) == 2); // Poisoning is preserved.
|
||||
free(copy);
|
||||
return 0;
|
||||
// ON: Uninitialized bytes in __interceptor_{{(__)?}}strndup at offset 2 inside [{{.*}}, 4)
|
||||
// ON: MemorySanitizer: use-of-uninitialized-value
|
||||
// ON: #0 {{.*}}main {{.*}}strndup.cc:[[@LINE-6]]
|
||||
// ON-LABEL: SUMMARY
|
||||
// ON: {{.*}}strndup.cc:[[@LINE-8]]
|
||||
// OFF-NOT: MemorySanitizer
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
// https://github.com/google/sanitizers/issues/774
|
||||
// Test that sanitizer allocator is fork-safe.
|
||||
// Run a number of threads that perform memory allocation/deallocation, then fork
|
||||
// and verify that malloc/free do not deadlock in the child process.
|
||||
|
||||
// RUN: %clangxx -std=c++11 -O0 %s -o %t
|
||||
// RUN: ASAN_OPTIONS=detect_leaks=0 %run %t 2>&1 | FileCheck %s
|
||||
|
||||
// Fun fact: if test output is redirected to a file (as opposed to
|
||||
// being piped directly to FileCheck), we may lose some "done"s due to
|
||||
// a kernel bug:
|
||||
// https://lkml.org/lkml/2014/2/17/324
|
||||
|
||||
// UNSUPPORTED: tsan
|
||||
|
||||
// Flaky on PPC64.
|
||||
// UNSUPPORTED: powerpc64-target-arch
|
||||
// UNSUPPORTED: powerpc64le-target-arch
|
||||
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
int done;
|
||||
|
||||
void *worker(void *arg) {
|
||||
while (true) {
|
||||
void *p = malloc(4);
|
||||
if (__atomic_load_n(&done, __ATOMIC_RELAXED))
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Run through malloc/free in the child process.
|
||||
// This can deadlock on allocator cache refilling.
|
||||
void child() {
|
||||
for (int i = 0; i < 10000; ++i) {
|
||||
void *p = malloc(4);
|
||||
}
|
||||
write(2, "done\n", 5);
|
||||
}
|
||||
|
||||
void test() {
|
||||
const int kThreads = 10;
|
||||
pthread_t t[kThreads];
|
||||
for (int i = 0; i < kThreads; ++i)
|
||||
pthread_create(&t[i], NULL, worker, (void*)(long)i);
|
||||
usleep(100000);
|
||||
pid_t pid = fork();
|
||||
if (pid) {
|
||||
// parent
|
||||
__atomic_store_n(&done, 1, __ATOMIC_RELAXED);
|
||||
pid_t p;
|
||||
while ((p = wait(NULL)) == -1) { }
|
||||
} else {
|
||||
// child
|
||||
child();
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
const int kChildren = 30;
|
||||
for (int i = 0; i < kChildren; ++i) {
|
||||
pid_t pid = fork();
|
||||
if (pid) {
|
||||
// parent
|
||||
} else {
|
||||
test();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < kChildren; ++i) {
|
||||
pid_t p;
|
||||
while ((p = wait(NULL)) == -1) { }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Expect 30 (== kChildren) "done" messages.
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
||||
// CHECK: done
|
|
@ -25,4 +25,4 @@ int main() {
|
|||
}
|
||||
|
||||
// CHECK: main
|
||||
// CHECK: SanitizerCoverage: ./sanitizer_coverage_symbolize.{{.*}}.sancov 2 PCs written
|
||||
// CHECK: SanitizerCoverage: ./sanitizer_coverage_symbolize.{{.*}}.sancov: 2 PCs written
|
||||
|
|
|
@ -62,9 +62,9 @@ int baz() {
|
|||
// CHECK-NEXT: foo
|
||||
// CHECK-NEXT: bar
|
||||
// CHECK-NEXT: baz
|
||||
// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}.sancov 2 PCs written
|
||||
// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_2.so.{{.*}}.sancov 1 PCs written
|
||||
// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_1.so.{{.*}}.sancov 1 PCs written
|
||||
// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}.sancov: 2 PCs written
|
||||
// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_2.so.{{.*}}.sancov: 1 PCs written
|
||||
// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_1.so.{{.*}}.sancov: 1 PCs written
|
||||
//
|
||||
// CHECK-SANCOV: Ignoring {{.*}}_1.so and its coverage because __sanitizer_cov* functions were not found.
|
||||
// CHECK-SANCOV: Ignoring {{.*}}_2.so and its coverage because __sanitizer_cov* functions were not found.
|
||||
|
|
|
@ -34,7 +34,7 @@ int main() {
|
|||
// CHECK: main
|
||||
// CHECK-NEXT: foo
|
||||
// CHECK-NEXT: foo
|
||||
// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard.{{.*}}.sancov 2 PCs written
|
||||
// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard.{{.*}}.sancov: 2 PCs written
|
||||
//
|
||||
// CHECK-SANCOV: sanitizer_coverage_trace_pc_guard.cc:23 foo
|
||||
// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard.cc:28 main
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// RUN: %clangxx -frtti -fsanitize=vptr -g %s -O3 -o %t
|
||||
// RUN: %run %t 2>&1 | FileCheck %s
|
||||
|
||||
// REQUIRES: cxxabi
|
||||
|
||||
#include <string.h>
|
||||
|
||||
class Base {
|
||||
public:
|
||||
int i;
|
||||
virtual void print() {}
|
||||
};
|
||||
|
||||
class Derived : public Base {
|
||||
public:
|
||||
void print() {}
|
||||
};
|
||||
|
||||
int main() {
|
||||
char *c = new char[sizeof(Derived)];
|
||||
memset((void *)c, 0, sizeof(Derived));
|
||||
Derived *list = (Derived *)c;
|
||||
|
||||
// CHECK: PR33221.cpp:[[@LINE+2]]:19: runtime error: member access within address {{.*}} which does not point to an object of type 'Base'
|
||||
// CHECK-NEXT: invalid vptr
|
||||
int foo = list->i;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue