Merge remote-tracking branch 'llvm-upstream/master'
This brings in r236319:
Fix float->uint conversion for inputs less than 0
diff --git a/include/sanitizer/lsan_interface.h b/include/sanitizer/lsan_interface.h
index 46d2668..db017c4 100644
--- a/include/sanitizer/lsan_interface.h
+++ b/include/sanitizer/lsan_interface.h
@@ -41,14 +41,25 @@
void __lsan_register_root_region(const void *p, size_t size);
void __lsan_unregister_root_region(const void *p, size_t size);
- // Calling this function makes LSan enter the leak checking phase immediately.
- // Use this if normal end-of-process leak checking happens too late (e.g. if
- // you have intentional memory leaks in your shutdown code). Calling this
- // function overrides end-of-process leak checking; it must be called at
- // most once per process. This function will terminate the process if there
- // are memory leaks and the exit_code flag is non-zero.
+ // Check for leaks now. This function behaves identically to the default
+ // end-of-process leak check. In particular, it will terminate the process if
+ // leaks are found and the exit_code flag is non-zero.
+ // Subsequent calls to this function will have no effect and end-of-process
+ // leak check will not run. Effectively, end-of-process leak check is moved to
+ // the time of first invocation of this function.
+ // By calling this function early during process shutdown, you can instruct
+ // LSan to ignore shutdown-only leaks which happen later on.
void __lsan_do_leak_check();
+ // Check for leaks now. Returns zero if no leaks have been found or if leak
+ // detection is disabled, non-zero otherwise.
+ // This function may be called repeatedly, e.g. to periodically check a
+ // long-running process. It prints a leak report if appropriate, but does not
+ // terminate the process. It does not affect the behavior of
+ // __lsan_do_leak_check() or the end-of-process leak check, and is not
+ // affected by them.
+ int __lsan_do_recoverable_leak_check();
+
// The user may optionally provide this function to disallow leak checking
// for the program it is linked into (if the return value is non-zero). This
// function must be defined as returning a constant value; any behavior beyond
diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc
index ce86506..10ddfc7 100644
--- a/lib/asan/asan_rtl.cc
+++ b/lib/asan/asan_rtl.cc
@@ -347,9 +347,9 @@
Printf("malloc_context_size=%zu\n",
(uptr)common_flags()->malloc_context_size);
- Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE);
- Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY);
- Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET);
+ Printf("SHADOW_SCALE: %d\n", (int)SHADOW_SCALE);
+ Printf("SHADOW_GRANULARITY: %d\n", (int)SHADOW_GRANULARITY);
+ Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)SHADOW_OFFSET);
CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
if (kMidMemBeg)
CHECK(kMidShadowBeg > kLowShadowEnd &&
diff --git a/lib/builtins/fixunsdfdi.c b/lib/builtins/fixunsdfdi.c
index b93d1c1..2e0d87e 100644
--- a/lib/builtins/fixunsdfdi.c
+++ b/lib/builtins/fixunsdfdi.c
@@ -21,6 +21,7 @@
COMPILER_RT_ABI du_int
__fixunsdfdi(double a)
{
+ if (a <= 0.0) return 0;
su_int high = a/0x1p32f;
su_int low = a - (double)high*0x1p32f;
return ((du_int)high << 32) | low;
diff --git a/lib/builtins/fixunsdfti.c b/lib/builtins/fixunsdfti.c
index c3d7df9..f8046a0 100644
--- a/lib/builtins/fixunsdfti.c
+++ b/lib/builtins/fixunsdfti.c
@@ -17,7 +17,7 @@
#include "fp_fixuint_impl.inc"
COMPILER_RT_ABI tu_int
-__fixunsdftti(fp_t a) {
+__fixunsdfti(fp_t a) {
return __fixuint(a);
}
#endif /* CRT_HAS_128BIT */
diff --git a/lib/builtins/fixunssfdi.c b/lib/builtins/fixunssfdi.c
index 374ebbe..5a154e8 100644
--- a/lib/builtins/fixunssfdi.c
+++ b/lib/builtins/fixunssfdi.c
@@ -21,6 +21,7 @@
COMPILER_RT_ABI du_int
__fixunssfdi(float a)
{
+ if (a <= 0.0f) return 0;
double da = a;
su_int high = da/0x1p32f;
su_int low = da - (double)high*0x1p32f;
diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc
index 8ac2ae0..0ffba50 100644
--- a/lib/lsan/lsan_common.cc
+++ b/lib/lsan/lsan_common.cc
@@ -126,13 +126,14 @@
// Scans the memory range, looking for byte patterns that point into allocator
// chunks. Marks those chunks with |tag| and adds them to |frontier|.
-// There are two usage modes for this function: finding reachable or ignored
-// chunks (|tag| = kReachable or kIgnored) and finding indirectly leaked chunks
+// There are two usage modes for this function: finding reachable chunks
+// (|tag| = kReachable) and finding indirectly leaked chunks
// (|tag| = kIndirectlyLeaked). In the second case, there's no flood fill,
// so |frontier| = 0.
void ScanRangeForPointers(uptr begin, uptr end,
Frontier *frontier,
const char *region_type, ChunkTag tag) {
+ CHECK(tag == kReachable || tag == kIndirectlyLeaked);
const uptr alignment = flags()->pointer_alignment();
LOG_POINTERS("Scanning %s range %p-%p.\n", region_type, begin, end);
uptr pp = begin;
@@ -146,9 +147,7 @@
// Pointers to self don't count. This matters when tag == kIndirectlyLeaked.
if (chunk == begin) continue;
LsanMetadata m(chunk);
- // Reachable beats ignored beats leaked.
- if (m.tag() == kReachable) continue;
- if (m.tag() == kIgnored && tag != kReachable) continue;
+ if (m.tag() == kReachable || m.tag() == kIgnored) continue;
// Do this check relatively late so we can log only the interesting cases.
if (!flags()->use_poisoned && WordIsPoisoned(pp)) {
@@ -287,7 +286,7 @@
LsanMetadata m(chunk);
if (m.allocated() && m.tag() != kReachable) {
ScanRangeForPointers(chunk, chunk + m.requested_size(),
- /* frontier */ 0, "HEAP", kIndirectlyLeaked);
+ /* frontier */ nullptr, "HEAP", kIndirectlyLeaked);
}
}
@@ -297,8 +296,11 @@
CHECK(arg);
chunk = GetUserBegin(chunk);
LsanMetadata m(chunk);
- if (m.allocated() && m.tag() == kIgnored)
+ if (m.allocated() && m.tag() == kIgnored) {
+ LOG_POINTERS("Ignored: chunk %p-%p of size %zu.\n",
+ chunk, chunk + m.requested_size(), m.requested_size());
reinterpret_cast<Frontier *>(arg)->push_back(chunk);
+ }
}
// Sets the appropriate tag on each chunk.
@@ -306,26 +308,33 @@
// Holds the flood fill frontier.
Frontier frontier(1);
+ ForEachChunk(CollectIgnoredCb, &frontier);
ProcessGlobalRegions(&frontier);
ProcessThreads(suspended_threads, &frontier);
ProcessRootRegions(&frontier);
FloodFillTag(&frontier, kReachable);
+
// The check here is relatively expensive, so we do this in a separate flood
// fill. That way we can skip the check for chunks that are reachable
// otherwise.
LOG_POINTERS("Processing platform-specific allocations.\n");
+ CHECK_EQ(0, frontier.size());
ProcessPlatformSpecificAllocations(&frontier);
FloodFillTag(&frontier, kReachable);
- LOG_POINTERS("Scanning ignored chunks.\n");
- CHECK_EQ(0, frontier.size());
- ForEachChunk(CollectIgnoredCb, &frontier);
- FloodFillTag(&frontier, kIgnored);
-
// Iterate over leaked chunks and mark those that are reachable from other
// leaked chunks.
LOG_POINTERS("Scanning leaked chunks.\n");
- ForEachChunk(MarkIndirectlyLeakedCb, 0 /* arg */);
+ ForEachChunk(MarkIndirectlyLeakedCb, nullptr);
+}
+
+// ForEachChunk callback. Resets the tags to pre-leak-check state.
+static void ResetTagsCb(uptr chunk, void *arg) {
+ (void)arg;
+ chunk = GetUserBegin(chunk);
+ LsanMetadata m(chunk);
+ if (m.allocated() && m.tag() != kIgnored)
+ m.set_tag(kDirectlyLeaked);
}
static void PrintStackTraceById(u32 stack_trace_id) {
@@ -371,35 +380,33 @@
Printf("%s\n\n", line);
}
-struct DoLeakCheckParam {
+struct CheckForLeaksParam {
bool success;
LeakReport leak_report;
};
-static void DoLeakCheckCallback(const SuspendedThreadsList &suspended_threads,
- void *arg) {
- DoLeakCheckParam *param = reinterpret_cast<DoLeakCheckParam *>(arg);
+static void CheckForLeaksCallback(const SuspendedThreadsList &suspended_threads,
+ void *arg) {
+ CheckForLeaksParam *param = reinterpret_cast<CheckForLeaksParam *>(arg);
CHECK(param);
CHECK(!param->success);
ClassifyAllChunks(suspended_threads);
ForEachChunk(CollectLeaksCb, ¶m->leak_report);
+ // Clean up for subsequent leak checks. This assumes we did not overwrite any
+ // kIgnored tags.
+ ForEachChunk(ResetTagsCb, nullptr);
param->success = true;
}
-void DoLeakCheck() {
- EnsureMainThreadIDIsCorrect();
- BlockingMutexLock l(&global_mutex);
- static bool already_done;
- if (already_done) return;
- already_done = true;
+static bool CheckForLeaks() {
if (&__lsan_is_turned_off && __lsan_is_turned_off())
- return;
-
- DoLeakCheckParam param;
+ return false;
+ EnsureMainThreadIDIsCorrect();
+ CheckForLeaksParam param;
param.success = false;
LockThreadRegistry();
LockAllocator();
- DoStopTheWorld(DoLeakCheckCallback, ¶m);
+ DoStopTheWorld(CheckForLeaksCallback, ¶m);
UnlockAllocator();
UnlockThreadRegistry();
@@ -423,12 +430,31 @@
PrintMatchedSuppressions();
if (unsuppressed_count > 0) {
param.leak_report.PrintSummary();
- if (flags()->exitcode) {
- if (common_flags()->coverage)
- __sanitizer_cov_dump();
- internal__exit(flags()->exitcode);
- }
+ return true;
}
+ return false;
+}
+
+void DoLeakCheck() {
+ BlockingMutexLock l(&global_mutex);
+ static bool already_done;
+ if (already_done) return;
+ already_done = true;
+ bool have_leaks = CheckForLeaks();
+ if (!have_leaks) {
+ return;
+ }
+ if (flags()->exitcode) {
+ if (common_flags()->coverage)
+ __sanitizer_cov_dump();
+ internal__exit(flags()->exitcode);
+ }
+}
+
+static int DoRecoverableLeakCheck() {
+ BlockingMutexLock l(&global_mutex);
+ bool have_leaks = CheckForLeaks();
+ return have_leaks ? 1 : 0;
}
static Suppression *GetSuppressionForAddr(uptr addr) {
@@ -676,6 +702,15 @@
#endif // CAN_SANITIZE_LEAKS
}
+SANITIZER_INTERFACE_ATTRIBUTE
+int __lsan_do_recoverable_leak_check() {
+#if CAN_SANITIZE_LEAKS
+ if (common_flags()->detect_leaks)
+ return __lsan::DoRecoverableLeakCheck();
+#endif // CAN_SANITIZE_LEAKS
+ return 0;
+}
+
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
int __lsan_is_turned_off() {
diff --git a/lib/lsan/lsan_common_linux.cc b/lib/lsan/lsan_common_linux.cc
index 813e0b7..2955343 100644
--- a/lib/lsan/lsan_common_linux.cc
+++ b/lib/lsan/lsan_common_linux.cc
@@ -110,7 +110,7 @@
reinterpret_cast<ProcessPlatformAllocParam *>(arg);
chunk = GetUserBegin(chunk);
LsanMetadata m(chunk);
- if (m.allocated() && m.tag() != kReachable) {
+ if (m.allocated() && m.tag() != kReachable && m.tag() != kIgnored) {
u32 stack_id = m.stack_trace_id();
uptr caller_pc = 0;
if (stack_id > 0)
diff --git a/lib/msan/CMakeLists.txt b/lib/msan/CMakeLists.txt
index ccf47fc..de5980e 100644
--- a/lib/msan/CMakeLists.txt
+++ b/lib/msan/CMakeLists.txt
@@ -7,12 +7,15 @@
msan_chained_origin_depot.cc
msan_interceptors.cc
msan_linux.cc
- msan_new_delete.cc
msan_report.cc
msan_thread.cc
msan_poisoning.cc
)
+set(MSAN_RTL_CXX_SOURCES
+ msan_new_delete.cc)
+
+
set(MSAN_RTL_CFLAGS ${SANITIZER_COMMON_CFLAGS})
append_no_rtti_flag(MSAN_RTL_CFLAGS)
append_list_if(COMPILER_RT_HAS_FPIE_FLAG -fPIE MSAN_RTL_CFLAGS)
@@ -29,12 +32,21 @@
$<TARGET_OBJECTS:RTInterception.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
+ $<TARGET_OBJECTS:RTUbsan.${arch}>
CFLAGS ${MSAN_RTL_CFLAGS})
- add_dependencies(msan clang_rt.msan-${arch})
- list(APPEND MSAN_RUNTIME_LIBRARIES clang_rt.msan-${arch})
+ add_compiler_rt_runtime(clang_rt.msan_cxx-${arch} ${arch} STATIC
+ SOURCES ${MSAN_RTL_CXX_SOURCES}
+ $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
+ CFLAGS ${MSAN_RTL_CFLAGS})
+ add_dependencies(msan clang_rt.msan-${arch}
+ clang_rt.msan_cxx-${arch})
+ list(APPEND MSAN_RUNTIME_LIBRARIES clang_rt.msan-${arch}
+ clang_rt.msan_cxx-${arch})
if(UNIX)
add_sanitizer_rt_symbols(clang_rt.msan-${arch} msan.syms.extra)
- add_dependencies(msan clang_rt.msan-${arch}-symbols)
+ add_sanitizer_rt_symbols(clang_rt.msan_cxx-${arch} msan.syms.extra)
+ add_dependencies(msan clang_rt.msan-${arch}-symbols
+ clang_rt.msan_cxx-${arch}-symbols)
endif()
endforeach()
diff --git a/lib/msan/msan.cc b/lib/msan/msan.cc
index caa7736..8f741de 100644
--- a/lib/msan/msan.cc
+++ b/lib/msan/msan.cc
@@ -26,6 +26,8 @@
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "ubsan/ubsan_flags.h"
+#include "ubsan/ubsan_init.h"
// ACHTUNG! No system header includes in this file.
@@ -133,11 +135,6 @@
}
static void InitializeFlags() {
- Flags *f = flags();
- FlagParser parser;
- RegisterMsanFlags(&parser, f);
- RegisterCommonFlags(&parser);
-
SetCommonFlagsDefaults();
{
CommonFlags cf;
@@ -151,14 +148,35 @@
OverrideCommonFlags(cf);
}
+ Flags *f = flags();
f->SetDefaults();
+ FlagParser parser;
+ RegisterMsanFlags(&parser, f);
+ RegisterCommonFlags(&parser);
+
+#if MSAN_CONTAINS_UBSAN
+ __ubsan::Flags *uf = __ubsan::flags();
+ uf->SetDefaults();
+
+ FlagParser ubsan_parser;
+ __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
+ RegisterCommonFlags(&ubsan_parser);
+#endif
+
// Override from user-specified string.
if (__msan_default_options)
parser.ParseString(__msan_default_options());
+#if MSAN_CONTAINS_UBSAN
+ const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions();
+ ubsan_parser.ParseString(ubsan_default_options);
+#endif
const char *msan_options = GetEnv("MSAN_OPTIONS");
parser.ParseString(msan_options);
+#if MSAN_CONTAINS_UBSAN
+ ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"));
+#endif
VPrintf(1, "MSAN_OPTIONS: %s\n", msan_options ? msan_options : "<empty>");
SetVerbosity(common_flags()->verbosity);
@@ -360,8 +378,6 @@
InitializeInterceptors();
InstallAtExitHandler(); // Needs __cxa_atexit interceptor.
- if (MSAN_REPLACE_OPERATORS_NEW_AND_DELETE)
- ReplaceOperatorsNewAndDelete();
DisableCoreDumperIfNecessary();
if (StackSizeIsUnlimited()) {
VPrintf(1, "Unlimited stack, doing reexec\n");
@@ -394,6 +410,10 @@
SetCurrentThread(main_thread);
main_thread->ThreadStart();
+#if MSAN_CONTAINS_UBSAN
+ __ubsan::InitAsPlugin();
+#endif
+
VPrintf(1, "MemorySanitizer init done\n");
msan_init_is_running = 0;
diff --git a/lib/msan/msan.h b/lib/msan/msan.h
index ed18f21..2d48e69 100644
--- a/lib/msan/msan.h
+++ b/lib/msan/msan.h
@@ -20,11 +20,16 @@
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "msan_interface_internal.h"
#include "msan_flags.h"
+#include "ubsan/ubsan_platform.h"
#ifndef MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
# define MSAN_REPLACE_OPERATORS_NEW_AND_DELETE 1
#endif
+#ifndef MSAN_CONTAINS_UBSAN
+# define MSAN_CONTAINS_UBSAN CAN_SANITIZE_UB
+#endif
+
struct MappingDesc {
uptr start;
uptr end;
@@ -131,7 +136,6 @@
void MsanDeallocate(StackTrace *stack, void *ptr);
void InstallTrapHandler();
void InstallAtExitHandler();
-void ReplaceOperatorsNewAndDelete();
const char *GetStackOriginDescr(u32 id, uptr *pc);
diff --git a/lib/msan/msan.syms.extra b/lib/msan/msan.syms.extra
index aad41cf..950e6f4 100644
--- a/lib/msan/msan.syms.extra
+++ b/lib/msan/msan.syms.extra
@@ -1 +1,2 @@
__msan_*
+__ubsan_*
diff --git a/lib/msan/msan_new_delete.cc b/lib/msan/msan_new_delete.cc
index 9a8e56e..c8bc065 100644
--- a/lib/msan/msan_new_delete.cc
+++ b/lib/msan/msan_new_delete.cc
@@ -19,13 +19,6 @@
#include <stddef.h>
-namespace __msan {
-// This function is a no-op. We need it to make sure that object file
-// with our replacements will actually be loaded from static MSan
-// run-time library at link-time.
-void ReplaceOperatorsNewAndDelete() { }
-}
-
using namespace __msan; // NOLINT
// Fake std::nothrow_t to avoid including <new>.
diff --git a/lib/profile/InstrProfiling.h b/lib/profile/InstrProfiling.h
index 2b1bd00..84b673c 100644
--- a/lib/profile/InstrProfiling.h
+++ b/lib/profile/InstrProfiling.h
@@ -62,7 +62,9 @@
*
* Writes to the file with the last name given to \a __llvm_profile_set_filename(),
* or if it hasn't been called, the \c LLVM_PROFILE_FILE environment variable,
- * or if that's not set, \c "default.profdata".
+ * or if that's not set, the last name given to
+ * \a __llvm_profile_override_default_filename(), or if that's not set,
+ * \c "default.profdata".
*/
int __llvm_profile_write_file(void);
@@ -77,6 +79,19 @@
*/
void __llvm_profile_set_filename(const char *Name);
+/*!
+ * \brief Set the filename for writing instrumentation data, unless the
+ * \c LLVM_PROFILE_FILE environment variable was set.
+ *
+ * Unless overridden, sets the filename to be used for subsequent calls to
+ * \a __llvm_profile_write_file().
+ *
+ * \c Name is not copied, so it must remain valid. Passing NULL resets the
+ * filename logic to the default behaviour (unless the \c LLVM_PROFILE_FILE
+ * was set in which case it has no effect).
+ */
+void __llvm_profile_override_default_filename(const char *Name);
+
/*! \brief Register to write instrumentation data to file at exit. */
int __llvm_profile_register_write_file_atexit(void);
diff --git a/lib/profile/InstrProfilingFile.c b/lib/profile/InstrProfilingFile.c
index d9acbbe..0102a25 100644
--- a/lib/profile/InstrProfilingFile.c
+++ b/lib/profile/InstrProfilingFile.c
@@ -76,14 +76,6 @@
__attribute__((weak)) int __llvm_profile_OwnsFilename = 0;
__attribute__((weak)) const char *__llvm_profile_CurrentFilename = NULL;
-static void setFilename(const char *Filename, int OwnsFilename) {
- if (__llvm_profile_OwnsFilename)
- free(UNCONST(__llvm_profile_CurrentFilename));
-
- __llvm_profile_CurrentFilename = Filename;
- __llvm_profile_OwnsFilename = OwnsFilename;
-}
-
static void truncateCurrentFile(void) {
const char *Filename;
FILE *File;
@@ -99,19 +91,36 @@
fclose(File);
}
-static void setDefaultFilename(void) { setFilename("default.profraw", 0); }
+static void setFilename(const char *Filename, int OwnsFilename) {
+ /* Check if this is a new filename and therefore needs truncation. */
+ int NewFile = !__llvm_profile_CurrentFilename ||
+ (Filename && strcmp(Filename, __llvm_profile_CurrentFilename));
+ if (__llvm_profile_OwnsFilename)
+ free(UNCONST(__llvm_profile_CurrentFilename));
+
+ __llvm_profile_CurrentFilename = Filename;
+ __llvm_profile_OwnsFilename = OwnsFilename;
+
+ /* If not a new file, append to support profiling multiple shared objects. */
+ if (NewFile)
+ truncateCurrentFile();
+}
+
+static void resetFilenameToDefault(void) { setFilename("default.profraw", 0); }
int getpid(void);
-static int setFilenameFromEnvironment(void) {
- const char *Filename = getenv("LLVM_PROFILE_FILE");
+static int setFilenamePossiblyWithPid(const char *Filename) {
#define MAX_PID_SIZE 16
char PidChars[MAX_PID_SIZE] = {0};
int NumPids = 0, PidLength = 0;
char *Allocated;
int I, J;
- if (!Filename || !Filename[0])
- return -1;
+ /* Reset filename on NULL, except with env var which is checked by caller. */
+ if (!Filename) {
+ resetFilenameToDefault();
+ return 0;
+ }
/* Check the filename for "%p", which indicates a pid-substitution. */
for (I = 0; Filename[I]; ++I)
@@ -148,11 +157,20 @@
return 0;
}
+static int setFilenameFromEnvironment(void) {
+ const char *Filename = getenv("LLVM_PROFILE_FILE");
+
+ if (!Filename || !Filename[0])
+ return -1;
+
+ return setFilenamePossiblyWithPid(Filename);
+}
+
static void setFilenameAutomatically(void) {
if (!setFilenameFromEnvironment())
return;
- setDefaultFilename();
+ resetFilenameToDefault();
}
__attribute__((visibility("hidden")))
@@ -163,13 +181,20 @@
/* Detect the filename and truncate. */
setFilenameAutomatically();
- truncateCurrentFile();
}
__attribute__((visibility("hidden")))
void __llvm_profile_set_filename(const char *Filename) {
- setFilename(Filename, 0);
- truncateCurrentFile();
+ setFilenamePossiblyWithPid(Filename);
+}
+
+__attribute__((visibility("hidden")))
+void __llvm_profile_override_default_filename(const char *Filename) {
+ /* If the env var is set, skip setting filename from argument. */
+ const char *Env_Filename = getenv("LLVM_PROFILE_FILE");
+ if (Env_Filename && Env_Filename[0])
+ return;
+ setFilenamePossiblyWithPid(Filename);
}
__attribute__((visibility("hidden")))
diff --git a/lib/sanitizer_common/CMakeLists.txt b/lib/sanitizer_common/CMakeLists.txt
index d213953..58105c1 100644
--- a/lib/sanitizer_common/CMakeLists.txt
+++ b/lib/sanitizer_common/CMakeLists.txt
@@ -119,7 +119,7 @@
set(SANITIZER_CFLAGS ${SANITIZER_COMMON_CFLAGS})
append_no_rtti_flag(SANITIZER_CFLAGS)
-append_list_if(SANITIZER_LIMIT_FRAME_SIZE -Wframe-larger-than=512
+append_list_if(SANITIZER_LIMIT_FRAME_SIZE -Wframe-larger-than=570
SANITIZER_CFLAGS)
append_list_if(COMPILER_RT_HAS_WGLOBAL_CONSTRUCTORS_FLAG -Wglobal-constructors
SANITIZER_CFLAGS)
diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 69c1cf8..6e81a50 100644
--- a/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -47,6 +47,7 @@
#define pthread_setname_np pthread_set_name_np
#define inet_aton __inet_aton
#define inet_pton __inet_pton
+#define iconv __bsd_iconv
#endif
#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
@@ -3903,25 +3904,33 @@
}
return res;
}
-INTERCEPTOR(SSIZE_T, __getdelim, char **lineptr, SIZE_T *n, int delim,
- void *stream) {
- void *ctx;
- COMMON_INTERCEPTOR_ENTER(ctx, __getdelim, lineptr, n, delim, stream);
- // FIXME: under ASan the call below may write to freed memory and corrupt
- // its metadata. See
- // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
- SSIZE_T res = REAL(__getdelim)(lineptr, n, delim, stream);
- if (res > 0) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);
+
+// FIXME: under ASan the call below may write to freed memory and corrupt its
+// metadata. See
+// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
+#define GETDELIM_INTERCEPTOR_IMPL(vname) \
+ { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, vname, lineptr, n, delim, stream); \
+ SSIZE_T res = REAL(vname)(lineptr, n, delim, stream); \
+ if (res > 0) { \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr)); \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1); \
+ } \
+ return res; \
}
- return res;
-}
+
+INTERCEPTOR(SSIZE_T, __getdelim, char **lineptr, SIZE_T *n, int delim,
+ void *stream)
+GETDELIM_INTERCEPTOR_IMPL(__getdelim)
+
+// There's no __getdelim() on FreeBSD so we supply the getdelim() interceptor
+// with its own body.
INTERCEPTOR(SSIZE_T, getdelim, char **lineptr, SIZE_T *n, int delim,
- void *stream) {
- return __getdelim(lineptr, n, delim, stream);
-}
+ void *stream)
+GETDELIM_INTERCEPTOR_IMPL(getdelim)
+
#define INIT_GETLINE \
COMMON_INTERCEPT_FUNCTION(getline); \
COMMON_INTERCEPT_FUNCTION(__getdelim); \
diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
index 171c6ca..789cf99 100644
--- a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
@@ -109,8 +109,9 @@
// Maximal size pc array may ever grow.
// We MmapNoReserve this space to ensure that the array is contiguous.
- static const uptr kPcArrayMaxSize =
- FIRST_32_SECOND_64(1 << (SANITIZER_ANDROID ? 24 : 26), 1 << 27);
+ static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(
+ 1 << (SANITIZER_ANDROID ? 24 : (SANITIZER_WINDOWS ? 27 : 26)),
+ 1 << 27);
// The amount file mapping for the pc array is grown by.
static const uptr kPcArrayMmapSize = 64 * 1024;
@@ -265,8 +266,9 @@
// In memory-mapped mode we must extend the new file to the known array
// size.
uptr size = atomic_load(&pc_array_size, memory_order_relaxed);
+ uptr npcs = size / sizeof(uptr);
Enable();
- if (size) Extend(size);
+ if (size) Extend(npcs);
if (coverage_enabled) CovUpdateMapping(coverage_dir);
} else {
Enable();
diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc
index ab9f0ab..7db7ce4 100644
--- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc
@@ -28,6 +28,7 @@
#include <dlfcn.h> // for dlsym()
#endif
+#include <link.h>
#include <pthread.h>
#include <signal.h>
#include <sys/resource.h>
@@ -42,9 +43,12 @@
#include <sys/prctl.h>
#endif
+#if SANITIZER_ANDROID
+#include <android/api-level.h>
+#endif
+
#if !SANITIZER_ANDROID
#include <elf.h>
-#include <link.h>
#include <unistd.h>
#endif
@@ -397,13 +401,6 @@
}
}
-#if SANITIZER_ANDROID
-uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
- string_predicate_t filter) {
- MemoryMappingLayout memory_mapping(false);
- return memory_mapping.DumpListOfModules(modules, max_modules, filter);
-}
-#else // SANITIZER_ANDROID
# if !SANITIZER_FREEBSD
typedef ElfW(Phdr) Elf_Phdr;
# elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2
@@ -451,14 +448,27 @@
return 0;
}
+#if SANITIZER_ANDROID && __ANDROID_API__ < 21
+extern "C" __attribute__((weak)) int dl_iterate_phdr(
+ int (*)(struct dl_phdr_info *, size_t, void *), void *);
+#endif
+
uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
string_predicate_t filter) {
+#if SANITIZER_ANDROID && __ANDROID_API__ < 21
+ // Fall back to /proc/maps if dl_iterate_phdr is not available.
+ // The runtime check allows the same library to work with
+ // both K and L (and future) Android releases.
+ if (!dl_iterate_phdr) {
+ MemoryMappingLayout memory_mapping(false);
+ return memory_mapping.DumpListOfModules(modules, max_modules, filter);
+ }
+#endif
CHECK(modules);
DlIteratePhdrData data = {modules, 0, true, max_modules, filter};
dl_iterate_phdr(dl_iterate_phdr_cb, &data);
return data.current_n;
}
-#endif // SANITIZER_ANDROID
// getrusage does not give us the current RSS, only the max RSS.
// Still, this is better than nothing if /proc/self/statm is not available
diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 9a6c0c0..157fa59 100644
--- a/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -204,11 +204,11 @@
#define SANITIZER_INTERCEPT_LGAMMAL_R SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_DRAND48_R SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_RAND_R SI_MAC || SI_LINUX_NOT_ANDROID
-#define SANITIZER_INTERCEPT_ICONV SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_ICONV SI_FREEBSD || SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_TIMES SI_NOT_WINDOWS
// FIXME: getline seems to be available on OSX 10.7
-#define SANITIZER_INTERCEPT_GETLINE SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_GETLINE SI_FREEBSD || SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT__EXIT SI_LINUX || SI_FREEBSD
diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index bd20bea..77bbdb1 100644
--- a/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -321,7 +321,7 @@
long pw_change;
char *pw_class;
#endif
-#if !SANITIZER_ANDROID
+#if !(SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32))
char *pw_gecos;
#endif
char *pw_dir;
@@ -383,7 +383,7 @@
};
#endif
-#if SANITIZER_ANDROID || SANITIZER_MAC || SANITIZER_FREEBSD
+#if SANITIZER_MAC || SANITIZER_FREEBSD
struct __sanitizer_msghdr {
void *msg_name;
unsigned msg_namelen;
@@ -520,6 +520,27 @@
#endif
// Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
+#if SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 64)
+ struct __sanitizer_sigaction {
+ unsigned sa_flags;
+ union {
+ void (*sigaction)(int sig, void *siginfo, void *uctx);
+ void (*handler)(int sig);
+ };
+ __sanitizer_sigset_t sa_mask;
+ void (*sa_restorer)();
+ };
+#elif SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32)
+ struct __sanitizer_sigaction {
+ union {
+ void (*sigaction)(int sig, void *siginfo, void *uctx);
+ void (*handler)(int sig);
+ };
+ __sanitizer_sigset_t sa_mask;
+ uptr sa_flags;
+ void (*sa_restorer)();
+ };
+#else // !SANITIZER_ANDROID
struct __sanitizer_sigaction {
#if defined(__mips__) && !SANITIZER_FREEBSD
unsigned int sa_flags;
@@ -544,6 +565,7 @@
int sa_resv[1];
#endif
};
+#endif // !SANITIZER_ANDROID
#if SANITIZER_FREEBSD
typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t;
diff --git a/lib/tsan/CMakeLists.txt b/lib/tsan/CMakeLists.txt
index 68862f4..e091f1a 100644
--- a/lib/tsan/CMakeLists.txt
+++ b/lib/tsan/CMakeLists.txt
@@ -41,6 +41,9 @@
rtl/tsan_symbolize.cc
rtl/tsan_sync.cc)
+set(TSAN_CXX_SOURCES
+ rtl/tsan_new_delete.cc)
+
if(APPLE)
list(APPEND TSAN_SOURCES rtl/tsan_platform_mac.cc)
elseif(UNIX)
@@ -57,6 +60,7 @@
rtl/tsan_flags.h
rtl/tsan_flags.inc
rtl/tsan_ignoreset.h
+ rtl/tsan_interceptors.h
rtl/tsan_interface_ann.h
rtl/tsan_interface.h
rtl/tsan_interface_inl.h
@@ -103,12 +107,20 @@
$<TARGET_OBJECTS:RTInterception.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
- CFLAGS ${TSAN_RTL_CFLAGS}
- DEFS ${TSAN_COMMON_DEFINITIONS})
- list(APPEND TSAN_RUNTIME_LIBRARIES clang_rt.tsan-${arch})
+ $<TARGET_OBJECTS:RTUbsan.${arch}>
+ CFLAGS ${TSAN_RTL_CFLAGS})
+ add_compiler_rt_runtime(clang_rt.tsan_cxx-${arch} ${arch} STATIC
+ SOURCES ${TSAN_CXX_SOURCES}
+ $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
+ CFLAGS ${TSAN_RTL_CFLAGS})
+ list(APPEND TSAN_RUNTIME_LIBRARIES clang_rt.tsan-${arch}
+ clang_rt.tsan_cxx-${arch})
add_sanitizer_rt_symbols(clang_rt.tsan-${arch} rtl/tsan.syms.extra)
+ add_sanitizer_rt_symbols(clang_rt.tsan_cxx-${arch} rtl/tsan.syms.extra)
add_dependencies(tsan clang_rt.tsan-${arch}
- clang_rt.tsan-${arch}-symbols)
+ clang_rt.tsan_cxx-${arch}
+ clang_rt.tsan-${arch}-symbols
+ clang_rt.tsan_cxx-${arch}-symbols)
endforeach()
endif()
diff --git a/lib/tsan/Makefile.old b/lib/tsan/Makefile.old
index fbdb9dd..b2ac912 100644
--- a/lib/tsan/Makefile.old
+++ b/lib/tsan/Makefile.old
@@ -1,7 +1,8 @@
DEBUG=0
LDFLAGS=-ldl -lrt -lpthread -pie
CXXFLAGS = -std=c++11 -fPIE -fno-rtti -g -Wall -Werror \
- -DGTEST_HAS_RTTI=0 -DSANITIZER_DEBUG=$(DEBUG)
+ -DGTEST_HAS_RTTI=0 -DSANITIZER_DEBUG=$(DEBUG) \
+ -DTSAN_CONTAINS_UBSAN=0
CLANG=clang
FILECHECK=FileCheck
# Silence warnings that Clang produces for gtest code.
diff --git a/lib/tsan/rtl/Makefile.old b/lib/tsan/rtl/Makefile.old
index 627e03b..ee7095e 100644
--- a/lib/tsan/rtl/Makefile.old
+++ b/lib/tsan/rtl/Makefile.old
@@ -1,4 +1,4 @@
-CXXFLAGS = -std=c++11 -fPIE -g -Wall -Werror -fno-builtin -msse3 -DSANITIZER_DEBUG=$(DEBUG)
+CXXFLAGS = -std=c++11 -fPIE -g -Wall -Werror -fno-builtin -msse3 -DSANITIZER_DEBUG=$(DEBUG) -DTSAN_CONTAINS_UBSAN=0
CLANG=clang
ifeq ($(DEBUG), 0)
CXXFLAGS += -O3
diff --git a/lib/tsan/rtl/tsan.syms.extra b/lib/tsan/rtl/tsan.syms.extra
index 49ed6b4..1bc1d93 100644
--- a/lib/tsan/rtl/tsan.syms.extra
+++ b/lib/tsan/rtl/tsan.syms.extra
@@ -8,6 +8,7 @@
__tsan_unaligned*
__tsan_release
__tsan_acquire
+__ubsan_*
Annotate*
WTFAnnotate*
RunningOnValgrind
diff --git a/lib/tsan/rtl/tsan_defs.h b/lib/tsan/rtl/tsan_defs.h
index 910a483..d869d95 100644
--- a/lib/tsan/rtl/tsan_defs.h
+++ b/lib/tsan/rtl/tsan_defs.h
@@ -17,6 +17,7 @@
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "tsan_stat.h"
+#include "ubsan/ubsan_platform.h"
// Setup defaults for compile definitions.
#ifndef TSAN_NO_HISTORY
@@ -27,6 +28,10 @@
# define TSAN_COLLECT_STATS 0
#endif
+#ifndef TSAN_CONTAINS_UBSAN
+# define TSAN_CONTAINS_UBSAN (CAN_SANITIZE_UB && !defined(SANITIZER_GO))
+#endif
+
namespace __tsan {
#ifdef SANITIZER_GO
diff --git a/lib/tsan/rtl/tsan_flags.cc b/lib/tsan/rtl/tsan_flags.cc
index 4c06600..5de227a 100644
--- a/lib/tsan/rtl/tsan_flags.cc
+++ b/lib/tsan/rtl/tsan_flags.cc
@@ -17,6 +17,7 @@
#include "tsan_flags.h"
#include "tsan_rtl.h"
#include "tsan_mman.h"
+#include "ubsan/ubsan_flags.h"
namespace __tsan {
@@ -54,12 +55,6 @@
}
void InitializeFlags(Flags *f, const char *env) {
- FlagParser parser;
- RegisterTsanFlags(&parser, f);
- RegisterCommonFlags(&parser);
-
- f->SetDefaults();
-
SetCommonFlagsDefaults();
{
// Override some common flags defaults.
@@ -74,10 +69,32 @@
OverrideCommonFlags(cf);
}
+ f->SetDefaults();
+
+ FlagParser parser;
+ RegisterTsanFlags(&parser, f);
+ RegisterCommonFlags(&parser);
+
+#if TSAN_CONTAINS_UBSAN
+ __ubsan::Flags *uf = __ubsan::flags();
+ uf->SetDefaults();
+
+ FlagParser ubsan_parser;
+ __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
+ RegisterCommonFlags(&ubsan_parser);
+#endif
+
// Let a frontend override.
parser.ParseString(__tsan_default_options());
+#if TSAN_CONTAINS_UBSAN
+ const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions();
+ ubsan_parser.ParseString(ubsan_default_options);
+#endif
// Override from command line.
parser.ParseString(env);
+#if TSAN_CONTAINS_UBSAN
+ ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"));
+#endif
// Sanity check.
if (!f->report_bugs) {
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc
index 24749ca..36d93e0 100644
--- a/lib/tsan/rtl/tsan_interceptors.cc
+++ b/lib/tsan/rtl/tsan_interceptors.cc
@@ -20,6 +20,7 @@
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "interception/interception.h"
+#include "tsan_interceptors.h"
#include "tsan_interface.h"
#include "tsan_platform.h"
#include "tsan_suppressions.h"
@@ -31,10 +32,8 @@
#if SANITIZER_FREEBSD
#define __errno_location __error
-#define __libc_malloc __malloc
#define __libc_realloc __realloc
#define __libc_calloc __calloc
-#define __libc_free __free
#define stdout __stdoutp
#define stderr __stderrp
#endif
@@ -78,10 +77,8 @@
extern "C" void _exit(int status);
extern "C" int *__errno_location();
extern "C" int fileno_unlocked(void *stream);
-extern "C" void *__libc_malloc(uptr size);
extern "C" void *__libc_calloc(uptr size, uptr n);
extern "C" void *__libc_realloc(void *ptr, uptr size);
-extern "C" void __libc_free(void *ptr);
extern "C" int dirfd(void *dirp);
#if !SANITIZER_FREEBSD
extern "C" int mallopt(int param, int value);
@@ -159,10 +156,6 @@
#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED \
(!cur_thread()->is_inited)
-namespace std {
-struct nothrow_t {};
-} // namespace std
-
static sigaction_t sigactions[kSigCount];
namespace __tsan {
@@ -212,16 +205,6 @@
static unsigned g_thread_finalize_key;
-class ScopedInterceptor {
- public:
- ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc);
- ~ScopedInterceptor();
- private:
- ThreadState *const thr_;
- const uptr pc_;
- bool in_ignored_lib_;
-};
-
ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
uptr pc)
: thr_(thr)
@@ -251,14 +234,6 @@
}
}
-#define SCOPED_INTERCEPTOR_RAW(func, ...) \
- ThreadState *thr = cur_thread(); \
- const uptr caller_pc = GET_CALLER_PC(); \
- ScopedInterceptor si(thr, #func, caller_pc); \
- const uptr pc = StackTrace::GetCurrentPc(); \
- (void)pc; \
-/**/
-
#define SCOPED_TSAN_INTERCEPTOR(func, ...) \
SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
if (REAL(func) == 0) { \
@@ -598,73 +573,6 @@
return user_alloc_usable_size(p);
}
-#define OPERATOR_NEW_BODY(mangled_name) \
- if (cur_thread()->in_symbolizer) \
- return __libc_malloc(size); \
- void *p = 0; \
- { \
- SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
- p = user_alloc(thr, pc, size); \
- } \
- invoke_malloc_hook(p, size); \
- return p;
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void *operator new(__sanitizer::uptr size);
-void *operator new(__sanitizer::uptr size) {
- OPERATOR_NEW_BODY(_Znwm);
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void *operator new[](__sanitizer::uptr size);
-void *operator new[](__sanitizer::uptr size) {
- OPERATOR_NEW_BODY(_Znam);
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void *operator new(__sanitizer::uptr size, std::nothrow_t const&);
-void *operator new(__sanitizer::uptr size, std::nothrow_t const&) {
- OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t);
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void *operator new[](__sanitizer::uptr size, std::nothrow_t const&);
-void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) {
- OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t);
-}
-
-#define OPERATOR_DELETE_BODY(mangled_name) \
- if (ptr == 0) return; \
- if (cur_thread()->in_symbolizer) \
- return __libc_free(ptr); \
- invoke_free_hook(ptr); \
- SCOPED_INTERCEPTOR_RAW(mangled_name, ptr); \
- user_free(thr, pc, ptr);
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void operator delete(void *ptr) throw();
-void operator delete(void *ptr) throw() {
- OPERATOR_DELETE_BODY(_ZdlPv);
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void operator delete[](void *ptr) throw();
-void operator delete[](void *ptr) throw() {
- OPERATOR_DELETE_BODY(_ZdaPv);
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void operator delete(void *ptr, std::nothrow_t const&);
-void operator delete(void *ptr, std::nothrow_t const&) {
- OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t);
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void operator delete[](void *ptr, std::nothrow_t const&);
-void operator delete[](void *ptr, std::nothrow_t const&) {
- OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t);
-}
-
TSAN_INTERCEPTOR(uptr, strlen, const char *s) {
SCOPED_TSAN_INTERCEPTOR(strlen, s);
uptr len = internal_strlen(s);
diff --git a/lib/tsan/rtl/tsan_interceptors.h b/lib/tsan/rtl/tsan_interceptors.h
new file mode 100644
index 0000000..49b79a7
--- /dev/null
+++ b/lib/tsan/rtl/tsan_interceptors.h
@@ -0,0 +1,37 @@
+#ifndef TSAN_INTERCEPTORS_H
+#define TSAN_INTERCEPTORS_H
+
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "tsan_rtl.h"
+
+namespace __tsan {
+
+class ScopedInterceptor {
+ public:
+ ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc);
+ ~ScopedInterceptor();
+ private:
+ ThreadState *const thr_;
+ const uptr pc_;
+ bool in_ignored_lib_;
+};
+
+} // namespace __tsan
+
+#define SCOPED_INTERCEPTOR_RAW(func, ...) \
+ ThreadState *thr = cur_thread(); \
+ const uptr caller_pc = GET_CALLER_PC(); \
+ ScopedInterceptor si(thr, #func, caller_pc); \
+ const uptr pc = StackTrace::GetCurrentPc(); \
+ (void)pc; \
+/**/
+
+#if SANITIZER_FREEBSD
+#define __libc_free __free
+#define __libc_malloc __malloc
+#endif
+
+extern "C" void __libc_free(void *ptr);
+extern "C" void *__libc_malloc(uptr size);
+
+#endif // TSAN_INTERCEPTORS_H
diff --git a/lib/tsan/rtl/tsan_new_delete.cc b/lib/tsan/rtl/tsan_new_delete.cc
new file mode 100644
index 0000000..2d9d044
--- /dev/null
+++ b/lib/tsan/rtl/tsan_new_delete.cc
@@ -0,0 +1,88 @@
+//===-- tsan_new_delete.cc ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Interceptors for operators new and delete.
+//===----------------------------------------------------------------------===//
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "tsan_interceptors.h"
+
+using namespace __tsan; // NOLINT
+
+namespace std {
+struct nothrow_t {};
+} // namespace std
+
+#define OPERATOR_NEW_BODY(mangled_name) \
+ if (cur_thread()->in_symbolizer) \
+ return __libc_malloc(size); \
+ void *p = 0; \
+ { \
+ SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
+ p = user_alloc(thr, pc, size); \
+ } \
+ invoke_malloc_hook(p, size); \
+ return p;
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new(__sanitizer::uptr size);
+void *operator new(__sanitizer::uptr size) {
+ OPERATOR_NEW_BODY(_Znwm);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new[](__sanitizer::uptr size);
+void *operator new[](__sanitizer::uptr size) {
+ OPERATOR_NEW_BODY(_Znam);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new(__sanitizer::uptr size, std::nothrow_t const&);
+void *operator new(__sanitizer::uptr size, std::nothrow_t const&) {
+ OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new[](__sanitizer::uptr size, std::nothrow_t const&);
+void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) {
+ OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t);
+}
+
+#define OPERATOR_DELETE_BODY(mangled_name) \
+ if (ptr == 0) return; \
+ if (cur_thread()->in_symbolizer) \
+ return __libc_free(ptr); \
+ invoke_free_hook(ptr); \
+ SCOPED_INTERCEPTOR_RAW(mangled_name, ptr); \
+ user_free(thr, pc, ptr);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr) throw();
+void operator delete(void *ptr) throw() {
+ OPERATOR_DELETE_BODY(_ZdlPv);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr) throw();
+void operator delete[](void *ptr) throw() {
+ OPERATOR_DELETE_BODY(_ZdaPv);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr, std::nothrow_t const&);
+void operator delete(void *ptr, std::nothrow_t const&) {
+ OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr, std::nothrow_t const&);
+void operator delete[](void *ptr, std::nothrow_t const&) {
+ OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t);
+}
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index ee279a3..3eddfcb 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -24,6 +24,7 @@
#include "tsan_mman.h"
#include "tsan_suppressions.h"
#include "tsan_symbolize.h"
+#include "ubsan/ubsan_init.h"
#ifdef __SSE3__
// <emmintrin.h> transitively includes <stdlib.h>,
@@ -350,6 +351,9 @@
int tid = ThreadCreate(thr, 0, 0, true);
CHECK_EQ(tid, 0);
ThreadStart(thr, tid, internal_getpid());
+#if TSAN_CONTAINS_UBSAN
+ __ubsan::InitAsPlugin();
+#endif
ctx->initialized = true;
if (flags()->stop_on_start) {
diff --git a/lib/tsan/rtl/tsan_update_shadow_word_inl.h b/lib/tsan/rtl/tsan_update_shadow_word_inl.h
index c80e0a8..6e3ac2f 100644
--- a/lib/tsan/rtl/tsan_update_shadow_word_inl.h
+++ b/lib/tsan/rtl/tsan_update_shadow_word_inl.h
@@ -38,7 +38,8 @@
}
StatInc(thr, StatShadowAnotherThread);
if (HappensBefore(old, thr)) {
- StoreIfNotYetStored(sp, &store_word);
+ if (old.IsRWWeakerOrEqual(kAccessIsWrite, kIsAtomic))
+ StoreIfNotYetStored(sp, &store_word);
break;
}
if (old.IsBothReadsOrAtomic(kAccessIsWrite, kIsAtomic))
diff --git a/test/asan/TestCases/debug_mapping.cc b/test/asan/TestCases/debug_mapping.cc
index bf6fa63..b6d5e2a 100644
--- a/test/asan/TestCases/debug_mapping.cc
+++ b/test/asan/TestCases/debug_mapping.cc
@@ -8,14 +8,14 @@
// printed because of verbosity=1
// CHECK: SHADOW_SCALE: [[SCALE:[0-9]+]]
-// CHECK: SHADOW_OFFSET: [[OFFSET:[0-9a-f]+]]
+// CHECK: SHADOW_OFFSET: [[OFFSET:0x[0-9a-f]+]]
int main() {
size_t scale, offset;
__asan_get_shadow_mapping(&scale, &offset);
- fprintf(stderr, "scale: %lx\n", scale);
- fprintf(stderr, "offset: %lx\n", offset);
+ fprintf(stderr, "scale: %d\n", (int)scale);
+ fprintf(stderr, "offset: 0x%lx\n", offset);
// CHECK: scale: [[SCALE]]
// CHECK: offset: [[OFFSET]]
diff --git a/test/lsan/TestCases/recoverable_leak_check.cc b/test/lsan/TestCases/recoverable_leak_check.cc
new file mode 100644
index 0000000..0fe377f
--- /dev/null
+++ b/test/lsan/TestCases/recoverable_leak_check.cc
@@ -0,0 +1,32 @@
+// Test for on-demand leak checking.
+// RUN: LSAN_BASE="use_stacks=0:use_registers=0"
+// RUN: %clangxx_lsan %s -o %t
+// RUN: LSAN_OPTIONS=$LSAN_BASE %run %t foo 2>&1 | FileCheck %s
+// RUN: LSAN_OPTIONS=$LSAN_BASE %run %t 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sanitizer/lsan_interface.h>
+
+void *p;
+
+int main(int argc, char *argv[]) {
+ p = malloc(23);
+
+ assert(__lsan_do_recoverable_leak_check() == 0);
+
+ fprintf(stderr, "Test alloc: %p.\n", malloc(1337));
+// CHECK: Test alloc:
+
+ assert(__lsan_do_recoverable_leak_check() == 1);
+// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer: 1337 byte
+
+ // Test that we correctly reset chunk tags.
+ p = 0;
+ assert(__lsan_do_recoverable_leak_check() == 1);
+// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer: 1360 byte
+
+ _exit(0);
+}
diff --git a/test/msan/getline.cc b/test/msan/getline.cc
index 51e105e..ee12d4d 100644
--- a/test/msan/getline.cc
+++ b/test/msan/getline.cc
@@ -7,6 +7,10 @@
// RUN: %clang_msan -O0 -xc -D_GNU_SOURCE=1 %s -o %t && %run %t %t-testdata
// RUN: %clang_msan -O2 -xc -D_GNU_SOURCE=1 %s -o %t && %run %t %t-testdata
+#if defined(__FreeBSD__)
+#define _WITH_GETLINE // To declare getline().
+#endif
+
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/test/msan/iconv.cc b/test/msan/iconv.cc
index c4f2534..c2da938 100644
--- a/test/msan/iconv.cc
+++ b/test/msan/iconv.cc
@@ -15,7 +15,12 @@
char inbuf_[100];
strcpy(inbuf_, "sample text");
char outbuf_[100];
+#if defined(__FreeBSD__)
+ // FreeBSD's iconv() expects the 2nd argument be of type 'const char**'.
+ const char *inbuf = inbuf_;
+#else
char *inbuf = inbuf_;
+#endif
char *outbuf = outbuf_;
size_t inbytesleft = strlen(inbuf_);
size_t outbytesleft = sizeof(outbuf_);
diff --git a/test/profile/instrprof-override-filename-then-reset-default.c b/test/profile/instrprof-override-filename-then-reset-default.c
new file mode 100644
index 0000000..137a3b2
--- /dev/null
+++ b/test/profile/instrprof-override-filename-then-reset-default.c
@@ -0,0 +1,19 @@
+// RUN: rm -rf %t.d
+// RUN: mkdir -p %t.d
+// RUN: cd %t.d
+// RUN: %clang_profgen -O3 %s -o %t.out
+// RUN: %run %t.out %t.d/bad.profraw
+// RUN: llvm-profdata merge -o %t.d/default.profdata %t.d/default.profraw
+// RUN: %clang_profuse=%t.d/default.profdata -o - -S -emit-llvm %s | FileCheck %s
+
+
+void __llvm_profile_override_default_filename(const char *);
+int main(int argc, const char *argv[]) {
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
+ if (argc < 2)
+ return 1;
+ __llvm_profile_override_default_filename(argv[1]);
+ __llvm_profile_override_default_filename(0);
+ return 0;
+}
+// CHECK: ![[PD1]] = !{!"branch_weights", i32 1, i32 2}
diff --git a/test/profile/instrprof-override-filename-with-env.c b/test/profile/instrprof-override-filename-with-env.c
new file mode 100644
index 0000000..cce8389
--- /dev/null
+++ b/test/profile/instrprof-override-filename-with-env.c
@@ -0,0 +1,14 @@
+// RUN: %clang_profgen -o %t -O3 %s
+// RUN: env LLVM_PROFILE_FILE=%t.good.profraw %run %t %t.bad.profraw
+// RUN: llvm-profdata merge -o %t.profdata %t.good.profraw
+// RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s
+
+void __llvm_profile_override_default_filename(const char *);
+int main(int argc, const char *argv[]) {
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
+ if (argc < 2)
+ return 1;
+ __llvm_profile_override_default_filename(argv[1]);
+ return 0;
+}
+// CHECK: ![[PD1]] = !{!"branch_weights", i32 1, i32 2}
diff --git a/test/profile/instrprof-override-filename.c b/test/profile/instrprof-override-filename.c
new file mode 100644
index 0000000..59dea29
--- /dev/null
+++ b/test/profile/instrprof-override-filename.c
@@ -0,0 +1,14 @@
+// RUN: %clang_profgen -o %t -O3 %s
+// RUN: %run %t %t.profraw
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s
+
+void __llvm_profile_override_default_filename(const char *);
+int main(int argc, const char *argv[]) {
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
+ if (argc < 2)
+ return 1;
+ __llvm_profile_override_default_filename(argv[1]);
+ return 0;
+}
+// CHECK: ![[PD1]] = !{!"branch_weights", i32 1, i32 2}
diff --git a/test/profile/instrprof-set-filename-then-reset-default.c b/test/profile/instrprof-set-filename-then-reset-default.c
new file mode 100644
index 0000000..6c07994
--- /dev/null
+++ b/test/profile/instrprof-set-filename-then-reset-default.c
@@ -0,0 +1,18 @@
+// RUN: rm -rf %t.d
+// RUN: mkdir -p %t.d
+// RUN: cd %t.d
+// RUN: %clang_profgen -O3 %s -o %t.out
+// RUN: %run %t.out %t.d/bad.profraw
+// RUN: llvm-profdata merge -o %t.d/default.profdata %t.d/default.profraw
+// RUN: %clang_profuse=%t.d/default.profdata -o - -S -emit-llvm %s | FileCheck %s
+
+void __llvm_profile_set_filename(const char *);
+int main(int argc, const char *argv[]) {
+ // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
+ if (argc < 2)
+ return 1;
+ __llvm_profile_set_filename(argv[1]);
+ __llvm_profile_set_filename(0);
+ return 0;
+}
+// CHECK: ![[PD1]] = !{!"branch_weights", i32 1, i32 2}
diff --git a/test/tsan/cond_race.cc b/test/tsan/cond_race.cc
index 52654f1..4daf37f 100644
--- a/test/tsan/cond_race.cc
+++ b/test/tsan/cond_race.cc
@@ -1,4 +1,4 @@
-// RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
+// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
// CHECK-NOT: unlock of unlocked mutex
// CHECK: ThreadSanitizer: data race
// CHECK: pthread_cond_signal
diff --git a/test/tsan/ignore_free.cc b/test/tsan/ignore_free.cc
index bb6c6ee..4e67895 100644
--- a/test/tsan/ignore_free.cc
+++ b/test/tsan/ignore_free.cc
@@ -1,4 +1,4 @@
-// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
#include "test.h"
extern "C" {
diff --git a/test/tsan/ignore_malloc.cc b/test/tsan/ignore_malloc.cc
index 1f633f0..100b4e5 100644
--- a/test/tsan/ignore_malloc.cc
+++ b/test/tsan/ignore_malloc.cc
@@ -1,4 +1,4 @@
-// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
#include "test.h"
extern "C" {
diff --git a/test/tsan/malloc_stack.cc b/test/tsan/malloc_stack.cc
index ba1d62b..f0c6f93 100644
--- a/test/tsan/malloc_stack.cc
+++ b/test/tsan/malloc_stack.cc
@@ -1,4 +1,4 @@
-// RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
+// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
#include "test.h"
_Atomic(int*) p;
diff --git a/test/tsan/mop1.c b/test/tsan/mop1.c
new file mode 100644
index 0000000..e61c5b8
--- /dev/null
+++ b/test/tsan/mop1.c
@@ -0,0 +1,40 @@
+// RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
+#include "test.h"
+
+// We want to establish the following sequence of accesses to X:
+// - main thread writes X
+// - thread2 reads X, this read happens-before the write in main thread
+// - thread1 reads X, this read is concurrent with the write in main thread
+// Write in main thread and read in thread1 should be detected as a race.
+// Previously tsan replaced write by main thread with read by thread1,
+// as the result the race was not detected.
+
+volatile long X, Y, Z;
+
+void *Thread1(void *x) {
+ barrier_wait(&barrier);
+ barrier_wait(&barrier);
+ Y = X;
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ Z = X;
+ barrier_wait(&barrier);
+ return NULL;
+}
+
+int main() {
+ barrier_init(&barrier, 2);
+ pthread_t t[2];
+ pthread_create(&t[0], 0, Thread1, 0);
+ X = 42;
+ barrier_wait(&barrier);
+ pthread_create(&t[1], 0, Thread2, 0);
+ pthread_join(t[0], 0);
+ pthread_join(t[1], 0);
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+
diff --git a/test/tsan/setuid2.c b/test/tsan/setuid2.c
new file mode 100644
index 0000000..67a6fd1
--- /dev/null
+++ b/test/tsan/setuid2.c
@@ -0,0 +1,21 @@
+// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" %run %t 2>&1 | FileCheck %s
+#include "test.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <time.h>
+
+// Test that setuid call works in presence of stoptheworld.
+
+int main() {
+ struct timespec tp0, tp1;
+ clock_gettime(CLOCK_MONOTONIC, &tp0);
+ clock_gettime(CLOCK_MONOTONIC, &tp1);
+ while (tp1.tv_sec - tp0.tv_sec < 3) {
+ clock_gettime(CLOCK_MONOTONIC, &tp1);
+ setuid(0);
+ }
+ fprintf(stderr, "DONE\n");
+ return 0;
+}
+
+// CHECK: DONE
diff --git a/test/ubsan/CMakeLists.txt b/test/ubsan/CMakeLists.txt
index 760ce60..85296a3 100644
--- a/test/ubsan/CMakeLists.txt
+++ b/test/ubsan/CMakeLists.txt
@@ -1,6 +1,20 @@
set(UBSAN_LIT_TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(UBSAN_TESTSUITES)
+set(UBSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+
+macro(add_ubsan_testsuite test_mode sanitizer arch)
+ set(UBSAN_LIT_TEST_MODE "${test_mode}")
+ set(CONFIG_NAME ${UBSAN_LIT_TEST_MODE}-${arch})
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
+ list(APPEND UBSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+ if(NOT COMPILER_RT_STANDALONE_BUILD)
+ list(APPEND UBSAN_TEST_DEPS ${sanitizer})
+ endif()
+endmacro()
+
foreach(arch ${UBSAN_SUPPORTED_ARCH})
set(UBSAN_TEST_TARGET_ARCH ${arch})
if(${arch} MATCHES "arm|aarch64")
@@ -9,28 +23,19 @@
else()
get_target_flags_for_arch(${arch} UBSAN_TEST_TARGET_CFLAGS)
endif()
- set(UBSAN_LIT_TEST_MODE "Standalone")
- set(CONFIG_NAME ${UBSAN_LIT_TEST_MODE}-${arch})
- configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
- ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
- list(APPEND UBSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+ add_ubsan_testsuite("Standalone" ubsan ${arch})
- if(COMPILER_RT_HAS_ASAN)
- set(UBSAN_LIT_TEST_MODE "AddressSanitizer")
- set(CONFIG_NAME ${UBSAN_LIT_TEST_MODE}-${arch})
- configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
- ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
- list(APPEND UBSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+ if(COMPILER_RT_HAS_ASAN AND ";${ASAN_SUPPORTED_ARCH};" MATCHES ";${arch};")
+ add_ubsan_testsuite("AddressSanitizer" asan ${arch})
+ endif()
+ if(COMPILER_RT_HAS_MSAN AND ";${MSAN_SUPPORTED_ARCH};" MATCHES ";${arch};")
+ add_ubsan_testsuite("MemorySanitizer" msan ${arch})
+ endif()
+ if(COMPILER_RT_HAS_TSAN AND ";${TSAN_SUPPORTED_ARCH};" MATCHES ";${arch};")
+ add_ubsan_testsuite("ThreadSanitizer" tsan ${arch})
endif()
endforeach()
-set(UBSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
-if(NOT COMPILER_RT_STANDALONE_BUILD)
- list(APPEND UBSAN_TEST_DEPS ubsan asan)
-endif()
-
add_lit_testsuite(check-ubsan "Running UndefinedBehaviorSanitizer tests"
${UBSAN_TESTSUITES}
DEPENDS ${UBSAN_TEST_DEPS})
diff --git a/test/ubsan/TestCases/Float/cast-overflow.cpp b/test/ubsan/TestCases/Float/cast-overflow.cpp
index 7fd6ab2..61bf431 100644
--- a/test/ubsan/TestCases/Float/cast-overflow.cpp
+++ b/test/ubsan/TestCases/Float/cast-overflow.cpp
@@ -1,4 +1,3 @@
-// FIXME: run this (and other) UBSan tests in both 32- and 64-bit modes (?).
// RUN: %clangxx -fsanitize=float-cast-overflow -g %s -o %t
// RUN: %run %t _
// RUN: env UBSAN_OPTIONS=print_summary=1 %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-0
diff --git a/test/ubsan/TestCases/Misc/Linux/coverage-levels.cc b/test/ubsan/TestCases/Misc/Linux/coverage-levels.cc
index d00b3e0..4482a08 100644
--- a/test/ubsan/TestCases/Misc/Linux/coverage-levels.cc
+++ b/test/ubsan/TestCases/Misc/Linux/coverage-levels.cc
@@ -14,6 +14,9 @@
// RUN: %clangxx -fsanitize=shift -O1 -fsanitize-coverage=3 %s -o %t
// RUN: UBSAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --check-prefix=CHECK_WARN
+// Coverage is not yet implemented in TSan.
+// XFAIL: ubsan-tsan
+
volatile int sink;
int main(int argc, char **argv) {
int shift = argc * 32;
diff --git a/test/ubsan/TestCases/Misc/Linux/ubsan_options.cc b/test/ubsan/TestCases/Misc/Linux/ubsan_options.cc
new file mode 100644
index 0000000..2be8792
--- /dev/null
+++ b/test/ubsan/TestCases/Misc/Linux/ubsan_options.cc
@@ -0,0 +1,18 @@
+// RUN: %clangxx -fsanitize=integer -fsanitize-recover=integer %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s
+
+// __ubsan_default_options() doesn't work on Darwin.
+// XFAIL: darwin
+
+#include <stdint.h>
+
+extern "C" const char *__ubsan_default_options() {
+ return "halt_on_error=1";
+}
+
+int main() {
+ (void)(uint64_t(10000000000000000000ull) + uint64_t(9000000000000000000ull));
+ // CHECK: ubsan_options.cc:[[@LINE-1]]:44: runtime error: unsigned integer overflow
+ return 0;
+}
+
diff --git a/test/ubsan/TestCases/Misc/missing_return.cpp b/test/ubsan/TestCases/Misc/missing_return.cpp
index 5d3d54d..a9b0799 100644
--- a/test/ubsan/TestCases/Misc/missing_return.cpp
+++ b/test/ubsan/TestCases/Misc/missing_return.cpp
@@ -1,15 +1,13 @@
// RUN: %clangxx -fsanitize=return -g %s -O3 -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
-// RUN: UBSAN_OPTIONS=print_stacktrace=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os-STACKTRACE
+// RUN: UBSAN_OPTIONS=print_stacktrace=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%os-STACKTRACE
// CHECK: missing_return.cpp:[[@LINE+1]]:5: runtime error: execution reached the end of a value-returning function without returning a value
int f() {
-// Slow stack unwinding is disabled on Darwin for now, see
+// Slow stack unwinding is not available on Darwin for now, see
// https://code.google.com/p/address-sanitizer/issues/detail?id=137
-// CHECK-Linux-STACKTRACE: #0 {{.*}} in f(){{.*}}missing_return.cpp:[[@LINE-3]]
-// CHECK-FreeBSD-STACKTRACE: #0 {{.*}} in f(void){{.*}}missing_return.cpp:[[@LINE-4]]
-// Check for already checked line to avoid lit error reports.
-// CHECK-Darwin-STACKTRACE: missing_return.cpp
+// CHECK-Linux-STACKTRACE: #0 {{.*}}f(){{.*}}missing_return.cpp:[[@LINE-3]]
+// CHECK-FreeBSD-STACKTRACE: #0 {{.*}}f(void){{.*}}missing_return.cpp:[[@LINE-4]]
}
int main(int, char **argv) {
diff --git a/test/ubsan/TestCases/TypeCheck/misaligned.cpp b/test/ubsan/TestCases/TypeCheck/misaligned.cpp
index 9c8455d..0c9275d 100644
--- a/test/ubsan/TestCases/TypeCheck/misaligned.cpp
+++ b/test/ubsan/TestCases/TypeCheck/misaligned.cpp
@@ -45,7 +45,7 @@
return *p && 0;
// Slow stack unwinding is disabled on Darwin for now, see
// https://code.google.com/p/address-sanitizer/issues/detail?id=137
- // CHECK-Linux-STACK-LOAD: #0 {{.*}} in main{{.*}}misaligned.cpp
+ // CHECK-Linux-STACK-LOAD: #0 {{.*}}main{{.*}}misaligned.cpp
// Check for the already checked line to avoid lit error reports.
// CHECK-Darwin-STACK-LOAD: {{ }}
diff --git a/test/ubsan/TestCases/TypeCheck/vptr.cpp b/test/ubsan/TestCases/TypeCheck/vptr.cpp
index a0681fc..6c7955b 100644
--- a/test/ubsan/TestCases/TypeCheck/vptr.cpp
+++ b/test/ubsan/TestCases/TypeCheck/vptr.cpp
@@ -1,38 +1,33 @@
-// RUN: %clangxx -frtti -fsanitize=vptr -g %s -O3 -o %t
+// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t
+// RUN: export UBSAN_OPTIONS=print_stacktrace=1
// RUN: %run %t rT && %run %t mT && %run %t fT && %run %t cT
// RUN: %run %t rU && %run %t mU && %run %t fU && %run %t cU
// RUN: %run %t rS && %run %t rV && %run %t oV
-// RUN: %run %t mS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER --strict-whitespace
-// RUN: %run %t fS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace
-// RUN: %run %t cS 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --strict-whitespace
-// RUN: %run %t mV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER --strict-whitespace
-// RUN: %run %t fV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace
-// RUN: %run %t cV 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --strict-whitespace
-// RUN: %run %t oU 2>&1 | FileCheck %s --check-prefix=CHECK-OFFSET --strict-whitespace
-// RUN: %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --strict-whitespace
+// RUN: not %run %t mS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER --check-prefix=CHECK-%os-MEMBER --strict-whitespace
+// RUN: not %run %t fS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace
+// RUN: not %run %t cS 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --check-prefix=CHECK-%os-DOWNCAST --strict-whitespace
+// RUN: not %run %t mV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER --check-prefix=CHECK-%os-MEMBER --strict-whitespace
+// RUN: not %run %t fV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace
+// RUN: not %run %t cV 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --check-prefix=CHECK-%os-DOWNCAST --strict-whitespace
+// RUN: not %run %t oU 2>&1 | FileCheck %s --check-prefix=CHECK-OFFSET --check-prefix=CHECK-%os-OFFSET --strict-whitespace
+// RUN: not %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --check-prefix=CHECK-%os-NULL-MEMBER --strict-whitespace
// RUN: (echo "vptr_check:S"; echo "vptr_check:T"; echo "vptr_check:U") > %t.supp
-// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mS 2>&1
-// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fS 2>&1
-// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cS 2>&1
-// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mV 2>&1
-// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fV 2>&1
-// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cV 2>&1
-// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t oU 2>&1
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp'" %run %t mS
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp'" %run %t fS
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp'" %run %t cS
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp'" %run %t mV
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp'" %run %t fV
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp'" %run %t cV
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp'" %run %t oU
// RUN: echo "vptr_check:S" > %t.loc-supp
-// RUN: UBSAN_OPTIONS="suppressions='%t.loc-supp':halt_on_error=1" not %run %t x- 2>&1 | FileCheck %s --check-prefix=CHECK-LOC-SUPPRESS
+// RUN: UBSAN_OPTIONS="suppressions='%t.loc-supp'" not %run %t x- 2>&1 | FileCheck %s --check-prefix=CHECK-LOC-SUPPRESS
-// FIXME: This test produces linker errors on Darwin.
-// XFAIL: darwin
// REQUIRES: stable-runtime
#include <new>
-
-extern "C" {
-const char *__ubsan_default_options() {
- return "print_stacktrace=1";
-}
-}
+#include <assert.h>
+#include <stdio.h>
struct S {
S() : a(0) {}
@@ -58,7 +53,9 @@
int access_p(T *p, char type);
-int main(int, char **argv) {
+int main(int argc, char **argv) {
+ assert(argc > 1);
+ fprintf(stderr, "Test case: %s\n", argv[1]);
T t;
(void)t.a;
(void)t.b;
@@ -107,7 +104,7 @@
case 'r':
// Binding a reference to storage of appropriate size and alignment is OK.
{T &r = *p;}
- break;
+ return 0;
case 'x':
for (int i = 0; i < 2; i++) {
@@ -128,7 +125,7 @@
// CHECK-MEMBER-NEXT: {{^ .. .. .. .. .. .. .. .. .. .. .. .. }}
// CHECK-MEMBER-NEXT: {{^ \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
// CHECK-MEMBER-NEXT: {{^ vptr for}} [[DYN_TYPE]]
- // CHECK-MEMBER-NEXT: #0 {{.*}} in access_p{{.*}}vptr.cpp:[[@LINE+1]]
+ // CHECK-Linux-MEMBER: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE+1]]
return p->b;
// CHECK-NULL-MEMBER: vptr.cpp:[[@LINE-2]]:15: runtime error: member access within address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
@@ -136,7 +133,7 @@
// CHECK-NULL-MEMBER-NEXT: {{^ ?.. .. .. .. ?00 00 00 00 ?00 00 00 00 ?}}
// CHECK-NULL-MEMBER-NEXT: {{^ \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
// CHECK-NULL-MEMBER-NEXT: {{^ invalid vptr}}
- // CHECK-NULL-MEMBER-NEXT: #0 {{.*}} in access_p{{.*}}vptr.cpp:[[@LINE-7]]
+ // CHECK-Linux-NULL-MEMBER: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE-7]]
case 'f':
// CHECK-MEMFUN: vptr.cpp:[[@LINE+6]]:12: runtime error: member call on address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
@@ -153,17 +150,18 @@
// CHECK-OFFSET-NEXT: {{^ .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. }}
// CHECK-OFFSET-NEXT: {{^ \^ ( ~~~~~~~~~~~~)?~~~~~~~~~~~ *$}}
// CHECK-OFFSET-NEXT: {{^ ( )?vptr for}} 'T' base class of [[DYN_TYPE]]
- // CHECK-OFFSET-NEXT: #0 {{.*}} in access_p{{.*}}vptr.cpp:[[@LINE+1]]
+ // CHECK-Linux-OFFSET: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE+1]]
return reinterpret_cast<U*>(p)->v() - 2;
case 'c':
- // CHECK-DOWNCAST: vptr.cpp:[[@LINE+6]]:5: runtime error: downcast of address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
+ // CHECK-DOWNCAST: vptr.cpp:[[@LINE+6]]:11: runtime error: downcast of address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
// CHECK-DOWNCAST-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:'S'|'U']]
// CHECK-DOWNCAST-NEXT: {{^ .. .. .. .. .. .. .. .. .. .. .. .. }}
// CHECK-DOWNCAST-NEXT: {{^ \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
// CHECK-DOWNCAST-NEXT: {{^ vptr for}} [[DYN_TYPE]]
- // CHECK-DOWNCAST-NEXT: #0 {{.*}} in access_p{{.*}}vptr.cpp:[[@LINE+1]]
- static_cast<T*>(reinterpret_cast<S*>(p));
+ // CHECK-Linux-DOWNCAST: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE+1]]
+ (void)static_cast<T*>(reinterpret_cast<S*>(p));
return 0;
}
+ return 0;
}
diff --git a/test/ubsan/lit.common.cfg b/test/ubsan/lit.common.cfg
index 5a406ee..5d3e78e 100644
--- a/test/ubsan/lit.common.cfg
+++ b/test/ubsan/lit.common.cfg
@@ -21,14 +21,18 @@
config.available_features.add("ubsan-standalone")
clang_ubsan_cflags = []
elif ubsan_lit_test_mode == "AddressSanitizer":
- if config.host_os == 'Darwin':
- # ubsan-asan doesn't yet work on Darwin,
- # see http://llvm.org/bugs/show_bug.cgi?id=21112.
- config.unsupported = True
config.name = 'UBSan-ASan-' + config.target_arch
config.available_features.add("ubsan-asan")
clang_ubsan_cflags = ["-fsanitize=address"]
config.environment['ASAN_OPTIONS'] = 'detect_leaks=0'
+elif ubsan_lit_test_mode == "MemorySanitizer":
+ config.name = 'UBSan-MSan-' + config.target_arch
+ config.available_features.add("ubsan-msan")
+ clang_ubsan_cflags = ["-fsanitize=memory"]
+elif ubsan_lit_test_mode == "ThreadSanitizer":
+ config.name = 'UBSan-TSan-' + config.target_arch
+ config.available_features.add("ubsan-tsan")
+ clang_ubsan_cflags = ["-fsanitize=thread"]
else:
lit_config.fatal("Unknown UBSan test mode: %r" % ubsan_lit_test_mode)