[ASan/Win] Add handling of C++ exceptions to the RTL
authorTimur Iskhodzhanov <timurrrr@google.com>
Tue, 22 Jul 2014 12:37:51 +0000 (12:37 +0000)
committerTimur Iskhodzhanov <timurrrr@google.com>
Tue, 22 Jul 2014 12:37:51 +0000 (12:37 +0000)
Also add a longjmp() test

llvm-svn: 213649

compiler-rt/lib/asan/asan_interceptors.cc
compiler-rt/test/asan/TestCases/Windows/longjmp.cc [new file with mode: 0644]
compiler-rt/test/asan/TestCases/Windows/throw_catch.cc [new file with mode: 0644]

index 4ae03ec..3638317 100644 (file)
@@ -295,6 +295,14 @@ INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
 }
 #endif
 
+#if SANITIZER_WINDOWS
+INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
+  CHECK(REAL(RaiseException));
+  __asan_handle_no_return();
+  REAL(RaiseException)(a, b, c, d);
+}
+#endif
+
 #if ASAN_INTERCEPT_MLOCKX
 // intercept mlock and friends.
 // Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
@@ -728,6 +736,7 @@ INTERCEPTOR_WINAPI(DWORD, CreateThread,
 namespace __asan {
 void InitializeWindowsInterceptors() {
   ASAN_INTERCEPT_FUNC(CreateThread);
+  ASAN_INTERCEPT_FUNC(RaiseException);
 }
 
 }  // namespace __asan
diff --git a/compiler-rt/test/asan/TestCases/Windows/longjmp.cc b/compiler-rt/test/asan/TestCases/Windows/longjmp.cc
new file mode 100644 (file)
index 0000000..443933e
--- /dev/null
@@ -0,0 +1,26 @@
+// RUN: %clangxx_asan -O %s -o %t && %run %t
+
+// FIXME: merge this with the common longjmp test when we can run common
+// tests on Windows.
+
+#include <assert.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <sanitizer/asan_interface.h>
+
+static jmp_buf buf;
+
+int main() {
+  char x[32];
+  fprintf(stderr, "\nTestLongJmp\n");
+  fprintf(stderr, "Before: %p poisoned: %d\n", &x,
+          __asan_address_is_poisoned(x + 32));
+  assert(__asan_address_is_poisoned(x + 32));
+  if (0 == setjmp(buf))
+    longjmp(buf, 1);
+  fprintf(stderr, "After:  %p poisoned: %d\n",  &x,
+          __asan_address_is_poisoned(x + 32));
+  // FIXME: Invert this assertion once we fix
+  // https://code.google.com/p/address-sanitizer/issues/detail?id=258
+  assert(!__asan_address_is_poisoned(x + 32));
+}
diff --git a/compiler-rt/test/asan/TestCases/Windows/throw_catch.cc b/compiler-rt/test/asan/TestCases/Windows/throw_catch.cc
new file mode 100644 (file)
index 0000000..e60f57d
--- /dev/null
@@ -0,0 +1,73 @@
+// Clang doesn't support exceptions on Windows yet, so for the time being we
+// build this program in two parts: the code with exceptions is built with CL,
+// the rest is built with Clang.  This represents the typical scenario when we
+// build a large project using "clang-cl -fallback -fsanitize=address".
+//
+// RUN: cl -Zi -FS -c %s -Fo%t.obj
+// RUN: %clangxx_asan -o %t.exe %s %t.obj
+// RUN: %run %t.exe
+
+#include <assert.h>
+#include <stdio.h>
+
+// Should just "#include <sanitizer/asan_interface.h>" when C++ exceptions are
+// supported and we don't need to use CL.
+extern "C" bool __asan_address_is_poisoned(void *p);
+
+void ThrowAndCatch();
+void TestThrowInline();
+
+#if !defined(__clang__)
+__declspec(noinline)
+void Throw() {
+  int local;
+  fprintf(stderr, "Throw:  %p\n", &local);
+  throw 1;
+}
+
+__declspec(noinline)
+void ThrowAndCatch() {
+  int local;
+  try {
+    Throw();
+  } catch(...) {
+    fprintf(stderr, "Catch:  %p\n", &local);
+  }
+}
+
+void TestThrowInline() {
+  char x[32];
+  fprintf(stderr, "Before: %p poisoned: %d\n", &x,
+          __asan_address_is_poisoned(x + 32));
+  try {
+    Throw();
+  } catch(...) {
+    fprintf(stderr, "Catch\n");
+  }
+  fprintf(stderr, "After:  %p poisoned: %d\n",  &x,
+          __asan_address_is_poisoned(x + 32));
+  // FIXME: Invert this assertion once we fix
+  // https://code.google.com/p/address-sanitizer/issues/detail?id=258
+  assert(!__asan_address_is_poisoned(x + 32));
+}
+
+#else
+
+void TestThrow() {
+  char x[32];
+  fprintf(stderr, "Before: %p poisoned: %d\n", &x,
+          __asan_address_is_poisoned(x + 32));
+  assert(__asan_address_is_poisoned(x + 32));
+  ThrowAndCatch();
+  fprintf(stderr, "After:  %p poisoned: %d\n",  &x,
+          __asan_address_is_poisoned(x + 32));
+  // FIXME: Invert this assertion once we fix
+  // https://code.google.com/p/address-sanitizer/issues/detail?id=258
+  assert(!__asan_address_is_poisoned(x + 32));
+}
+
+int main(int argc, char **argv) {
+  TestThrowInline();
+  TestThrow();
+}
+#endif