[ASan] port interception and shared library tests to lit

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@161933 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/asan/lit_tests/Linux/interception_failure_test.cc b/lib/asan/lit_tests/Linux/interception_failure_test.cc
new file mode 100644
index 0000000..0157264
--- /dev/null
+++ b/lib/asan/lit_tests/Linux/interception_failure_test.cc
@@ -0,0 +1,20 @@
+// If user provides his own libc functions, ASan doesn't
+// intercept these functions.
+
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <stdio.h>
+
+extern "C" long strtol(const char *nptr, char **endptr, int base) {
+  fprintf(stderr, "my_strtol_interceptor\n");
+  return 0;
+}
+
+int main() {
+  char *x = (char*)malloc(10 * sizeof(char));
+  free(x);
+  return (int)strtol(x, 0, 10);
+  // CHECK: my_strtol_interceptor
+  // CHECK-NOT: heap-use-after-free
+}
diff --git a/lib/asan/lit_tests/Linux/interception_malloc_test.cc b/lib/asan/lit_tests/Linux/interception_malloc_test.cc
new file mode 100644
index 0000000..4f1a092
--- /dev/null
+++ b/lib/asan/lit_tests/Linux/interception_malloc_test.cc
@@ -0,0 +1,21 @@
+// ASan interceptor can be accessed with __interceptor_ prefix.
+
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+extern "C" void *__interceptor_malloc(size_t size);
+extern "C" void *malloc(size_t size) {
+  write(2, "malloc call\n", sizeof("malloc call\n") - 1);
+  return __interceptor_malloc(size);
+}
+
+int main() {
+  char *x = (char*)malloc(10 * sizeof(char));
+  free(x);
+  return (int)strtol(x, 0, 10);
+  // CHECK: malloc call
+  // CHECK: heap-use-after-free
+}
diff --git a/lib/asan/lit_tests/Linux/interception_test.cc b/lib/asan/lit_tests/Linux/interception_test.cc
new file mode 100644
index 0000000..01111f1
--- /dev/null
+++ b/lib/asan/lit_tests/Linux/interception_test.cc
@@ -0,0 +1,20 @@
+// ASan interceptor can be accessed with __interceptor_ prefix.
+
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <stdio.h>
+
+extern "C" long __interceptor_strtol(const char *nptr, char **endptr, int base);
+extern "C" long strtol(const char *nptr, char **endptr, int base) {
+  fprintf(stderr, "my_strtol_interceptor\n");
+  return __interceptor_strtol(nptr, endptr, base);
+}
+
+int main() {
+  char *x = (char*)malloc(10 * sizeof(char));
+  free(x);
+  return (int)strtol(x, 0, 10);
+  // CHECK: my_strtol_interceptor
+  // CHECK: heap-use-after-free
+}
diff --git a/lib/asan/lit_tests/SharedLibs/dlclose-test-so.cc b/lib/asan/lit_tests/SharedLibs/dlclose-test-so.cc
new file mode 100644
index 0000000..73e0050
--- /dev/null
+++ b/lib/asan/lit_tests/SharedLibs/dlclose-test-so.cc
@@ -0,0 +1,33 @@
+//===----------- dlclose-test-so.cc -----------------------------*- C++ -*-===//
+//
+//                     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 AddressSanitizer, an address sanity checker.
+//
+// Regression test for
+// http://code.google.com/p/address-sanitizer/issues/detail?id=19
+//===----------------------------------------------------------------------===//
+#include <stdio.h>
+
+static int pad1;
+static int static_var;
+static int pad2;
+
+extern "C"
+int *get_address_of_static_var() {
+  return &static_var;
+}
+
+__attribute__((constructor))
+void at_dlopen() {
+  printf("%s: I am being dlopened\n", __FILE__);
+}
+__attribute__((destructor))
+void at_dlclose() {
+  printf("%s: I am being dlclosed\n", __FILE__);
+}
diff --git a/lib/asan/lit_tests/SharedLibs/lit.local.cfg b/lib/asan/lit_tests/SharedLibs/lit.local.cfg
new file mode 100644
index 0000000..b3677c1
--- /dev/null
+++ b/lib/asan/lit_tests/SharedLibs/lit.local.cfg
@@ -0,0 +1,4 @@
+# Sources in this directory are compiled as shared libraries and used by
+# tests in parent directory.
+
+config.suffixes = []
diff --git a/lib/asan/lit_tests/SharedLibs/shared-lib-test-so.cc b/lib/asan/lit_tests/SharedLibs/shared-lib-test-so.cc
new file mode 100644
index 0000000..686a245
--- /dev/null
+++ b/lib/asan/lit_tests/SharedLibs/shared-lib-test-so.cc
@@ -0,0 +1,21 @@
+//===----------- shared-lib-test-so.cc --------------------------*- C++ -*-===//
+//
+//                     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 AddressSanitizer, an address sanity checker.
+//
+//===----------------------------------------------------------------------===//
+#include <stdio.h>
+
+int pad[10];
+int GLOB[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+extern "C"
+void inc(int index) {
+  GLOB[index]++;
+}
diff --git a/lib/asan/lit_tests/dlclose-test.cc b/lib/asan/lit_tests/dlclose-test.cc
new file mode 100644
index 0000000..c13cf7c
--- /dev/null
+++ b/lib/asan/lit_tests/dlclose-test.cc
@@ -0,0 +1,80 @@
+//===----------- dlclose-test.cc --------------------------------*- C++ -*-===//
+//
+//                     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 AddressSanitizer, an address sanity checker.
+//
+// Regression test for
+// http://code.google.com/p/address-sanitizer/issues/detail?id=19
+// Bug description:
+// 1. application dlopens foo.so
+// 2. asan registers all globals from foo.so
+// 3. application dlcloses foo.so
+// 4. application mmaps some memory to the location where foo.so was before
+// 5. application starts using this mmaped memory, but asan still thinks there
+// are globals.
+// 6. BOOM
+//===----------------------------------------------------------------------===//
+
+// RUN: %clang_asan -O2 %p/SharedLibs/dlclose-test-so.cc \
+// RUN:     -fPIC -shared -o %t-so.so
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: %t | FileCheck %s
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <string>
+
+using std::string;
+
+static const int kPageSize = 4096;
+
+typedef int *(fun_t)();
+
+int main(int argc, char *argv[]) {
+  string path = string(argv[0]) + "-so.so";
+  printf("opening %s ... \n", path.c_str());
+  void *lib = dlopen(path.c_str(), RTLD_NOW);
+  if (!lib) {
+    printf("error in dlopen(): %s\n", dlerror());
+    return 1;
+  }
+  fun_t *get = (fun_t*)dlsym(lib, "get_address_of_static_var");
+  if (!get) {
+    printf("failed dlsym\n");
+    return 1;
+  }
+  int *addr = get();
+  assert(((size_t)addr % 32) == 0);  // should be 32-byte aligned.
+  printf("addr: %p\n", addr);
+  addr[0] = 1;  // make sure we can write there.
+
+  // Now dlclose the shared library.
+  printf("attempting to dlclose\n");
+  if (dlclose(lib)) {
+    printf("failed to dlclose\n");
+    return 1;
+  }
+  // Now, the page where 'addr' is unmapped. Map it.
+  size_t page_beg = ((size_t)addr) & ~(kPageSize - 1);
+  void *res = mmap((void*)(page_beg), kPageSize,
+                   PROT_READ | PROT_WRITE,
+                   MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 0, 0);
+  if (res == (char*)-1L) {
+    printf("failed to mmap\n");
+    return 1;
+  }
+  addr[1] = 2;  // BOOM (if the bug is not fixed).
+  printf("PASS\n");
+  // CHECK: PASS
+  return 0;
+}
diff --git a/lib/asan/lit_tests/shared-lib-test.cc b/lib/asan/lit_tests/shared-lib-test.cc
new file mode 100644
index 0000000..66f96c6
--- /dev/null
+++ b/lib/asan/lit_tests/shared-lib-test.cc
@@ -0,0 +1,47 @@
+//===----------- shared-lib-test.cc -----------------------------*- C++ -*-===//
+//
+//                     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 AddressSanitizer, an address sanity checker.
+//
+//===----------------------------------------------------------------------===//
+
+// RUN: %clang_asan -O2 %p/SharedLibs/shared-lib-test-so.cc \
+// RUN:     -fPIC -shared -o %t-so.so
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: %t 2>&1 | %symbolizer | FileCheck %s
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <string>
+
+using std::string;
+
+typedef void (fun_t)(int x);
+
+int main(int argc, char *argv[]) {
+  string path = string(argv[0]) + "-so.so";
+  printf("opening %s ... \n", path.c_str());
+  void *lib = dlopen(path.c_str(), RTLD_NOW);
+  if (!lib) {
+    printf("error in dlopen(): %s\n", dlerror());
+    return 1;
+  }
+  fun_t *inc = (fun_t*)dlsym(lib, "inc");
+  if (!inc) return 1;
+  printf("ok\n");
+  inc(1);
+  inc(-1);  // BOOM
+  // CHECK: {{.*ERROR: AddressSanitizer global-buffer-overflow}}
+  // CHECK: {{READ of size 4 at 0x.* thread T0}}
+  // CHECK: {{    #0 0x.*}}
+  // CHECK: {{    #1 0x.* in main .*shared-lib-test.cc:41}}
+  return 0;
+}