Index: clang/lib/Driver/ToolChains/MSVC.cpp =================================================================== --- clang/lib/Driver/ToolChains/MSVC.cpp +++ clang/lib/Driver/ToolChains/MSVC.cpp @@ -486,6 +486,13 @@ } } + if (TC.getSanitizerArgs().needsScudoRt()) { + for (const auto &Lib : {"scudo", "scudo_cxx"}) { + CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); + } + CmdArgs.push_back(Args.MakeArgString("-include:malloc")); + } + Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); // Control Flow Guard checks @@ -1344,6 +1351,7 @@ Res |= SanitizerKind::PointerSubtract; Res |= SanitizerKind::Fuzzer; Res |= SanitizerKind::FuzzerNoLink; + Res |= SanitizerKind::Scudo; Res &= ~SanitizerKind::CFIMFCall; return Res; } Index: clang/lib/Driver/ToolChains/MinGW.cpp =================================================================== --- clang/lib/Driver/ToolChains/MinGW.cpp +++ clang/lib/Driver/ToolChains/MinGW.cpp @@ -260,6 +260,14 @@ } } + if (Sanitize.needsScudoRt()) { + for (const auto &Lib : {"scudo", "scudo_cxx"}) { + CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); + } + CmdArgs.push_back("--require-defined"); + CmdArgs.push_back(Args.MakeArgString("malloc")); + } + AddLibGCC(Args, CmdArgs); if (Args.hasArg(options::OPT_pg)) @@ -492,6 +500,7 @@ Res |= SanitizerKind::PointerCompare; Res |= SanitizerKind::PointerSubtract; Res |= SanitizerKind::Vptr; + Res |= SanitizerKind::Scudo; return Res; } Index: compiler-rt/cmake/config-ix.cmake =================================================================== --- compiler-rt/cmake/config-ix.cmake +++ compiler-rt/cmake/config-ix.cmake @@ -58,6 +58,7 @@ check_c_compiler_flag(-std=c11 COMPILER_RT_HAS_STD_C11_FLAG) check_cxx_compiler_flag(-fPIC COMPILER_RT_HAS_FPIC_FLAG) check_cxx_compiler_flag(-fPIE COMPILER_RT_HAS_FPIE_FLAG) +check_cxx_compiler_flag(-fbuiltin COMPILER_RT_HAS_FBUILTIN_FLAG) check_cxx_compiler_flag(-fno-builtin COMPILER_RT_HAS_FNO_BUILTIN_FLAG) check_cxx_compiler_flag(-fno-exceptions COMPILER_RT_HAS_FNO_EXCEPTIONS_FLAG) check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG) @@ -177,6 +178,8 @@ check_library_exists(log __android_log_write "" COMPILER_RT_HAS_LIBLOG) endif() +check_linker_flag("-Wl,--gc-sections" COMPILER_RT_HAS_GC_SECTIONS) + # Architectures. # List of all architectures we can target. @@ -765,7 +768,7 @@ endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND SCUDO_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|Android|Fuchsia") + OS_NAME MATCHES "Linux|Android|Fuchsia|Windows") set(COMPILER_RT_HAS_SCUDO TRUE) else() set(COMPILER_RT_HAS_SCUDO FALSE) Index: compiler-rt/lib/sanitizer_common/sanitizer_win.cpp =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_win.cpp +++ compiler-rt/lib/sanitizer_common/sanitizer_win.cpp @@ -21,6 +21,13 @@ #include #include +// #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the +// "Community Additions" comment on MSDN here: +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx +#define SystemFunction036 NTAPI SystemFunction036 +#include +#undef SystemFunction036 + #include "sanitizer_common.h" #include "sanitizer_file.h" #include "sanitizer_libc.h" @@ -1113,9 +1120,11 @@ // Do nothing. } -// FIXME: implement on this platform. +#pragma comment(lib, "advapi32.lib") bool GetRandom(void *buffer, uptr length, bool blocking) { - UNIMPLEMENTED(); + if (!buffer || !length || length > 256) + return false; + return RtlGenRandom(buffer, length) != FALSE; } u32 GetNumberOfCPUs() { Index: compiler-rt/lib/scudo/CMakeLists.txt =================================================================== --- compiler-rt/lib/scudo/CMakeLists.txt +++ compiler-rt/lib/scudo/CMakeLists.txt @@ -4,7 +4,9 @@ set(SCUDO_CFLAGS ${SANITIZER_COMMON_CFLAGS}) # SANITIZER_COMMON_CFLAGS include -fno-builtin, but we actually want builtins! -list(APPEND SCUDO_CFLAGS -fbuiltin) +if (COMPILER_RT_HAS_FBUILTIN_FLAG) + list(APPEND SCUDO_CFLAGS -fbuiltin) +endif() append_rtti_flag(OFF SCUDO_CFLAGS) set(SCUDO_MINIMAL_DYNAMIC_LIBS ${SANITIZER_COMMON_LINK_LIBS}) @@ -14,10 +16,13 @@ append_list_if(COMPILER_RT_HAS_LIBLOG log SCUDO_MINIMAL_DYNAMIC_LIBS) append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fno-omit-frame-pointer SCUDO_CFLAGS) +append_list_if(MINGW "${MINGW_LIBRARIES}" SCUDO_MINIMAL_DYNAMIC_LIBS) set(SCUDO_DYNAMIC_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) # Use gc-sections by default to avoid unused code being pulled in. -list(APPEND SCUDO_DYNAMIC_LINK_FLAGS -Wl,--gc-sections) +if (COMPILER_RT_HAS_GC_SECTIONS) + list(APPEND SCUDO_DYNAMIC_LINK_FLAGS -Wl,--gc-sections) +endif() if(ANDROID) # Put most Sanitizer shared libraries in the global group. For more details, see Index: compiler-rt/lib/scudo/scudo_allocator.cpp =================================================================== --- compiler-rt/lib/scudo/scudo_allocator.cpp +++ compiler-rt/lib/scudo/scudo_allocator.cpp @@ -44,6 +44,12 @@ // at compilation or at runtime. static atomic_uint8_t HashAlgorithm = { CRC32Software }; +#if !SANITIZER_SUPPORTS_WEAK_HOOKS +SANITIZER_WEAK_ATTRIBUTE u32 computeHardwareCRC32(u32 Crc, uptr Data) { + return computeSoftwareCRC32(Crc, Data); +} +#endif + inline u32 computeCRC32(u32 Crc, uptr Value, uptr *Array, uptr ArraySize) { // If the hardware CRC32 feature is defined here, it was enabled everywhere, // as opposed to only for scudo_crc32.cpp. This means that other hardware @@ -608,8 +614,8 @@ // result, the maximum offset will be at most the maximum alignment for the // last size class minus the header size, in multiples of MinAlignment. UnpackedHeader Header = {}; - const uptr MaxPrimaryAlignment = - 1 << MostSignificantSetBitIndex(SizeClassMap::kMaxSize - MinAlignment); + const uptr MaxPrimaryAlignment = (uptr)1U << MostSignificantSetBitIndex( + SizeClassMap::kMaxSize - MinAlignment); const uptr MaxOffset = (MaxPrimaryAlignment - Chunk::getHeaderSize()) >> MinAlignmentLog; Header.Offset = MaxOffset; Index: compiler-rt/lib/scudo/scudo_crc32.cpp =================================================================== --- compiler-rt/lib/scudo/scudo_crc32.cpp +++ compiler-rt/lib/scudo/scudo_crc32.cpp @@ -15,10 +15,13 @@ namespace __scudo { +// Can't override this with weak symbols on Windows +#if !defined(_WIN32) #if defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) u32 computeHardwareCRC32(u32 Crc, uptr Data) { return CRC32_INTRINSIC(Crc, Data); } #endif // defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) +#endif // defined(_WIN32) } // namespace __scudo Index: compiler-rt/lib/scudo/scudo_new_delete.cpp =================================================================== --- compiler-rt/lib/scudo/scudo_new_delete.cpp +++ compiler-rt/lib/scudo/scudo_new_delete.cpp @@ -19,7 +19,32 @@ using namespace __scudo; +// C++ operators can't have dllexport attributes on Windows. We export them +// anyway by passing extra -export flags to the linker, which is exactly that +// dllexport would normally do. We need to export them in order to make the +// VS2015 dynamic CRT (MD) work. +#if SANITIZER_WINDOWS && !defined(__MINGW32__) +#define CXX_OPERATOR_ATTRIBUTE +#define COMMENT_EXPORT(sym) __pragma(comment(linker, "/export:" sym)) +#ifdef _WIN64 +COMMENT_EXPORT("??2@YAPEAX_K@Z") // operator new +COMMENT_EXPORT("??2@YAPEAX_KAEBUnothrow_t@std@@@Z") // operator new nothrow +COMMENT_EXPORT("??3@YAXPEAX@Z") // operator delete +COMMENT_EXPORT("??3@YAXPEAX_K@Z") // sized operator delete +COMMENT_EXPORT("??_U@YAPEAX_K@Z") // operator new[] +COMMENT_EXPORT("??_V@YAXPEAX@Z") // operator delete[] +#else +COMMENT_EXPORT("??2@YAPAXI@Z") // operator new +COMMENT_EXPORT("??2@YAPAXIABUnothrow_t@std@@@Z") // operator new nothrow +COMMENT_EXPORT("??3@YAXPAX@Z") // operator delete +COMMENT_EXPORT("??3@YAXPAXI@Z") // sized operator delete +COMMENT_EXPORT("??_U@YAPAXI@Z") // operator new[] +COMMENT_EXPORT("??_V@YAXPAX@Z") // operator delete[] +#endif +#undef COMMENT_EXPORT +#else #define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE +#endif // Fake std::nothrow_t to avoid including . namespace std { Index: compiler-rt/lib/scudo/scudo_platform.h =================================================================== --- compiler-rt/lib/scudo/scudo_platform.h +++ compiler-rt/lib/scudo/scudo_platform.h @@ -16,29 +16,26 @@ #include "sanitizer_common/sanitizer_allocator.h" -#if !SANITIZER_LINUX && !SANITIZER_FUCHSIA +#if !SANITIZER_LINUX && !SANITIZER_FUCHSIA && !SANITIZER_WINDOWS # error "The Scudo hardened allocator is not supported on this platform." #endif -#define SCUDO_TSD_EXCLUSIVE_SUPPORTED (!SANITIZER_ANDROID && !SANITIZER_FUCHSIA) +#define SCUDO_TSD_EXCLUSIVE_SUPPORTED \ + (!SANITIZER_ANDROID && !SANITIZER_FUCHSIA && !SANITIZER_WINDOWS) #ifndef SCUDO_TSD_EXCLUSIVE // SCUDO_TSD_EXCLUSIVE wasn't defined, use a default TSD model for the platform. -# if SANITIZER_ANDROID || SANITIZER_FUCHSIA -// Android and Fuchsia use a pool of TSDs shared between threads. -# define SCUDO_TSD_EXCLUSIVE 0 -# elif SANITIZER_LINUX && !SANITIZER_ANDROID -// Non-Android Linux use an exclusive TSD per thread. +#if SCUDO_TSD_EXCLUSIVE_SUPPORTED # define SCUDO_TSD_EXCLUSIVE 1 # else -# error "No default TSD model defined for this platform." -# endif // SANITIZER_ANDROID || SANITIZER_FUCHSIA -#endif // SCUDO_TSD_EXCLUSIVE - +#define SCUDO_TSD_EXCLUSIVE 0 +#endif // SCUDO_TSD_EXCLUSIVE_SUPPORTED +#else // If the exclusive TSD model is chosen, make sure the platform supports it. #if SCUDO_TSD_EXCLUSIVE && !SCUDO_TSD_EXCLUSIVE_SUPPORTED # error "The exclusive TSD model is not supported on this platform." #endif +#endif // SCUDO_TSD_EXCLUSIVE // Maximum number of TSDs that can be created for the Shared model. #ifndef SCUDO_SHARED_TSD_POOL_SIZE @@ -71,6 +68,14 @@ const uptr AllocatorSize = 0x4000000000ULL; // 256G. # elif defined(__aarch64__) const uptr AllocatorSize = 0x10000000000ULL; // 1T. +#elif SANITIZER_WINDOWS +// Avoid pathological case in the Windows NT Kernel hit with 4TB size. +// For some reason, the application's VAD (Virtual Address Descriptor) tree is +// not cleared right away, but deferred to the system zero thread. Since that +// thread is low-priority, the VAD trees are accumulating in the "Active List", +// until it hits the physical memory limit, then it goes to swap, then at some +// point the VirtualAlloc calls in the application fail. +const uptr AllocatorSize = 0x4000000000ULL; // 256G. # else const uptr AllocatorSize = 0x40000000000ULL; // 4T. # endif Index: compiler-rt/lib/scudo/scudo_tsd.h =================================================================== --- compiler-rt/lib/scudo/scudo_tsd.h +++ compiler-rt/lib/scudo/scudo_tsd.h @@ -18,7 +18,11 @@ #include "scudo_allocator.h" #include "scudo_utils.h" +#if !SANITIZER_WINDOWS #include +#else +#include +#endif // SANITIZER_WINDOWS namespace __scudo { Index: compiler-rt/lib/scudo/scudo_tsd_shared.cpp =================================================================== --- compiler-rt/lib/scudo/scudo_tsd_shared.cpp +++ compiler-rt/lib/scudo/scudo_tsd_shared.cpp @@ -16,8 +16,13 @@ namespace __scudo { +#if !SANITIZER_WINDOWS static pthread_once_t GlobalInitialized = PTHREAD_ONCE_INIT; pthread_key_t PThreadKey; +#else +DWORD TlsIndex = TLS_OUT_OF_INDEXES; +static INIT_ONCE InitOnce = INIT_ONCE_STATIC_INIT; +#endif static atomic_uint32_t CurrentIndex; static ScudoTSD *TSDs; @@ -31,7 +36,12 @@ #endif static void initOnce() { +#if SANITIZER_WINDOWS + TlsIndex = TlsAlloc(); + CHECK_NE(TlsIndex, TLS_OUT_OF_INDEXES); +#elif !SANITIZER_ANDROID CHECK_EQ(pthread_key_create(&PThreadKey, NULL), 0); +#endif initScudo(); NumberOfTSDs = Min(Max(1U, GetNumberOfCPUsCached()), static_cast(SCUDO_SHARED_TSD_POOL_SIZE)); @@ -48,7 +58,9 @@ } ALWAYS_INLINE void setCurrentTSD(ScudoTSD *TSD) { -#if SANITIZER_ANDROID +#if SANITIZER_WINDOWS + CHECK(TlsSetValue(TlsIndex, reinterpret_cast(TSD))); +#elif SANITIZER_ANDROID *get_android_tls_ptr() = reinterpret_cast(TSD); #elif SANITIZER_LINUX CurrentTSD = TSD; @@ -57,8 +69,20 @@ #endif // SANITIZER_ANDROID } +#if SANITIZER_WINDOWS +static BOOL CALLBACK handleInit(PINIT_ONCE InitOnce, PVOID Parameter, + PVOID *Context) { + initOnce(); + return TRUE; +} +#endif + void initThread(bool MinimalInit) { +#if SANITIZER_WINDOWS + CHECK(InitOnceExecuteOnce(&InitOnce, handleInit, nullptr, nullptr)); +#else pthread_once(&GlobalInitialized, initOnce); +#endif // Initial context assignment is done in a plain round-robin fashion. u32 Index = atomic_fetch_add(&CurrentIndex, 1, memory_order_relaxed); setCurrentTSD(&TSDs[Index % NumberOfTSDs]); Index: compiler-rt/lib/scudo/scudo_tsd_shared.inc =================================================================== --- compiler-rt/lib/scudo/scudo_tsd_shared.inc +++ compiler-rt/lib/scudo/scudo_tsd_shared.inc @@ -16,7 +16,11 @@ #if !SCUDO_TSD_EXCLUSIVE +#if SANITIZER_WINDOWS +extern DWORD TlsIndex; +#elif !SANITIZER_ANDROID extern pthread_key_t PThreadKey; +#endif #if SANITIZER_LINUX && !SANITIZER_ANDROID __attribute__((tls_model("initial-exec"))) @@ -24,7 +28,9 @@ #endif ALWAYS_INLINE ScudoTSD* getCurrentTSD() { -#if SANITIZER_ANDROID +#if SANITIZER_WINDOWS + return reinterpret_cast(TlsGetValue(TlsIndex)); +#elif SANITIZER_ANDROID return reinterpret_cast(*get_android_tls_ptr()); #elif SANITIZER_LINUX return CurrentTSD; Index: compiler-rt/test/scudo/cxx_threads.cpp =================================================================== --- /dev/null +++ compiler-rt/test/scudo/cxx_threads.cpp @@ -0,0 +1,73 @@ +// RUN: %clangxx_scudo %s -o %t +// RUN: %env_scudo_opts="QuarantineSizeKb=0:ThreadLocalQuarantineSizeKb=0" %run %t 5 1000000 2>&1 +// RUN: %env_scudo_opts="QuarantineSizeKb=1024:ThreadLocalQuarantineSizeKb=64" %run %t 5 1000000 2>&1 + +// Tests parallel allocations and deallocations of memory chunks from a number +// of concurrent threads, with and without quarantine. +// This test passes if everything executes properly without crashing. + +#include +#include +#include +#include +#include + +#include + +int num_threads; +int total_num_alloc; +const int kMaxNumThreads = 500; +std::thread thread[kMaxNumThreads]; + +std::condition_variable cond; +std::mutex mutex; +char go = 0; + +void *thread_fun(void *arg) { + mutex.lock(); + while (!go) { + std::unique_lock lk(mutex); + cond.wait(lk); + } + + mutex.unlock(); + for (int i = 0; i < total_num_alloc / num_threads; i++) { + void *p = malloc(10); + __asm__ __volatile__("" + : + : "r"(p) + : "memory"); + free(p); + } + return 0; +} + +int main(int argc, char **argv) { + assert(argc == 3); + num_threads = atoi(argv[1]); + assert(num_threads > 0); + assert(num_threads <= kMaxNumThreads); + total_num_alloc = atoi(argv[2]); + assert(total_num_alloc > 0); + + printf("%d threads, %d allocations in each\n", num_threads, + total_num_alloc / num_threads); + fprintf(stderr, "Heap size before: %zd\n", __sanitizer_get_heap_size()); + fprintf(stderr, "Allocated bytes before: %zd\n", + __sanitizer_get_current_allocated_bytes()); + + mutex.lock(); + for (int i = 0; i < num_threads; i++) + thread[i] = std::thread(thread_fun, (void *)0); + go = 1; + cond.notify_all(); + mutex.unlock(); + for (int i = 0; i < num_threads; i++) + thread[i].join(); + + fprintf(stderr, "Heap size after: %zd\n", __sanitizer_get_heap_size()); + fprintf(stderr, "Allocated bytes after: %zd\n", + __sanitizer_get_current_allocated_bytes()); + + return 0; +} Index: compiler-rt/test/scudo/dealloc-race.c =================================================================== --- compiler-rt/test/scudo/dealloc-race.c +++ compiler-rt/test/scudo/dealloc-race.c @@ -1,3 +1,5 @@ +// UNSUPPORTED: windows + // RUN: %clang_scudo %s -O2 -o %t // RUN: %env_scudo_opts="QuarantineChunksUpToSize=0" %run %t 2>&1 Index: compiler-rt/test/scudo/fsanitize.c =================================================================== --- compiler-rt/test/scudo/fsanitize.c +++ compiler-rt/test/scudo/fsanitize.c @@ -1,5 +1,7 @@ // Test various -fsanitize= additional flags combinations. +// UNSUPPORTED: windows + // RUN: %clang_scudo %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s Index: compiler-rt/test/scudo/interface.cpp =================================================================== --- compiler-rt/test/scudo/interface.cpp +++ compiler-rt/test/scudo/interface.cpp @@ -10,13 +10,30 @@ #include #include #include +#if defined(_WIN32) +#include +#else #include +#endif #include #include #include +#if defined(_MSC_VER) +#include +typedef SSIZE_T ssize_t; +#endif + +void sleep_ms(unsigned int ms) { +#if defined(_WIN32) + Sleep(ms); +#else + usleep(ms * 1000U); +#endif +} + int main(int argc, char **argv) { assert(argc == 2); @@ -57,7 +74,7 @@ } // Set the soft RSS limit to 1Mb. __scudo_set_rss_limit(1, 0); - usleep(20000); + sleep_ms(200); // The following allocation should return NULL. void *p = malloc(size); assert(!p); @@ -83,7 +100,7 @@ } // Set the hard RSS limit to 1Mb __scudo_set_rss_limit(1, 1); - usleep(20000); + sleep_ms(200); // The following should trigger our death. void *p = malloc(size); } Index: compiler-rt/test/scudo/lit.cfg.py =================================================================== --- compiler-rt/test/scudo/lit.cfg.py +++ compiler-rt/test/scudo/lit.cfg.py @@ -17,19 +17,22 @@ # C & CXX flags. c_flags = ([config.target_cflags] + - ["-pthread", - "-fPIE", - "-pie", - "-O0", - "-UNDEBUG", - "-ldl", - "-Wl,--gc-sections"]) + ["-O0", + "-UNDEBUG"]) -# Android doesn't want -lrt. -if not config.android: - c_flags += ["-lrt"] +if config.host_os != 'Windows': + c_flags += ["-pthread", + "-fPIE", + "-pie", + "-ldl", + "-Wl,--gc-sections"] + # Android doesn't want -lrt. + if not config.android: + c_flags += ["-lrt"] -cxx_flags = (c_flags + config.cxx_mode_flags + ["-std=c++11"]) +cxx_flags = (c_flags + config.cxx_mode_flags) +if config.host_os != 'Windows': + cxx_flags += ["-std=c++11"] scudo_flags = ["-fsanitize=scudo"] @@ -59,6 +62,6 @@ config.substitutions.append(('%env_scudo_opts=', 'env SCUDO_OPTIONS=' + default_scudo_opts)) -# Hardened Allocator tests are currently supported on Linux only. -if config.host_os not in ['Linux']: +# Hardened Allocator tests are currently supported on Linux and Windows only. +if config.host_os not in ['Linux', 'Windows']: config.unsupported = True Index: compiler-rt/test/scudo/malloc.cpp =================================================================== --- compiler-rt/test/scudo/malloc.cpp +++ compiler-rt/test/scudo/malloc.cpp @@ -11,6 +11,11 @@ #include +#if defined(_MSC_VER) +#include +typedef SSIZE_T ssize_t; +#endif + int main(int argc, char **argv) { void *p; Index: compiler-rt/test/scudo/memalign.c =================================================================== --- compiler-rt/test/scudo/memalign.c +++ compiler-rt/test/scudo/memalign.c @@ -5,6 +5,7 @@ // RUN: not %run %t double-free 2>&1 | FileCheck --check-prefix=CHECK-double-free %s // RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t realloc 2>&1 | FileCheck --check-prefix=CHECK-realloc %s // RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t realloc 2>&1 +// UNSUPPORTED: windows // Tests that the various aligned allocation functions work as intended. Also // tests for the condition where the alignment is not a power of 2. Index: compiler-rt/test/scudo/mismatch.cpp =================================================================== --- compiler-rt/test/scudo/mismatch.cpp +++ compiler-rt/test/scudo/mismatch.cpp @@ -28,4 +28,3 @@ } // CHECK-dealloc: ERROR: allocation type mismatch when deallocating address -// CHECK-realloc: ERROR: allocation type mismatch when reallocating address Index: compiler-rt/test/scudo/overflow.c =================================================================== --- compiler-rt/test/scudo/overflow.c +++ compiler-rt/test/scudo/overflow.c @@ -8,6 +8,11 @@ #include #include +#if defined(_MSC_VER) +#include +typedef SSIZE_T ssize_t; +#endif + int main(int argc, char **argv) { ssize_t offset = sizeof(void *) == 8 ? 8 : 0; Index: compiler-rt/test/scudo/preload.cpp =================================================================== --- compiler-rt/test/scudo/preload.cpp +++ compiler-rt/test/scudo/preload.cpp @@ -5,7 +5,7 @@ // RUN: env LD_PRELOAD=%shared_minlibscudo not %run %t 2>&1 | FileCheck %s // This way of setting LD_PRELOAD does not work with Android test runner. -// REQUIRES: !android +// UNSUPPORTED: android, windows #include Index: compiler-rt/test/scudo/rss.c =================================================================== --- compiler-rt/test/scudo/rss.c +++ compiler-rt/test/scudo/rss.c @@ -20,19 +20,31 @@ #include #include #include +#if defined(_WIN32) +#include +#else #include +#endif static const size_t kNumAllocs = 64; static const size_t kAllocSize = 1 << 20; // 1MB. static void *allocs[kNumAllocs]; +void sleep_ms(unsigned int ms) { +#if defined(_WIN32) + Sleep(ms); +#else + usleep(ms * 1000U); +#endif +} + int main(int argc, char *argv[]) { int returned_null = 0; for (int i = 0; i < kNumAllocs; i++) { // sleep for 100ms every 8 allocations, to allow the RSS check to catch up. if (i != 0 && (i & 0x7) == 0) - usleep(100000); + sleep_ms(100); allocs[i] = malloc(kAllocSize); if (allocs[i]) memset(allocs[i], 0xff, kAllocSize); // Dirty the pages. Index: compiler-rt/test/scudo/secondary.c =================================================================== --- compiler-rt/test/scudo/secondary.c +++ compiler-rt/test/scudo/secondary.c @@ -6,37 +6,60 @@ // allocated by the Secondary allocator, or writing too far in front of it. #include -#include -#include +#include #include #include +#ifdef _WIN32 +#include +#else +#include #include +#endif +#ifdef _WIN32 +DWORD getsystempagesize() { + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwPageSize; +} +LONG WINAPI handler(EXCEPTION_POINTERS *ExceptionInfo) { + fprintf(stderr, "AccessViolation\n"); + ExitProcess(0); +} +#else void handler(int signo, siginfo_t *info, void *uctx) { if (info->si_code == SEGV_ACCERR) { - fprintf(stderr, "SCUDO SIGSEGV\n"); + fprintf(stderr, "AccessViolation\n"); exit(0); } exit(1); } +long getsystempagesize() { + return sysconf(_SC_PAGESIZE); +} +#endif int main(int argc, char **argv) { // The size must be large enough to be serviced by the secondary allocator. - long page_size = sysconf(_SC_PAGESIZE); - size_t size = (1U << 17) + page_size; - struct sigaction a; + long page_size = getsystempagesize(); + size_t size = (1U << 19) + page_size; assert(argc == 2); - memset(&a, 0, sizeof(a)); - a.sa_sigaction = handler; - a.sa_flags = SA_SIGINFO; char *p = (char *)malloc(size); assert(p); memset(p, 'A', size); // This should not trigger anything. // Set up the SIGSEGV handler now, as the rest should trigger an AV. +#ifdef _WIN32 + SetUnhandledExceptionFilter(handler); +#else + struct sigaction a = {0}; + a.sa_sigaction = handler; + a.sa_flags = SA_SIGINFO; sigaction(SIGSEGV, &a, NULL); +#endif + if (!strcmp(argv[1], "after")) { for (int i = 0; i < page_size; i++) p[size + i] = 'A'; @@ -50,4 +73,4 @@ return 1; // A successful test means we shouldn't reach this. } -// CHECK: SCUDO SIGSEGV +// CHECK: AccessViolation Index: compiler-rt/test/scudo/symbols.test =================================================================== --- compiler-rt/test/scudo/symbols.test +++ compiler-rt/test/scudo/symbols.test @@ -1,4 +1,4 @@ -UNSUPPORTED: android +UNSUPPORTED: android, windows Verify that various functions are *not* present in the minimal binary. Presence of those symbols in the minimal runtime would mean that the split code made it Index: compiler-rt/test/scudo/threads.c =================================================================== --- compiler-rt/test/scudo/threads.c +++ compiler-rt/test/scudo/threads.c @@ -1,6 +1,7 @@ // RUN: %clang_scudo %s -o %t // RUN: %env_scudo_opts="QuarantineSizeKb=0:ThreadLocalQuarantineSizeKb=0" %run %t 5 1000000 2>&1 // RUN: %env_scudo_opts="QuarantineSizeKb=1024:ThreadLocalQuarantineSizeKb=64" %run %t 5 1000000 2>&1 +// UNSUPPORTED: windows // Tests parallel allocations and deallocations of memory chunks from a number // of concurrent threads, with and without quarantine. Index: compiler-rt/test/scudo/tsd_destruction.c =================================================================== --- compiler-rt/test/scudo/tsd_destruction.c +++ compiler-rt/test/scudo/tsd_destruction.c @@ -1,5 +1,6 @@ // RUN: %clang_scudo %s -o %t // RUN: %run %t 2>&1 +// UNSUPPORTED: windows #include #include Index: compiler-rt/test/scudo/valloc.c =================================================================== --- compiler-rt/test/scudo/valloc.c +++ compiler-rt/test/scudo/valloc.c @@ -2,7 +2,7 @@ // RUN: %run %t valid 2>&1 // RUN: not %run %t invalid 2>&1 | FileCheck %s // RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1 -// UNSUPPORTED: android +// UNSUPPORTED: android, windows // Tests that valloc and pvalloc work as intended.