diff options
| author | Etienne Bergeron <etienneb@google.com> | 2017-02-21 16:09:38 +0000 |
|---|---|---|
| committer | Etienne Bergeron <etienneb@google.com> | 2017-02-21 16:09:38 +0000 |
| commit | fc68c2c777d1600d011e9052fec5b1885084feb4 (patch) | |
| tree | eee623c2ab1f6d4c1f6a9fb6722a16c6b4250172 | |
| parent | 4cc6dd0cf6a73b86155842d6fa9cb32b98aaba47 (diff) | |
| download | bcm5719-llvm-fc68c2c777d1600d011e9052fec5b1885084feb4.tar.gz bcm5719-llvm-fc68c2c777d1600d011e9052fec5b1885084feb4.zip | |
[compiler-rt][asan] Add support for desallocation of unhandled pointers
Summary: On windows 10, the ucrt DLL is performing allocations before the function hooking and there are multiple allocations not handled by Asan. When a free occur at the end of the process, asan is reporting desallocations not malloc-ed.
Reviewers: rnk, kcc
Reviewed By: rnk, kcc
Subscribers: kcc, llvm-commits, kubamracek, chrisha, dberris
Differential Revision: https://reviews.llvm.org/D25946
llvm-svn: 295730
| -rw-r--r-- | compiler-rt/lib/asan/asan_allocator.cc | 10 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_internal.h | 3 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_linux.cc | 1 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_mac.cc | 1 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_win.cc | 4 | ||||
| -rw-r--r-- | compiler-rt/test/asan/TestCases/Windows/dll_heap_allocation.cc | 30 | ||||
| -rw-r--r-- | compiler-rt/test/asan/lit.cfg | 22 |
7 files changed, 63 insertions, 8 deletions
diff --git a/compiler-rt/lib/asan/asan_allocator.cc b/compiler-rt/lib/asan/asan_allocator.cc index 59a2bd846ad..4be1f1ce2fa 100644 --- a/compiler-rt/lib/asan/asan_allocator.cc +++ b/compiler-rt/lib/asan/asan_allocator.cc @@ -554,7 +554,17 @@ struct Allocator { uptr chunk_beg = p - kChunkHeaderSize; AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg); + // On Windows, uninstrumented DLLs may allocate memory before ASan hooks + // malloc. Don't report an invalid free in this case. + if (SANITIZER_WINDOWS && + !get_allocator().PointerIsMine(ptr)) { + if (!IsSystemHeapAddress(p)) + ReportFreeNotMalloced(p, stack); + return; + } + ASAN_FREE_HOOK(ptr); + // Must mark the chunk as quarantined before any changes to its metadata. // Do not quarantine given chunk if we failed to set CHUNK_QUARANTINE flag. if (!AtomicallySetQuarantineFlagIfAllocated(m, ptr, stack)) return; diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h index ad516d95f0c..3b70695249e 100644 --- a/compiler-rt/lib/asan/asan_internal.h +++ b/compiler-rt/lib/asan/asan_internal.h @@ -64,6 +64,9 @@ void AsanInitFromRtl(); // asan_win.cc void InitializePlatformExceptionHandlers(); +// Returns whether an address is a valid allocated system heap block. +// 'addr' must point to the beginning of the block. +bool IsSystemHeapAddress(uptr addr); // asan_rtl.cc void NORETURN ShowStatsAndAbort(); diff --git a/compiler-rt/lib/asan/asan_linux.cc b/compiler-rt/lib/asan/asan_linux.cc index c051573dd49..6d150de790b 100644 --- a/compiler-rt/lib/asan/asan_linux.cc +++ b/compiler-rt/lib/asan/asan_linux.cc @@ -70,6 +70,7 @@ namespace __asan { void InitializePlatformInterceptors() {} void InitializePlatformExceptionHandlers() {} +bool IsSystemHeapAddress (uptr addr) { return false; } void *AsanDoesNotSupportStaticLinkage() { // This will fail to link with -static. diff --git a/compiler-rt/lib/asan/asan_mac.cc b/compiler-rt/lib/asan/asan_mac.cc index 38189a90714..3c93b26d9bf 100644 --- a/compiler-rt/lib/asan/asan_mac.cc +++ b/compiler-rt/lib/asan/asan_mac.cc @@ -48,6 +48,7 @@ namespace __asan { void InitializePlatformInterceptors() {} void InitializePlatformExceptionHandlers() {} +bool IsSystemHeapAddress (uptr addr) { return false; } // No-op. Mac does not support static linkage anyway. void *AsanDoesNotSupportStaticLinkage() { diff --git a/compiler-rt/lib/asan/asan_win.cc b/compiler-rt/lib/asan/asan_win.cc index b53d1069bcb..4ab535c42e5 100644 --- a/compiler-rt/lib/asan/asan_win.cc +++ b/compiler-rt/lib/asan/asan_win.cc @@ -277,6 +277,10 @@ void InitializePlatformExceptionHandlers() { #endif } +bool IsSystemHeapAddress(uptr addr) { + return ::HeapValidate(GetProcessHeap(), 0, (void*)addr) != FALSE; +} + // We want to install our own exception handler (EH) to print helpful reports // on access violations and whatnot. Unfortunately, the CRT initializers assume // they are run before any user code and drop any previously-installed EHs on diff --git a/compiler-rt/test/asan/TestCases/Windows/dll_heap_allocation.cc b/compiler-rt/test/asan/TestCases/Windows/dll_heap_allocation.cc new file mode 100644 index 00000000000..b4df9d4f222 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Windows/dll_heap_allocation.cc @@ -0,0 +1,30 @@ + +// RUN: %clang_cl -LD %s -Fe%t.dll -DHEAP_LIBRARY -MD +// RUN: %clang_cl %s %t.lib -Fe%t -fsanitize=address -MT +// RUN: %run %t 2>&1 | FileCheck %s + +// Check that ASan does not fail when releasing allocations that occurred within +// an uninstrumented DLL. + +#ifdef HEAP_LIBRARY +#include <memory> +#include <windows.h> + +std::unique_ptr<int> __declspec(dllexport) myglobal(new int(42)); +BOOL WINAPI DllMain(PVOID h, DWORD reason, PVOID reserved) { + return TRUE; +} + +#else + +#include <memory> +extern std::unique_ptr<int> __declspec(dllimport) myglobal; +int main(int argc, char **argv) { + printf("myglobal: %d\n", *myglobal); + return 0; +} + +#endif + +// CHECK: myglobal: 42 +// CHECK-NOT: ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed diff --git a/compiler-rt/test/asan/lit.cfg b/compiler-rt/test/asan/lit.cfg index 0a4856b11b8..7765a248ded 100644 --- a/compiler-rt/test/asan/lit.cfg +++ b/compiler-rt/test/asan/lit.cfg @@ -132,16 +132,22 @@ if config.asan_dynamic: # Windows-specific tests might also use the clang-cl.exe driver. if platform.system() == 'Windows': - clang_cl_asan_cxxflags = ["-fsanitize=address", - "-Wno-deprecated-declarations", - "-WX", - "-D_HAS_EXCEPTIONS=0", - "-Zi"] + target_cflags + clang_cl_cxxflags = ["-Wno-deprecated-declarations", + "-WX", + "-D_HAS_EXCEPTIONS=0", + "-Zi"] + target_cflags + clang_cl_asan_cxxflags = ["-fsanitize=address"] + clang_cl_cxxflags if config.asan_dynamic: clang_cl_asan_cxxflags.append("-MD") - clang_invocation = build_invocation(clang_cl_asan_cxxflags) - clang_cl_invocation = clang_invocation.replace("clang.exe","clang-cl.exe") - config.substitutions.append( ("%clang_cl_asan ", clang_cl_invocation) ) + + clang_cl_invocation = build_invocation(clang_cl_cxxflags) + clang_cl_invocation = clang_cl_invocation.replace("clang.exe","clang-cl.exe") + config.substitutions.append( ("%clang_cl ", clang_cl_invocation) ) + + clang_cl_asan_invocation = build_invocation(clang_cl_asan_cxxflags) + clang_cl_asan_invocation = clang_cl_asan_invocation.replace("clang.exe","clang-cl.exe") + config.substitutions.append( ("%clang_cl_asan ", clang_cl_asan_invocation) ) + base_lib = os.path.join(config.compiler_rt_libdir, "clang_rt.asan%%s-%s.lib" % config.target_arch) config.substitutions.append( ("%asan_lib", base_lib % "") ) config.substitutions.append( ("%asan_cxx_lib", base_lib % "_cxx") ) |

