[compiler-rt] r190788 - [ASan] Split ASan unit tests into two different binaries:

Alexey Samsonov samsonov at google.com
Mon Sep 16 08:50:53 PDT 2013


Author: samsonov
Date: Mon Sep 16 10:50:53 2013
New Revision: 190788

URL: http://llvm.org/viewvc/llvm-project?rev=190788&view=rev
Log:
[ASan] Split ASan unit tests into two different binaries:

(1) instrumented, i.e. compiled and linked with -fsanitize=address
(2) not instrumented, compiled w/o -fsanitize=address and linked with ASan runtime statically.

Added:
    compiler-rt/trunk/lib/asan/tests/asan_interface_test.cc
Modified:
    compiler-rt/trunk/cmake/Modules/AddCompilerRT.cmake
    compiler-rt/trunk/lib/asan/CMakeLists.txt
    compiler-rt/trunk/lib/asan/tests/CMakeLists.txt
    compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc
    compiler-rt/trunk/lib/asan/tests/asan_test.cc

Modified: compiler-rt/trunk/cmake/Modules/AddCompilerRT.cmake
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/cmake/Modules/AddCompilerRT.cmake?rev=190788&r1=190787&r2=190788&view=diff
==============================================================================
--- compiler-rt/trunk/cmake/Modules/AddCompilerRT.cmake (original)
+++ compiler-rt/trunk/cmake/Modules/AddCompilerRT.cmake Mon Sep 16 10:50:53 2013
@@ -6,13 +6,16 @@ include(CompilerRTUtils)
 # with name "<name>.<arch>" if architecture can be targeted.
 # add_compiler_rt_object_library(<name> <arch>
 #                                SOURCES <source files>
-#                                CFLAGS <compile flags>)
+#                                CFLAGS <compile flags>
+#                                DEFS <compile definitions>)
 macro(add_compiler_rt_object_library name arch)
   if(CAN_TARGET_${arch})
-    parse_arguments(LIB "SOURCES;CFLAGS" "" ${ARGN})
+    parse_arguments(LIB "SOURCES;CFLAGS;DEFS" "" ${ARGN})
     add_library(${name}.${arch} OBJECT ${LIB_SOURCES})
     set_target_compile_flags(${name}.${arch}
       ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS})
+    set_property(TARGET ${name}.${arch} APPEND PROPERTY
+      COMPILE_DEFINITIONS ${LIB_DEFS})
   else()
     message(FATAL_ERROR "Archtecture ${arch} can't be targeted")
   endif()
@@ -23,12 +26,15 @@ endmacro()
 # add_compiler_rt_osx_object_library(<name> ARCH <architectures>
 #                                           SOURCES <source files>
 #                                           CFLAGS <compile flags>)
+#                                           DEFS <compile definitions>)
 macro(add_compiler_rt_osx_object_library name)
-  parse_arguments(LIB "ARCH;SOURCES;CFLAGS" "" ${ARGN})
+  parse_arguments(LIB "ARCH;SOURCES;CFLAGS;DEFS" "" ${ARGN})
   set(libname "${name}.osx")
   add_library(${libname} OBJECT ${LIB_SOURCES})
   set_target_compile_flags(${libname} ${LIB_CFLAGS})
   set_target_properties(${libname} PROPERTIES OSX_ARCHITECTURES "${LIB_ARCH}")
+  set_property(TARGET ${libname} APPEND PROPERTY
+    COMPILE_DEFINITIONS ${LIB_DEFS})
 endmacro()
 
 # Adds static runtime for a given architecture and puts it in the proper

Modified: compiler-rt/trunk/lib/asan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/CMakeLists.txt?rev=190788&r1=190787&r2=190788&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/asan/CMakeLists.txt Mon Sep 16 10:50:53 2013
@@ -21,9 +21,6 @@ set(ASAN_SOURCES
   asan_thread.cc
   asan_win.cc)
 
-set(ASAN_DYLIB_SOURCES
-  ${ASAN_SOURCES})
-
 include_directories(..)
 
 if (NOT MSVC)
@@ -58,12 +55,32 @@ endif()
 filter_available_targets(ASAN_SUPPORTED_ARCH
   x86_64 i386 powerpc64)
 
+# Compile ASan sources into an object library.
+if(APPLE)
+  add_compiler_rt_osx_object_library(RTAsan
+    ARCH ${ASAN_SUPPORTED_ARCH}
+    SOURCES ${ASAN_SOURCES}
+    CFLAGS ${ASAN_CFLAGS}
+    DEFS ${ASAN_COMMON_DEFINITIONS})
+elseif(ANDROID)
+  add_library(RTAsan.arm.android OBJECT ${ASAN_SOURCES})
+  set_target_compile_flags(RTAsan.arm.android ${ASAN_CFLAGS})
+  set_property(TARGET RTAsan.arm.android APPEND PROPERTY
+    COMPILE_DEFINITIONS ${ASAN_COMMON_DEFINITIONS})
+else()
+  foreach(arch ${ASAN_SUPPORTED_ARCH})
+    add_compiler_rt_object_library(RTAsan ${arch}
+      SOURCES ${ASAN_SOURCES} CFLAGS ${ASAN_CFLAGS}
+      DEFS ${ASAN_COMMON_DEFINITIONS})
+  endforeach()
+endif()
+
+# Build ASan runtimes shipped with Clang.
 set(ASAN_RUNTIME_LIBRARIES)
 if(APPLE)
-  # Build universal binary on APPLE.
   add_compiler_rt_osx_dynamic_runtime(clang_rt.asan_osx_dynamic
     ARCH ${ASAN_SUPPORTED_ARCH}
-    SOURCES ${ASAN_DYLIB_SOURCES}
+    SOURCES $<TARGET_OBJECTS:RTAsan.osx>
             $<TARGET_OBJECTS:RTInterception.osx>
             $<TARGET_OBJECTS:RTSanitizerCommon.osx>
             $<TARGET_OBJECTS:RTLSanCommon.osx>
@@ -76,10 +93,9 @@ if(APPLE)
   list(APPEND ASAN_RUNTIME_LIBRARIES clang_rt.asan_osx_dynamic)
 elseif(ANDROID)
   add_library(clang_rt.asan-arm-android SHARED
-    ${ASAN_SOURCES}
+    $<TARGET_OBJECTS:RTAsan.arm.android>
     $<TARGET_OBJECTS:RTInterception.arm.android>
-    $<TARGET_OBJECTS:RTSanitizerCommon.arm.android>
-    )
+    $<TARGET_OBJECTS:RTSanitizerCommon.arm.android>)
   set_target_compile_flags(clang_rt.asan-arm-android
     ${ASAN_CFLAGS})
   set_property(TARGET clang_rt.asan-arm-android APPEND PROPERTY
@@ -87,20 +103,20 @@ elseif(ANDROID)
   target_link_libraries(clang_rt.asan-arm-android dl)
   list(APPEND ASAN_RUNTIME_LIBRARIES clang_rt.asan-arm-android)
 else()
-  # Otherwise, build separate libraries for each target.
-
+  # Build separate libraries for each target.
   foreach(arch ${ASAN_SUPPORTED_ARCH})
-    set(ASAN_SOURCE_LIBS
+    set(ASAN_RUNTIME_OBJECTS
+      $<TARGET_OBJECTS:RTAsan.${arch}>
       $<TARGET_OBJECTS:RTInterception.${arch}>
       $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
       $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>)
     if (NOT MSVC)
       # We can't build Leak Sanitizer on Windows yet.
-      list(APPEND ASAN_SOURCE_LIBS $<TARGET_OBJECTS:RTLSanCommon.${arch}>)
+      list(APPEND ASAN_RUNTIME_OBJECTS $<TARGET_OBJECTS:RTLSanCommon.${arch}>)
     endif()
 
     add_compiler_rt_static_runtime(clang_rt.asan-${arch} ${arch}
-      SOURCES ${ASAN_SOURCES} ${ASAN_SOURCE_LIBS}
+      SOURCES ${ASAN_RUNTIME_OBJECTS}
       CFLAGS ${ASAN_CFLAGS}
       DEFS ${ASAN_COMMON_DEFINITIONS})
     list(APPEND ASAN_RUNTIME_LIBRARIES clang_rt.asan-${arch})

Modified: compiler-rt/trunk/lib/asan/tests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/CMakeLists.txt?rev=190788&r1=190787&r2=190788&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/asan/tests/CMakeLists.txt Mon Sep 16 10:50:53 2013
@@ -39,10 +39,6 @@ set(ASAN_UNITTEST_COMMON_CFLAGS
   -Werror=sign-compare
   -g
   -O2)
-
-if(ASAN_TESTS_USE_ZERO_BASE_SHADOW)
-  list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -fPIE)
-endif()
 if(SUPPORTS_NO_VARIADIC_MACROS_FLAG)
   list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -Wno-variadic-macros)
 endif()
@@ -62,24 +58,7 @@ else()
     -DASAN_NEEDS_SEGV=1)
 endif()
 
-set(ASAN_LINK_FLAGS)
-if(ASAN_TESTS_USE_ZERO_BASE_SHADOW)
-  list(APPEND ASAN_LINK_FLAGS -pie)
-endif()
-# On Android, we link with ASan runtime manually. On other platforms we depend
-# on Clang driver behavior, passing -fsanitize=address flag.
-if(NOT ANDROID)
-  list(APPEND ASAN_LINK_FLAGS -fsanitize=address)
-endif()
-# Unit tests on Mac depend on Foundation.
-if(APPLE)
-  list(APPEND ASAN_LINK_FLAGS -framework Foundation)
-endif()
-# Unit tests require libstdc++.
-list(APPEND ASAN_LINK_FLAGS -lstdc++)
-
 set(ASAN_BLACKLIST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/asan_test.ignore")
-
 set(ASAN_UNITTEST_INSTRUMENTED_CFLAGS
   ${ASAN_UNITTEST_COMMON_CFLAGS}
   -fsanitize=address
@@ -95,11 +74,30 @@ if(ASAN_TESTS_USE_ZERO_BASE_SHADOW)
     -fsanitize-address-zero-base-shadow)
 endif()
 
+# Unit tests require libstdc++.
+set(ASAN_UNITTEST_COMMON_LINKFLAGS -lstdc++)
+# Unit tests on Mac depend on Foundation.
+if(APPLE)
+  list(APPEND ASAN_UNITTEST_COMMON_LINKFLAGS -framework Foundation)
+endif()
+
+set(ASAN_UNITTEST_INSTRUMENTED_LINKFLAGS
+  ${ASAN_UNITTEST_COMMON_LINKFLAGS})
+# On Android, we link with ASan runtime manually. On other platforms we depend
+# on Clang driver behavior, passing -fsanitize=address flag.
+if(NOT ANDROID)
+  list(APPEND ASAN_UNITTEST_INSTRUMENTED_LINKFLAGS -fsanitize=address)
+endif()
+
+set(ASAN_UNITTEST_NOINST_LINKFLAGS
+  ${ASAN_UNITTEST_COMMON_LINKFLAGS}
+  -lpthread -ldl)
+
 # Compile source for the given architecture, using compiler
 # options in ${ARGN}, and add it to the object list.
 macro(asan_compile obj_list source arch)
   get_filename_component(basename ${source} NAME)
-  set(output_obj "${basename}.${arch}.o")
+  set(output_obj "${obj_list}.${basename}.${arch}.o")
   get_target_flags_for_arch(${arch} TARGET_CFLAGS)
   clang_compile(${output_obj} ${source}
                 CFLAGS ${ARGN} ${TARGET_CFLAGS}
@@ -110,13 +108,19 @@ macro(asan_compile obj_list source arch)
 endmacro()
 
 # Link ASan unit test for a given architecture from a set
-# of objects in ${ARGN}.
+# of objects in with given linker flags.
 macro(add_asan_test test_suite test_name arch)
+  parse_arguments(TEST "OBJECTS;LINKFLAGS" "WITH_TEST_RUNTIME" ${ARGN})
   get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS)
+  set(TEST_DEPS ${ASAN_RUNTIME_LIBRARIES} ${TEST_OBJECTS})
+  if(TEST_WITH_TEST_RUNTIME)
+    list(APPEND TEST_DEPS ${ASAN_TEST_RUNTIME})
+    list(APPEND TEST_OBJECTS lib${ASAN_TEST_RUNTIME}.a)
+  endif()
   add_compiler_rt_test(${test_suite} ${test_name}
-                       OBJECTS ${ARGN}
-                       DEPS ${ASAN_RUNTIME_LIBRARIES} ${ARGN}
-                       LINK_FLAGS ${ASAN_LINK_FLAGS}
+                       OBJECTS ${TEST_OBJECTS}
+                       DEPS ${TEST_DEPS}
+                       LINK_FLAGS ${TEST_LINKFLAGS}
                                   ${TARGET_LINK_FLAGS})
 endmacro()
 
@@ -127,64 +131,90 @@ set_target_properties(AsanUnitTests PROP
 add_custom_target(AsanBenchmarks)
 set_target_properties(AsanBenchmarks PROPERTIES FOLDER "Asan benchmarks")
 
-if (NOT APPLE AND NOT ANDROID)
-# Do not build asan_fake_stack_test.cc on OS X and Android, since it requires
-# exposing additional functions from the runtime.
-# See also https://code.google.com/p/address-sanitizer/issues/detail?id=222
-set(ASAN_NOINST_TEST_SOURCES
-  asan_fake_stack_test.cc
-  asan_noinst_test.cc
-  asan_test_main.cc)
-else()
 set(ASAN_NOINST_TEST_SOURCES
+  ${COMPILER_RT_GTEST_SOURCE}
   asan_noinst_test.cc
   asan_test_main.cc)
+if(NOT APPLE AND NOT ANDROID)
+  # Do not build asan_fake_stack_test.cc on OS X and Android, since it requires
+  # exposing additional functions from the runtime.
+  # See also https://code.google.com/p/address-sanitizer/issues/detail?id=222
+  list(APPEND ASAN_NOINST_TEST_SOURCES asan_fake_stack_test.cc)
 endif()
 
 set(ASAN_INST_TEST_SOURCES
+  ${COMPILER_RT_GTEST_SOURCE}
   asan_globals_test.cc
+  asan_interface_test.cc
   asan_test.cc
   asan_oob_test.cc
   asan_mem_test.cc
-  asan_str_test.cc)
+  asan_str_test.cc
+  asan_test_main.cc)
+if(APPLE)
+  list(APPEND ASAN_INST_TEST_SOURCES asan_mac_test.cc)
+endif()
+
+set(ASAN_BENCHMARKS_SOURCES
+  ${COMPILER_RT_GTEST_SOURCE}
+  asan_benchmarks_test.cc)  
 
 # Adds ASan unit tests and benchmarks for architecture.
 macro(add_asan_tests_for_arch arch)
-  # Build gtest instrumented with ASan.
-  set(ASAN_INST_GTEST)
-  asan_compile(ASAN_INST_GTEST ${COMPILER_RT_GTEST_SOURCE} ${arch} 
-                               ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
   # Instrumented tests.
   set(ASAN_INST_TEST_OBJECTS)
   foreach(src ${ASAN_INST_TEST_SOURCES})
     asan_compile(ASAN_INST_TEST_OBJECTS ${src} ${arch}
                  ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
   endforeach()
-  # Add Mac-specific tests.
   if (APPLE)
-    asan_compile(ASAN_INST_TEST_OBJECTS asan_mac_test.cc ${arch}
-                 ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
+    # Add Mac-specific helper.
     asan_compile(ASAN_INST_TEST_OBJECTS asan_mac_test_helpers.mm ${arch}
                  ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} -ObjC)
   endif()
+  add_asan_test(AsanUnitTests "Asan-${arch}-Test" ${arch}
+                OBJECTS ${ASAN_INST_TEST_OBJECTS}
+                LINKFLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINKFLAGS})
+
+  # Add static ASan runtime that will be linked with uninstrumented tests.
+  set(ASAN_TEST_RUNTIME RTAsanTest.${arch})
+  if(APPLE)
+    set(ASAN_TEST_RUNTIME_OBJECTS
+      $<TARGET_OBJECTS:RTAsan.osx>
+      $<TARGET_OBJECTS:RTInterception.osx>
+      $<TARGET_OBJECTS:RTSanitizerCommon.osx>
+      $<TARGET_OBJECTS:RTLSanCommon.osx>)
+  else()
+    set(ASAN_TEST_RUNTIME_OBJECTS
+      $<TARGET_OBJECTS:RTAsan.${arch}>
+      $<TARGET_OBJECTS:RTInterception.${arch}>
+      $<TARGET_OBJECTS:RTLSanCommon.${arch}>
+      $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
+      $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>)
+  endif()
+  add_library(${ASAN_TEST_RUNTIME} STATIC ${ASAN_TEST_RUNTIME_OBJECTS})
+  set_target_properties(${ASAN_TEST_RUNTIME} PROPERTIES
+    ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
   # Uninstrumented tests.
   set(ASAN_NOINST_TEST_OBJECTS)
   foreach(src ${ASAN_NOINST_TEST_SOURCES})
     asan_compile(ASAN_NOINST_TEST_OBJECTS ${src} ${arch}
                  ${ASAN_UNITTEST_COMMON_CFLAGS})
   endforeach()
-  # Link everything together.
-  add_asan_test(AsanUnitTests "Asan-${arch}-Test" ${arch}
-                ${ASAN_NOINST_TEST_OBJECTS}
-                ${ASAN_INST_TEST_OBJECTS} ${ASAN_INST_GTEST})
+  add_asan_test(AsanUnitTests "Asan-${arch}-Noinst-Test" ${arch}
+                OBJECTS ${ASAN_NOINST_TEST_OBJECTS}
+                LINKFLAGS ${ASAN_UNITTEST_NOINST_LINKFLAGS}
+                WITH_TEST_RUNTIME)
 
-  # Instrumented benchmarks.
+  # Benchmarks.
   set(ASAN_BENCHMARKS_OBJECTS)
-  asan_compile(ASAN_BENCHMARKS_OBJECTS asan_benchmarks_test.cc ${arch}
-               ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
-  # Link benchmarks.
+  foreach(src ${ASAN_BENCHMARKS_SOURCES})
+    asan_compile(ASAN_BENCHMARKS_OBJECTS ${src} ${arch}
+                 ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
+  endforeach()
   add_asan_test(AsanBenchmarks "Asan-${arch}-Benchmark" ${arch}
-                ${ASAN_BENCHMARKS_OBJECTS} ${ASAN_INST_GTEST})
+                OBJECTS ${ASAN_BENCHMARKS_OBJECTS}
+                LINKFLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINKFLAGS})
 endmacro()
 
 if(COMPILER_RT_CAN_EXECUTE_TESTS)
@@ -196,20 +226,28 @@ endif()
 if(ANDROID)
   # We assume that unit tests on Android are built in a build
   # tree with fresh Clang as a host compiler.
-  add_library(asan_noinst_test OBJECT ${ASAN_NOINST_TEST_SOURCES})
-  set_target_compile_flags(asan_noinst_test ${ASAN_UNITTEST_COMMON_CFLAGS})
-  add_library(asan_inst_test OBJECT
-              ${ASAN_INST_TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE})  
-  set_target_compile_flags(asan_inst_test ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
+  
+  # Test w/o ASan instrumentation. Link it with ASan statically.
+  add_executable(AsanNoinstTest
+    $<TARGET_OBJECTS:RTAsan.arm.android>
+    $<TARGET_OBJECTS:RTInterception.arm.android>
+    $<TARGET_OBJECTS:RTSanitizerCommon.arm.android>
+    ${COMPILER_RT_GTEST_SOURCE}
+    ${ASAN_NOINST_TEST_SOURCES})
+  set_target_compile_flags(AsanNoinstTest ${ASAN_UNITTEST_COMMON_CFLAGS})
+  set_target_link_flags(AsanNoinstTest ${ASAN_UNITTEST_NOINST_LINKFLAGS})
+
+  # Test with ASan instrumentation. Link with ASan dynamic runtime.
   add_executable(AsanTest
-    $<TARGET_OBJECTS:asan_noinst_test>
-    $<TARGET_OBJECTS:asan_inst_test>
-  )
+    ${COMPILER_RT_GTEST_SOURCE}
+    ${ASAN_INST_TEST_SOURCES})
+  set_target_compile_flags(AsanTest ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
+  set_target_link_flags(AsanTest ${ASAN_UNITTEST_INSTRUMENTED_LINKFLAGS})
+  target_link_libraries(AsanTest clang_rt.asan-arm-android)
+
   # Setup correct output directory and link flags.
-  set_target_properties(AsanTest PROPERTIES
+  set_target_properties(AsanNoinstTest AsanTest PROPERTIES
     RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
-  set_target_link_flags(AsanTest ${ASAN_LINK_FLAGS})
-  target_link_libraries(AsanTest clang_rt.asan-arm-android)
   # Add unit test to test suite.
-  add_dependencies(AsanUnitTests AsanTest)
+  add_dependencies(AsanUnitTests AsanNoinstTest AsanTest)
 endif()

Added: compiler-rt/trunk/lib/asan/tests/asan_interface_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_interface_test.cc?rev=190788&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_interface_test.cc (added)
+++ compiler-rt/trunk/lib/asan/tests/asan_interface_test.cc Mon Sep 16 10:50:53 2013
@@ -0,0 +1,426 @@
+//===-- asan_interface_test.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 AddressSanitizer, an address sanity checker.
+//
+//===----------------------------------------------------------------------===//
+#include "asan_test_utils.h"
+#include "sanitizer/asan_interface.h"
+
+TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) {
+  EXPECT_EQ(0U, __asan_get_estimated_allocated_size(0));
+  const size_t sizes[] = { 1, 30, 1<<30 };
+  for (size_t i = 0; i < 3; i++) {
+    EXPECT_EQ(sizes[i], __asan_get_estimated_allocated_size(sizes[i]));
+  }
+}
+
+static const char* kGetAllocatedSizeErrorMsg =
+  "attempting to call __asan_get_allocated_size()";
+
+TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) {
+  const size_t kArraySize = 100;
+  char *array = Ident((char*)malloc(kArraySize));
+  int *int_ptr = Ident(new int);
+
+  // Allocated memory is owned by allocator. Allocated size should be
+  // equal to requested size.
+  EXPECT_EQ(true, __asan_get_ownership(array));
+  EXPECT_EQ(kArraySize, __asan_get_allocated_size(array));
+  EXPECT_EQ(true, __asan_get_ownership(int_ptr));
+  EXPECT_EQ(sizeof(int), __asan_get_allocated_size(int_ptr));
+
+  // We cannot call GetAllocatedSize from the memory we didn't map,
+  // and from the interior pointers (not returned by previous malloc).
+  void *wild_addr = (void*)0x1;
+  EXPECT_FALSE(__asan_get_ownership(wild_addr));
+  EXPECT_DEATH(__asan_get_allocated_size(wild_addr), kGetAllocatedSizeErrorMsg);
+  EXPECT_FALSE(__asan_get_ownership(array + kArraySize / 2));
+  EXPECT_DEATH(__asan_get_allocated_size(array + kArraySize / 2),
+               kGetAllocatedSizeErrorMsg);
+
+  // NULL is not owned, but is a valid argument for __asan_get_allocated_size().
+  EXPECT_FALSE(__asan_get_ownership(NULL));
+  EXPECT_EQ(0U, __asan_get_allocated_size(NULL));
+
+  // When memory is freed, it's not owned, and call to GetAllocatedSize
+  // is forbidden.
+  free(array);
+  EXPECT_FALSE(__asan_get_ownership(array));
+  EXPECT_DEATH(__asan_get_allocated_size(array), kGetAllocatedSizeErrorMsg);
+  delete int_ptr;
+
+  void *zero_alloc = Ident(malloc(0));
+  if (zero_alloc != 0) {
+    // If malloc(0) is not null, this pointer is owned and should have valid
+    // allocated size.
+    EXPECT_TRUE(__asan_get_ownership(zero_alloc));
+    // Allocated size is 0 or 1 depending on the allocator used.
+    EXPECT_LT(__asan_get_allocated_size(zero_alloc), 2U);
+  }
+  free(zero_alloc);
+}
+
+TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) {
+  size_t before_malloc, after_malloc, after_free;
+  char *array;
+  const size_t kMallocSize = 100;
+  before_malloc = __asan_get_current_allocated_bytes();
+
+  array = Ident((char*)malloc(kMallocSize));
+  after_malloc = __asan_get_current_allocated_bytes();
+  EXPECT_EQ(before_malloc + kMallocSize, after_malloc);
+
+  free(array);
+  after_free = __asan_get_current_allocated_bytes();
+  EXPECT_EQ(before_malloc, after_free);
+}
+
+TEST(AddressSanitizerInterface, GetHeapSizeTest) {
+  // asan_allocator2 does not keep huge chunks in free list, but unmaps them.
+  // The chunk should be greater than the quarantine size,
+  // otherwise it will be stuck in quarantine instead of being unmaped.
+  static const size_t kLargeMallocSize = (1 << 28) + 1;  // 256M
+  free(Ident(malloc(kLargeMallocSize)));  // Drain quarantine.
+  size_t old_heap_size = __asan_get_heap_size();
+  for (int i = 0; i < 3; i++) {
+    // fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize);
+    free(Ident(malloc(kLargeMallocSize)));
+    EXPECT_EQ(old_heap_size, __asan_get_heap_size());
+  }
+}
+
+static const size_t kManyThreadsMallocSizes[] = {5, 1UL<<10, 1UL<<14, 357};
+static const size_t kManyThreadsIterations = 250;
+static const size_t kManyThreadsNumThreads =
+  (SANITIZER_WORDSIZE == 32) ? 40 : 200;
+
+static void *ManyThreadsWithStatsWorker(void *arg) {
+  (void)arg;
+  for (size_t iter = 0; iter < kManyThreadsIterations; iter++) {
+    for (size_t size_index = 0; size_index < 4; size_index++) {
+      free(Ident(malloc(kManyThreadsMallocSizes[size_index])));
+    }
+  }
+  // Just one large allocation.
+  free(Ident(malloc(1 << 20)));
+  return 0;
+}
+
+TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) {
+  size_t before_test, after_test, i;
+  pthread_t threads[kManyThreadsNumThreads];
+  before_test = __asan_get_current_allocated_bytes();
+  for (i = 0; i < kManyThreadsNumThreads; i++) {
+    PTHREAD_CREATE(&threads[i], 0,
+                   (void* (*)(void *x))ManyThreadsWithStatsWorker, (void*)i);
+  }
+  for (i = 0; i < kManyThreadsNumThreads; i++) {
+    PTHREAD_JOIN(threads[i], 0);
+  }
+  after_test = __asan_get_current_allocated_bytes();
+  // ASan stats also reflect memory usage of internal ASan RTL structs,
+  // so we can't check for equality here.
+  EXPECT_LT(after_test, before_test + (1UL<<20));
+}
+
+static void DoDoubleFree() {
+  int *x = Ident(new int);
+  delete Ident(x);
+  delete Ident(x);
+}
+
+TEST(AddressSanitizerInterface, ExitCode) {
+  int original_exit_code = __asan_set_error_exit_code(7);
+  EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(7), "");
+  EXPECT_EQ(7, __asan_set_error_exit_code(8));
+  EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(8), "");
+  EXPECT_EQ(8, __asan_set_error_exit_code(original_exit_code));
+  EXPECT_EXIT(DoDoubleFree(),
+              ::testing::ExitedWithCode(original_exit_code), "");
+}
+
+static void MyDeathCallback() {
+  fprintf(stderr, "MyDeathCallback\n");
+}
+
+TEST(AddressSanitizerInterface, DeathCallbackTest) {
+  __asan_set_death_callback(MyDeathCallback);
+  EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback");
+  __asan_set_death_callback(NULL);
+}
+
+static const char* kUseAfterPoisonErrorMessage = "use-after-poison";
+
+#define GOOD_ACCESS(ptr, offset)  \
+    EXPECT_FALSE(__asan_address_is_poisoned(ptr + offset))
+
+#define BAD_ACCESS(ptr, offset) \
+    EXPECT_TRUE(__asan_address_is_poisoned(ptr + offset))
+
+TEST(AddressSanitizerInterface, SimplePoisonMemoryRegionTest) {
+  char *array = Ident((char*)malloc(120));
+  // poison array[40..80)
+  __asan_poison_memory_region(array + 40, 40);
+  GOOD_ACCESS(array, 39);
+  GOOD_ACCESS(array, 80);
+  BAD_ACCESS(array, 40);
+  BAD_ACCESS(array, 60);
+  BAD_ACCESS(array, 79);
+  char value;
+  EXPECT_DEATH(value = Ident(array[40]), kUseAfterPoisonErrorMessage);
+  __asan_unpoison_memory_region(array + 40, 40);
+  // access previously poisoned memory.
+  GOOD_ACCESS(array, 40);
+  GOOD_ACCESS(array, 79);
+  free(array);
+}
+
+TEST(AddressSanitizerInterface, OverlappingPoisonMemoryRegionTest) {
+  char *array = Ident((char*)malloc(120));
+  // Poison [0..40) and [80..120)
+  __asan_poison_memory_region(array, 40);
+  __asan_poison_memory_region(array + 80, 40);
+  BAD_ACCESS(array, 20);
+  GOOD_ACCESS(array, 60);
+  BAD_ACCESS(array, 100);
+  // Poison whole array - [0..120)
+  __asan_poison_memory_region(array, 120);
+  BAD_ACCESS(array, 60);
+  // Unpoison [24..96)
+  __asan_unpoison_memory_region(array + 24, 72);
+  BAD_ACCESS(array, 23);
+  GOOD_ACCESS(array, 24);
+  GOOD_ACCESS(array, 60);
+  GOOD_ACCESS(array, 95);
+  BAD_ACCESS(array, 96);
+  free(array);
+}
+
+TEST(AddressSanitizerInterface, PushAndPopWithPoisoningTest) {
+  // Vector of capacity 20
+  char *vec = Ident((char*)malloc(20));
+  __asan_poison_memory_region(vec, 20);
+  for (size_t i = 0; i < 7; i++) {
+    // Simulate push_back.
+    __asan_unpoison_memory_region(vec + i, 1);
+    GOOD_ACCESS(vec, i);
+    BAD_ACCESS(vec, i + 1);
+  }
+  for (size_t i = 7; i > 0; i--) {
+    // Simulate pop_back.
+    __asan_poison_memory_region(vec + i - 1, 1);
+    BAD_ACCESS(vec, i - 1);
+    if (i > 1) GOOD_ACCESS(vec, i - 2);
+  }
+  free(vec);
+}
+
+// Make sure that each aligned block of size "2^granularity" doesn't have
+// "true" value before "false" value.
+static void MakeShadowValid(bool *shadow, int length, int granularity) {
+  bool can_be_poisoned = true;
+  for (int i = length - 1; i >= 0; i--) {
+    if (!shadow[i])
+      can_be_poisoned = false;
+    if (!can_be_poisoned)
+      shadow[i] = false;
+    if (i % (1 << granularity) == 0) {
+      can_be_poisoned = true;
+    }
+  }
+}
+
+TEST(AddressSanitizerInterface, PoisoningStressTest) {
+  const size_t kSize = 24;
+  bool expected[kSize];
+  char *arr = Ident((char*)malloc(kSize));
+  for (size_t l1 = 0; l1 < kSize; l1++) {
+    for (size_t s1 = 1; l1 + s1 <= kSize; s1++) {
+      for (size_t l2 = 0; l2 < kSize; l2++) {
+        for (size_t s2 = 1; l2 + s2 <= kSize; s2++) {
+          // Poison [l1, l1+s1), [l2, l2+s2) and check result.
+          __asan_unpoison_memory_region(arr, kSize);
+          __asan_poison_memory_region(arr + l1, s1);
+          __asan_poison_memory_region(arr + l2, s2);
+          memset(expected, false, kSize);
+          memset(expected + l1, true, s1);
+          MakeShadowValid(expected, kSize, /*granularity*/ 3);
+          memset(expected + l2, true, s2);
+          MakeShadowValid(expected, kSize, /*granularity*/ 3);
+          for (size_t i = 0; i < kSize; i++) {
+            ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));
+          }
+          // Unpoison [l1, l1+s1) and [l2, l2+s2) and check result.
+          __asan_poison_memory_region(arr, kSize);
+          __asan_unpoison_memory_region(arr + l1, s1);
+          __asan_unpoison_memory_region(arr + l2, s2);
+          memset(expected, true, kSize);
+          memset(expected + l1, false, s1);
+          MakeShadowValid(expected, kSize, /*granularity*/ 3);
+          memset(expected + l2, false, s2);
+          MakeShadowValid(expected, kSize, /*granularity*/ 3);
+          for (size_t i = 0; i < kSize; i++) {
+            ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));
+          }
+        }
+      }
+    }
+  }
+  free(arr);
+}
+
+TEST(AddressSanitizerInterface, GlobalRedzones) {
+  GOOD_ACCESS(glob1, 1 - 1);
+  GOOD_ACCESS(glob2, 2 - 1);
+  GOOD_ACCESS(glob3, 3 - 1);
+  GOOD_ACCESS(glob4, 4 - 1);
+  GOOD_ACCESS(glob5, 5 - 1);
+  GOOD_ACCESS(glob6, 6 - 1);
+  GOOD_ACCESS(glob7, 7 - 1);
+  GOOD_ACCESS(glob8, 8 - 1);
+  GOOD_ACCESS(glob9, 9 - 1);
+  GOOD_ACCESS(glob10, 10 - 1);
+  GOOD_ACCESS(glob11, 11 - 1);
+  GOOD_ACCESS(glob12, 12 - 1);
+  GOOD_ACCESS(glob13, 13 - 1);
+  GOOD_ACCESS(glob14, 14 - 1);
+  GOOD_ACCESS(glob15, 15 - 1);
+  GOOD_ACCESS(glob16, 16 - 1);
+  GOOD_ACCESS(glob17, 17 - 1);
+  GOOD_ACCESS(glob1000, 1000 - 1);
+  GOOD_ACCESS(glob10000, 10000 - 1);
+  GOOD_ACCESS(glob100000, 100000 - 1);
+
+  BAD_ACCESS(glob1, 1);
+  BAD_ACCESS(glob2, 2);
+  BAD_ACCESS(glob3, 3);
+  BAD_ACCESS(glob4, 4);
+  BAD_ACCESS(glob5, 5);
+  BAD_ACCESS(glob6, 6);
+  BAD_ACCESS(glob7, 7);
+  BAD_ACCESS(glob8, 8);
+  BAD_ACCESS(glob9, 9);
+  BAD_ACCESS(glob10, 10);
+  BAD_ACCESS(glob11, 11);
+  BAD_ACCESS(glob12, 12);
+  BAD_ACCESS(glob13, 13);
+  BAD_ACCESS(glob14, 14);
+  BAD_ACCESS(glob15, 15);
+  BAD_ACCESS(glob16, 16);
+  BAD_ACCESS(glob17, 17);
+  BAD_ACCESS(glob1000, 1000);
+  BAD_ACCESS(glob1000, 1100);  // Redzone is at least 101 bytes.
+  BAD_ACCESS(glob10000, 10000);
+  BAD_ACCESS(glob10000, 11000);  // Redzone is at least 1001 bytes.
+  BAD_ACCESS(glob100000, 100000);
+  BAD_ACCESS(glob100000, 110000);  // Redzone is at least 10001 bytes.
+}
+
+TEST(AddressSanitizerInterface, PoisonedRegion) {
+  size_t rz = 16;
+  for (size_t size = 1; size <= 64; size++) {
+    char *p = new char[size];
+    for (size_t beg = 0; beg < size + rz; beg++) {
+      for (size_t end = beg; end < size + rz; end++) {
+        void *first_poisoned = __asan_region_is_poisoned(p + beg, end - beg);
+        if (beg == end) {
+          EXPECT_FALSE(first_poisoned);
+        } else if (beg < size && end <= size) {
+          EXPECT_FALSE(first_poisoned);
+        } else if (beg >= size) {
+          EXPECT_EQ(p + beg, first_poisoned);
+        } else {
+          EXPECT_GT(end, size);
+          EXPECT_EQ(p + size, first_poisoned);
+        }
+      }
+    }
+    delete [] p;
+  }
+}
+
+// This is a performance benchmark for manual runs.
+// asan's memset interceptor calls mem_is_zero for the entire shadow region.
+// the profile should look like this:
+//     89.10%   [.] __memset_sse2
+//     10.50%   [.] __sanitizer::mem_is_zero
+// I.e. mem_is_zero should consume ~ SHADOW_GRANULARITY less CPU cycles
+// than memset itself.
+TEST(AddressSanitizerInterface, DISABLED_StressLargeMemset) {
+  size_t size = 1 << 20;
+  char *x = new char[size];
+  for (int i = 0; i < 100000; i++)
+    Ident(memset)(x, 0, size);
+  delete [] x;
+}
+
+// Same here, but we run memset with small sizes.
+TEST(AddressSanitizerInterface, DISABLED_StressSmallMemset) {
+  size_t size = 32;
+  char *x = new char[size];
+  for (int i = 0; i < 100000000; i++)
+    Ident(memset)(x, 0, size);
+  delete [] x;
+}
+static const char *kInvalidPoisonMessage = "invalid-poison-memory-range";
+static const char *kInvalidUnpoisonMessage = "invalid-unpoison-memory-range";
+
+TEST(AddressSanitizerInterface, DISABLED_InvalidPoisonAndUnpoisonCallsTest) {
+  char *array = Ident((char*)malloc(120));
+  __asan_unpoison_memory_region(array, 120);
+  // Try to unpoison not owned memory
+  EXPECT_DEATH(__asan_unpoison_memory_region(array, 121),
+               kInvalidUnpoisonMessage);
+  EXPECT_DEATH(__asan_unpoison_memory_region(array - 1, 120),
+               kInvalidUnpoisonMessage);
+
+  __asan_poison_memory_region(array, 120);
+  // Try to poison not owned memory.
+  EXPECT_DEATH(__asan_poison_memory_region(array, 121), kInvalidPoisonMessage);
+  EXPECT_DEATH(__asan_poison_memory_region(array - 1, 120),
+               kInvalidPoisonMessage);
+  free(array);
+}
+
+static void ErrorReportCallbackOneToZ(const char *report) {
+  int report_len = strlen(report);
+  ASSERT_EQ(6, write(2, "ABCDEF", 6));
+  ASSERT_EQ(report_len, write(2, report, report_len));
+  ASSERT_EQ(6, write(2, "ABCDEF", 6));
+  _exit(1);
+}
+
+TEST(AddressSanitizerInterface, SetErrorReportCallbackTest) {
+  __asan_set_error_report_callback(ErrorReportCallbackOneToZ);
+  EXPECT_DEATH(__asan_report_error(0, 0, 0, 0, true, 1),
+               ASAN_PCRE_DOTALL "ABCDEF.*AddressSanitizer.*WRITE.*ABCDEF");
+  __asan_set_error_report_callback(NULL);
+}
+
+TEST(AddressSanitizerInterface, GetOwnershipStressTest) {
+  std::vector<char *> pointers;
+  std::vector<size_t> sizes;
+  const size_t kNumMallocs = 1 << 9;
+  for (size_t i = 0; i < kNumMallocs; i++) {
+    size_t size = i * 100 + 1;
+    pointers.push_back((char*)malloc(size));
+    sizes.push_back(size);
+  }
+  for (size_t i = 0; i < 4000000; i++) {
+    EXPECT_FALSE(__asan_get_ownership(&pointers));
+    EXPECT_FALSE(__asan_get_ownership((void*)0x1234));
+    size_t idx = i % kNumMallocs;
+    EXPECT_TRUE(__asan_get_ownership(pointers[idx]));
+    EXPECT_EQ(sizes[idx], __asan_get_allocated_size(pointers[idx]));
+  }
+  for (size_t i = 0, n = pointers.size(); i < n; i++)
+    free(pointers[i]);
+}
+

Modified: compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc?rev=190788&r1=190787&r2=190788&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc Mon Sep 16 10:50:53 2013
@@ -25,6 +25,46 @@
 #include <vector>
 #include <limits>
 
+#if ASAN_FLEXIBLE_MAPPING_AND_OFFSET == 1
+// Manually set correct ASan mapping scale and offset, as they won't be
+// exported from instrumented sources (there are none).
+# define FLEXIBLE_SHADOW_SCALE kDefaultShadowScale
+# if SANITIZER_ANDROID
+#  define FLEXIBLE_SHADOW_OFFSET (0)
+# else
+#  if SANITIZER_WORDSIZE == 32
+#   if defined(__mips__)
+#     define FLEXIBLE_SHADOW_OFFSET kMIPS32_ShadowOffset32
+#   else
+#     define FLEXIBLE_SHADOW_OFFSET kDefaultShadowOffset32
+#   endif
+#  else
+#   if defined(__powerpc64__)
+#    define FLEXIBLE_SHADOW_OFFSET kPPC64_ShadowOffset64
+#   elif SANITIZER_MAC
+#    define FLEXIBLE_SHADOW_OFFSET kDefaultShadowOffset64
+#   else
+#    define FLEXIBLE_SHADOW_OFFSET kDefaultShort64bitShadowOffset
+#   endif
+#  endif
+# endif
+SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_scale = FLEXIBLE_SHADOW_SCALE;
+SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset =
+    FLEXIBLE_SHADOW_OFFSET;
+#endif  // ASAN_FLEXIBLE_MAPPING_AND_OFFSET
+
+extern "C" {
+// Set specific ASan options for uninstrumented unittest.
+const char* __asan_default_options() {
+  return "allow_reexec=0";
+}
+}  // extern "C"
+
+// Make sure __asan_init is called before any test case is run.
+struct AsanInitCaller {
+  AsanInitCaller() { __asan_init(); }
+};
+static AsanInitCaller asan_init_caller;
 
 TEST(AddressSanitizer, InternalSimpleDeathTest) {
   EXPECT_DEATH(exit(1), "");
@@ -333,459 +373,13 @@ TEST(AddressSanitizer, ThreadedOneSizeMa
   }
 }
 
-TEST(AddressSanitizer, MemsetWildAddressTest) {
+TEST(AddressSanitizer, ShadowRegionIsPoisonedTest) {
   using __asan::kHighMemEnd;
-  typedef void*(*memset_p)(void*, int, size_t);
-  // Prevent inlining of memset().
-  volatile memset_p libc_memset = (memset_p)memset;
-  EXPECT_DEATH(libc_memset((void*)(kLowShadowBeg + 200), 0, 100),
-               (kLowShadowEnd == 0) ? "unknown-crash.*shadow gap"
-                                    : "unknown-crash.*low shadow");
-  EXPECT_DEATH(libc_memset((void*)(kShadowGapBeg + 200), 0, 100),
-               "unknown-crash.*shadow gap");
-  EXPECT_DEATH(libc_memset((void*)(kHighShadowBeg + 200), 0, 100),
-               "unknown-crash.*high shadow");
-}
-
-TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) {
-  EXPECT_EQ(0U, __asan_get_estimated_allocated_size(0));
-  const size_t sizes[] = { 1, 30, 1<<30 };
-  for (size_t i = 0; i < 3; i++) {
-    EXPECT_EQ(sizes[i], __asan_get_estimated_allocated_size(sizes[i]));
-  }
-}
-
-static const char* kGetAllocatedSizeErrorMsg =
-  "attempting to call __asan_get_allocated_size()";
-
-TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) {
-  const size_t kArraySize = 100;
-  char *array = Ident((char*)malloc(kArraySize));
-  int *int_ptr = Ident(new int);
-
-  // Allocated memory is owned by allocator. Allocated size should be
-  // equal to requested size.
-  EXPECT_EQ(true, __asan_get_ownership(array));
-  EXPECT_EQ(kArraySize, __asan_get_allocated_size(array));
-  EXPECT_EQ(true, __asan_get_ownership(int_ptr));
-  EXPECT_EQ(sizeof(int), __asan_get_allocated_size(int_ptr));
-
-  // We cannot call GetAllocatedSize from the memory we didn't map,
-  // and from the interior pointers (not returned by previous malloc).
-  void *wild_addr = (void*)0x1;
-  EXPECT_FALSE(__asan_get_ownership(wild_addr));
-  EXPECT_DEATH(__asan_get_allocated_size(wild_addr), kGetAllocatedSizeErrorMsg);
-  EXPECT_FALSE(__asan_get_ownership(array + kArraySize / 2));
-  EXPECT_DEATH(__asan_get_allocated_size(array + kArraySize / 2),
-               kGetAllocatedSizeErrorMsg);
-
-  // NULL is not owned, but is a valid argument for __asan_get_allocated_size().
-  EXPECT_FALSE(__asan_get_ownership(NULL));
-  EXPECT_EQ(0U, __asan_get_allocated_size(NULL));
-
-  // When memory is freed, it's not owned, and call to GetAllocatedSize
-  // is forbidden.
-  free(array);
-  EXPECT_FALSE(__asan_get_ownership(array));
-  EXPECT_DEATH(__asan_get_allocated_size(array), kGetAllocatedSizeErrorMsg);
-  delete int_ptr;
-
-  void *zero_alloc = Ident(malloc(0));
-  if (zero_alloc != 0) {
-    // If malloc(0) is not null, this pointer is owned and should have valid
-    // allocated size.
-    EXPECT_TRUE(__asan_get_ownership(zero_alloc));
-    // Allocated size is 0 or 1 depending on the allocator used.
-    EXPECT_LT(__asan_get_allocated_size(zero_alloc), 2U);
-  }
-  free(zero_alloc);
-}
-
-TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) {
-  size_t before_malloc, after_malloc, after_free;
-  char *array;
-  const size_t kMallocSize = 100;
-  before_malloc = __asan_get_current_allocated_bytes();
-
-  array = Ident((char*)malloc(kMallocSize));
-  after_malloc = __asan_get_current_allocated_bytes();
-  EXPECT_EQ(before_malloc + kMallocSize, after_malloc);
-
-  free(array);
-  after_free = __asan_get_current_allocated_bytes();
-  EXPECT_EQ(before_malloc, after_free);
-}
-
-static void DoDoubleFree() {
-  int *x = Ident(new int);
-  delete Ident(x);
-  delete Ident(x);
-}
-
-TEST(AddressSanitizerInterface, GetHeapSizeTest) {
-  // asan_allocator2 does not keep huge chunks in free list, but unmaps them.
-  // The chunk should be greater than the quarantine size,
-  // otherwise it will be stuck in quarantine instead of being unmaped.
-  static const size_t kLargeMallocSize = (1 << 28) + 1;  // 256M
-  free(Ident(malloc(kLargeMallocSize)));  // Drain quarantine.
-  uptr old_heap_size = __asan_get_heap_size();
-  for (int i = 0; i < 3; i++) {
-    // fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize);
-    free(Ident(malloc(kLargeMallocSize)));
-    EXPECT_EQ(old_heap_size, __asan_get_heap_size());
-  }
-}
-
-static const size_t kManyThreadsMallocSizes[] = {5, 1UL<<10, 1UL<<14, 357};
-static const size_t kManyThreadsIterations = 250;
-static const size_t kManyThreadsNumThreads =
-  (SANITIZER_WORDSIZE == 32) ? 40 : 200;
-
-void *ManyThreadsWithStatsWorker(void *arg) {
-  (void)arg;
-  for (size_t iter = 0; iter < kManyThreadsIterations; iter++) {
-    for (size_t size_index = 0; size_index < 4; size_index++) {
-      free(Ident(malloc(kManyThreadsMallocSizes[size_index])));
-    }
-  }
-  // Just one large allocation.
-  free(Ident(malloc(1 << 20)));
-  return 0;
-}
-
-TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) {
-  size_t before_test, after_test, i;
-  pthread_t threads[kManyThreadsNumThreads];
-  before_test = __asan_get_current_allocated_bytes();
-  for (i = 0; i < kManyThreadsNumThreads; i++) {
-    PTHREAD_CREATE(&threads[i], 0,
-                   (void* (*)(void *x))ManyThreadsWithStatsWorker, (void*)i);
-  }
-  for (i = 0; i < kManyThreadsNumThreads; i++) {
-    PTHREAD_JOIN(threads[i], 0);
-  }
-  after_test = __asan_get_current_allocated_bytes();
-  // ASan stats also reflect memory usage of internal ASan RTL structs,
-  // so we can't check for equality here.
-  EXPECT_LT(after_test, before_test + (1UL<<20));
-}
-
-TEST(AddressSanitizerInterface, ExitCode) {
-  int original_exit_code = __asan_set_error_exit_code(7);
-  EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(7), "");
-  EXPECT_EQ(7, __asan_set_error_exit_code(8));
-  EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(8), "");
-  EXPECT_EQ(8, __asan_set_error_exit_code(original_exit_code));
-  EXPECT_EXIT(DoDoubleFree(),
-              ::testing::ExitedWithCode(original_exit_code), "");
-}
-
-static void MyDeathCallback() {
-  fprintf(stderr, "MyDeathCallback\n");
-}
-
-TEST(AddressSanitizerInterface, DeathCallbackTest) {
-  __asan_set_death_callback(MyDeathCallback);
-  EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback");
-  __asan_set_death_callback(NULL);
-}
-
-static const char* kUseAfterPoisonErrorMessage = "use-after-poison";
-
-#define GOOD_ACCESS(ptr, offset)  \
-    EXPECT_FALSE(__asan::AddressIsPoisoned((uptr)(ptr + offset)))
-
-#define BAD_ACCESS(ptr, offset) \
-    EXPECT_TRUE(__asan::AddressIsPoisoned((uptr)(ptr + offset)))
-
-TEST(AddressSanitizerInterface, SimplePoisonMemoryRegionTest) {
-  char *array = Ident((char*)malloc(120));
-  // poison array[40..80)
-  __asan_poison_memory_region(array + 40, 40);
-  GOOD_ACCESS(array, 39);
-  GOOD_ACCESS(array, 80);
-  BAD_ACCESS(array, 40);
-  BAD_ACCESS(array, 60);
-  BAD_ACCESS(array, 79);
-  EXPECT_DEATH(__asan_report_error(0, 0, 0, (uptr)(array + 40), true, 1),
-               kUseAfterPoisonErrorMessage);
-  __asan_unpoison_memory_region(array + 40, 40);
-  // access previously poisoned memory.
-  GOOD_ACCESS(array, 40);
-  GOOD_ACCESS(array, 79);
-  free(array);
-}
-
-TEST(AddressSanitizerInterface, OverlappingPoisonMemoryRegionTest) {
-  char *array = Ident((char*)malloc(120));
-  // Poison [0..40) and [80..120)
-  __asan_poison_memory_region(array, 40);
-  __asan_poison_memory_region(array + 80, 40);
-  BAD_ACCESS(array, 20);
-  GOOD_ACCESS(array, 60);
-  BAD_ACCESS(array, 100);
-  // Poison whole array - [0..120)
-  __asan_poison_memory_region(array, 120);
-  BAD_ACCESS(array, 60);
-  // Unpoison [24..96)
-  __asan_unpoison_memory_region(array + 24, 72);
-  BAD_ACCESS(array, 23);
-  GOOD_ACCESS(array, 24);
-  GOOD_ACCESS(array, 60);
-  GOOD_ACCESS(array, 95);
-  BAD_ACCESS(array, 96);
-  free(array);
-}
-
-TEST(AddressSanitizerInterface, PushAndPopWithPoisoningTest) {
-  // Vector of capacity 20
-  char *vec = Ident((char*)malloc(20));
-  __asan_poison_memory_region(vec, 20);
-  for (size_t i = 0; i < 7; i++) {
-    // Simulate push_back.
-    __asan_unpoison_memory_region(vec + i, 1);
-    GOOD_ACCESS(vec, i);
-    BAD_ACCESS(vec, i + 1);
-  }
-  for (size_t i = 7; i > 0; i--) {
-    // Simulate pop_back.
-    __asan_poison_memory_region(vec + i - 1, 1);
-    BAD_ACCESS(vec, i - 1);
-    if (i > 1) GOOD_ACCESS(vec, i - 2);
-  }
-  free(vec);
-}
-
-TEST(AddressSanitizerInterface, GlobalRedzones) {
-  GOOD_ACCESS(glob1, 1 - 1);
-  GOOD_ACCESS(glob2, 2 - 1);
-  GOOD_ACCESS(glob3, 3 - 1);
-  GOOD_ACCESS(glob4, 4 - 1);
-  GOOD_ACCESS(glob5, 5 - 1);
-  GOOD_ACCESS(glob6, 6 - 1);
-  GOOD_ACCESS(glob7, 7 - 1);
-  GOOD_ACCESS(glob8, 8 - 1);
-  GOOD_ACCESS(glob9, 9 - 1);
-  GOOD_ACCESS(glob10, 10 - 1);
-  GOOD_ACCESS(glob11, 11 - 1);
-  GOOD_ACCESS(glob12, 12 - 1);
-  GOOD_ACCESS(glob13, 13 - 1);
-  GOOD_ACCESS(glob14, 14 - 1);
-  GOOD_ACCESS(glob15, 15 - 1);
-  GOOD_ACCESS(glob16, 16 - 1);
-  GOOD_ACCESS(glob17, 17 - 1);
-  GOOD_ACCESS(glob1000, 1000 - 1);
-  GOOD_ACCESS(glob10000, 10000 - 1);
-  GOOD_ACCESS(glob100000, 100000 - 1);
-
-  BAD_ACCESS(glob1, 1);
-  BAD_ACCESS(glob2, 2);
-  BAD_ACCESS(glob3, 3);
-  BAD_ACCESS(glob4, 4);
-  BAD_ACCESS(glob5, 5);
-  BAD_ACCESS(glob6, 6);
-  BAD_ACCESS(glob7, 7);
-  BAD_ACCESS(glob8, 8);
-  BAD_ACCESS(glob9, 9);
-  BAD_ACCESS(glob10, 10);
-  BAD_ACCESS(glob11, 11);
-  BAD_ACCESS(glob12, 12);
-  BAD_ACCESS(glob13, 13);
-  BAD_ACCESS(glob14, 14);
-  BAD_ACCESS(glob15, 15);
-  BAD_ACCESS(glob16, 16);
-  BAD_ACCESS(glob17, 17);
-  BAD_ACCESS(glob1000, 1000);
-  BAD_ACCESS(glob1000, 1100);  // Redzone is at least 101 bytes.
-  BAD_ACCESS(glob10000, 10000);
-  BAD_ACCESS(glob10000, 11000);  // Redzone is at least 1001 bytes.
-  BAD_ACCESS(glob100000, 100000);
-  BAD_ACCESS(glob100000, 110000);  // Redzone is at least 10001 bytes.
-}
-
-// Make sure that each aligned block of size "2^granularity" doesn't have
-// "true" value before "false" value.
-static void MakeShadowValid(bool *shadow, int length, int granularity) {
-  bool can_be_poisoned = true;
-  for (int i = length - 1; i >= 0; i--) {
-    if (!shadow[i])
-      can_be_poisoned = false;
-    if (!can_be_poisoned)
-      shadow[i] = false;
-    if (i % (1 << granularity) == 0) {
-      can_be_poisoned = true;
-    }
-  }
-}
-
-TEST(AddressSanitizerInterface, PoisoningStressTest) {
-  const size_t kSize = 24;
-  bool expected[kSize];
-  char *arr = Ident((char*)malloc(kSize));
-  for (size_t l1 = 0; l1 < kSize; l1++) {
-    for (size_t s1 = 1; l1 + s1 <= kSize; s1++) {
-      for (size_t l2 = 0; l2 < kSize; l2++) {
-        for (size_t s2 = 1; l2 + s2 <= kSize; s2++) {
-          // Poison [l1, l1+s1), [l2, l2+s2) and check result.
-          __asan_unpoison_memory_region(arr, kSize);
-          __asan_poison_memory_region(arr + l1, s1);
-          __asan_poison_memory_region(arr + l2, s2);
-          memset(expected, false, kSize);
-          memset(expected + l1, true, s1);
-          MakeShadowValid(expected, kSize, /*granularity*/ 3);
-          memset(expected + l2, true, s2);
-          MakeShadowValid(expected, kSize, /*granularity*/ 3);
-          for (size_t i = 0; i < kSize; i++) {
-            ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));
-          }
-          // Unpoison [l1, l1+s1) and [l2, l2+s2) and check result.
-          __asan_poison_memory_region(arr, kSize);
-          __asan_unpoison_memory_region(arr + l1, s1);
-          __asan_unpoison_memory_region(arr + l2, s2);
-          memset(expected, true, kSize);
-          memset(expected + l1, false, s1);
-          MakeShadowValid(expected, kSize, /*granularity*/ 3);
-          memset(expected + l2, false, s2);
-          MakeShadowValid(expected, kSize, /*granularity*/ 3);
-          for (size_t i = 0; i < kSize; i++) {
-            ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));
-          }
-        }
-      }
-    }
-  }
-  free(arr);
-}
-
-TEST(AddressSanitizerInterface, PoisonedRegion) {
-  size_t rz = 16;
-  for (size_t size = 1; size <= 64; size++) {
-    char *p = new char[size];
-    uptr x = reinterpret_cast<uptr>(p);
-    for (size_t beg = 0; beg < size + rz; beg++) {
-      for (size_t end = beg; end < size + rz; end++) {
-        uptr first_poisoned = __asan_region_is_poisoned(x + beg, end - beg);
-        if (beg == end) {
-          EXPECT_FALSE(first_poisoned);
-        } else if (beg < size && end <= size) {
-          EXPECT_FALSE(first_poisoned);
-        } else if (beg >= size) {
-          EXPECT_EQ(x + beg, first_poisoned);
-        } else {
-          EXPECT_GT(end, size);
-          EXPECT_EQ(x + size, first_poisoned);
-        }
-      }
-    }
-    delete [] p;
-  }
-}
-
-// This is a performance benchmark for manual runs.
-// asan's memset interceptor calls mem_is_zero for the entire shadow region.
-// the profile should look like this:
-//     89.10%   [.] __memset_sse2
-//     10.50%   [.] __sanitizer::mem_is_zero
-// I.e. mem_is_zero should consume ~ SHADOW_GRANULARITY less CPU cycles
-// than memset itself.
-TEST(AddressSanitizerInterface, DISABLED_StressLargeMemset) {
-  size_t size = 1 << 20;
-  char *x = new char[size];
-  for (int i = 0; i < 100000; i++)
-    Ident(memset)(x, 0, size);
-  delete [] x;
-}
-
-// Same here, but we run memset with small sizes.
-TEST(AddressSanitizerInterface, DISABLED_StressSmallMemset) {
-  size_t size = 32;
-  char *x = new char[size];
-  for (int i = 0; i < 100000000; i++)
-    Ident(memset)(x, 0, size);
-  delete [] x;
-}
-
-static const char *kInvalidPoisonMessage = "invalid-poison-memory-range";
-static const char *kInvalidUnpoisonMessage = "invalid-unpoison-memory-range";
-
-TEST(AddressSanitizerInterface, DISABLED_InvalidPoisonAndUnpoisonCallsTest) {
-  char *array = Ident((char*)malloc(120));
-  __asan_unpoison_memory_region(array, 120);
-  // Try to unpoison not owned memory
-  EXPECT_DEATH(__asan_unpoison_memory_region(array, 121),
-               kInvalidUnpoisonMessage);
-  EXPECT_DEATH(__asan_unpoison_memory_region(array - 1, 120),
-               kInvalidUnpoisonMessage);
-
-  __asan_poison_memory_region(array, 120);
-  // Try to poison not owned memory.
-  EXPECT_DEATH(__asan_poison_memory_region(array, 121), kInvalidPoisonMessage);
-  EXPECT_DEATH(__asan_poison_memory_region(array - 1, 120),
-               kInvalidPoisonMessage);
-  free(array);
-}
-
-static void ErrorReportCallbackOneToZ(const char *report) {
-  int report_len = strlen(report);
-  ASSERT_EQ(6, write(2, "ABCDEF", 6));
-  ASSERT_EQ(report_len, write(2, report, report_len));
-  ASSERT_EQ(6, write(2, "ABCDEF", 6));
-  _exit(1);
-}
-
-TEST(AddressSanitizerInterface, SetErrorReportCallbackTest) {
-  __asan_set_error_report_callback(ErrorReportCallbackOneToZ);
-  EXPECT_DEATH(__asan_report_error(0, 0, 0, 0, true, 1),
-               ASAN_PCRE_DOTALL "ABCDEF.*AddressSanitizer.*WRITE.*ABCDEF");
-  __asan_set_error_report_callback(NULL);
-}
-
-TEST(AddressSanitizerInterface, GetOwnershipStressTest) {
-  std::vector<char *> pointers;
-  std::vector<size_t> sizes;
-  const size_t kNumMallocs = 1 << 9;
-  for (size_t i = 0; i < kNumMallocs; i++) {
-    size_t size = i * 100 + 1;
-    pointers.push_back((char*)malloc(size));
-    sizes.push_back(size);
-  }
-  for (size_t i = 0; i < 4000000; i++) {
-    EXPECT_FALSE(__asan_get_ownership(&pointers));
-    EXPECT_FALSE(__asan_get_ownership((void*)0x1234));
-    size_t idx = i % kNumMallocs;
-    EXPECT_TRUE(__asan_get_ownership(pointers[idx]));
-    EXPECT_EQ(sizes[idx], __asan_get_allocated_size(pointers[idx]));
-  }
-  for (size_t i = 0, n = pointers.size(); i < n; i++)
-    free(pointers[i]);
-}
-
-
-TEST(AddressSanitizerInterface, CallocOverflow32) {
-#if SANITIZER_WORDSIZE == 32
-  size_t kArraySize = 112;
-  volatile size_t kArraySize2 = 43878406;
-  void *p = 0;
-  EXPECT_DEATH(p = calloc(kArraySize, kArraySize2),
-               "allocator is terminating the process instead of returning 0");
-  assert(!p);
-#endif
-}
-
-TEST(AddressSanitizerInterface, CallocReturnsZeroMem) {
-  size_t sizes[] = {16, 1000, 10000, 100000, 2100000};
-  for (size_t s = 0; s < ARRAY_SIZE(sizes); s++) {
-    size_t size = sizes[s];
-    for (size_t iter = 0; iter < 5; iter++) {
-      char *x = Ident((char*)calloc(1, size));
-      EXPECT_EQ(x[0], 0);
-      EXPECT_EQ(x[size - 1], 0);
-      EXPECT_EQ(x[size / 2], 0);
-      EXPECT_EQ(x[size / 3], 0);
-      EXPECT_EQ(x[size / 4], 0);
-      memset(x, 0x42, size);
-      free(Ident(x));
-      free(Ident(malloc(Ident(1 << 27))));  // Try to drain the quarantine.
-    }
-  }
+  // Check that __asan_region_is_poisoned works for shadow regions.
+  uptr ptr = kLowShadowBeg + 200;
+  EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100));
+  ptr = kShadowGapBeg + 200;
+  EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100));
+  ptr = kHighShadowBeg + 200;
+  EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100));
 }

Modified: compiler-rt/trunk/lib/asan/tests/asan_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_test.cc?rev=190788&r1=190787&r2=190788&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_test.cc Mon Sep 16 10:50:53 2013
@@ -111,6 +111,35 @@ TEST(AddressSanitizer, CallocTest) {
   free(a);
 }
 
+TEST(AddressSanitizer, CallocOverflow32) {
+#if SANITIZER_WORDSIZE == 32
+  size_t kArraySize = 112;
+  volatile size_t kArraySize2 = 43878406;
+  void *p = 0;
+  EXPECT_DEATH(p = calloc(kArraySize, kArraySize2),
+               "allocator is terminating the process instead of returning 0");
+  assert(!p);
+#endif
+}
+
+TEST(AddressSanitizer, CallocReturnsZeroMem) {
+  size_t sizes[] = {16, 1000, 10000, 100000, 2100000};
+  for (size_t s = 0; s < sizeof(sizes)/sizeof(sizes[0]); s++) {
+    size_t size = sizes[s];
+    for (size_t iter = 0; iter < 5; iter++) {
+      char *x = Ident((char*)calloc(1, size));
+      EXPECT_EQ(x[0], 0);
+      EXPECT_EQ(x[size - 1], 0);
+      EXPECT_EQ(x[size / 2], 0);
+      EXPECT_EQ(x[size / 3], 0);
+      EXPECT_EQ(x[size / 4], 0);
+      memset(x, 0x42, size);
+      free(Ident(x));
+      free(Ident(malloc(Ident(1 << 27))));  // Try to drain the quarantine.
+    }
+  }
+}
+
 TEST(AddressSanitizer, VallocTest) {
   void *a = valloc(100);
   EXPECT_EQ(0U, (uintptr_t)a % kPageSize);





More information about the llvm-commits mailing list