brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.4 KiB · 021ebfb Raw
422 lines · cpp
1//===-- asan_interface_test.cpp -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of AddressSanitizer, an address sanity checker.10//11//===----------------------------------------------------------------------===//12#include "asan_test_utils.h"13#include "sanitizer_common/sanitizer_internal_defs.h"14#include <sanitizer/allocator_interface.h>15#include <sanitizer/asan_interface.h>16#include <vector>17 18TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) {19  EXPECT_EQ(0U, __sanitizer_get_estimated_allocated_size(0));20  const size_t sizes[] = { 1, 30, 1<<30 };21  for (size_t i = 0; i < 3; i++) {22    EXPECT_EQ(sizes[i], __sanitizer_get_estimated_allocated_size(sizes[i]));23  }24}25 26static const char* kGetAllocatedSizeErrorMsg =27  "attempting to call __sanitizer_get_allocated_size";28 29TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) {30  const size_t kArraySize = 100;31  char *array = Ident((char*)malloc(kArraySize));32  int *int_ptr = Ident(new int);33 34  // Allocated memory is owned by allocator. Allocated size should be35  // equal to requested size.36  EXPECT_EQ(true, __sanitizer_get_ownership(array));37  EXPECT_EQ(kArraySize, __sanitizer_get_allocated_size(array));38  EXPECT_EQ(true, __sanitizer_get_ownership(int_ptr));39  EXPECT_EQ(sizeof(int), __sanitizer_get_allocated_size(int_ptr));40 41  // We cannot call GetAllocatedSize from the memory we didn't map,42  // and from the interior pointers (not returned by previous malloc).43  void *wild_addr = (void*)0x1;44  EXPECT_FALSE(__sanitizer_get_ownership(wild_addr));45  EXPECT_DEATH(__sanitizer_get_allocated_size(wild_addr),46               kGetAllocatedSizeErrorMsg);47  EXPECT_FALSE(__sanitizer_get_ownership(array + kArraySize / 2));48  EXPECT_DEATH(__sanitizer_get_allocated_size(array + kArraySize / 2),49               kGetAllocatedSizeErrorMsg);50 51  // NULL is not owned, but is a valid argument for52  // __sanitizer_get_allocated_size().53  EXPECT_FALSE(__sanitizer_get_ownership(NULL));54  EXPECT_EQ(0U, __sanitizer_get_allocated_size(NULL));55 56  // When memory is freed, it's not owned, and call to GetAllocatedSize57  // is forbidden.58  free(array);59  EXPECT_FALSE(__sanitizer_get_ownership(array));60  EXPECT_DEATH(__sanitizer_get_allocated_size(array),61               kGetAllocatedSizeErrorMsg);62  delete int_ptr;63 64  void *zero_alloc = Ident(malloc(0));65  if (zero_alloc != 0) {66    // If malloc(0) is not null, this pointer is owned and should have valid67    // allocated size.68    EXPECT_TRUE(__sanitizer_get_ownership(zero_alloc));69    // Allocated size is 0 or 1 depending on the allocator used.70    EXPECT_LT(__sanitizer_get_allocated_size(zero_alloc), 2U);71  }72  free(zero_alloc);73}74 75TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) {76  size_t before_malloc, after_malloc, after_free;77  char *array;78  const size_t kMallocSize = 100;79  before_malloc = __sanitizer_get_current_allocated_bytes();80 81  array = Ident((char*)malloc(kMallocSize));82  after_malloc = __sanitizer_get_current_allocated_bytes();83  EXPECT_EQ(before_malloc + kMallocSize, after_malloc);84 85  free(array);86  after_free = __sanitizer_get_current_allocated_bytes();87  EXPECT_EQ(before_malloc, after_free);88}89 90TEST(AddressSanitizerInterface, GetHeapSizeTest) {91  // ASan allocator does not keep huge chunks in free list, but unmaps them.92  // The chunk should be greater than the quarantine size,93  // otherwise it will be stuck in quarantine instead of being unmapped.94  static const size_t kLargeMallocSize = (1 << 28) + 1;  // 256M95  free(Ident(malloc(kLargeMallocSize)));  // Drain quarantine.96  size_t old_heap_size = __sanitizer_get_heap_size();97  for (int i = 0; i < 3; i++) {98    // fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize);99    free(Ident(malloc(kLargeMallocSize)));100    EXPECT_EQ(old_heap_size, __sanitizer_get_heap_size());101  }102}103 104#if !defined(__NetBSD__)105static const size_t kManyThreadsMallocSizes[] = {5, 1UL<<10, 1UL<<14, 357};106static const size_t kManyThreadsIterations = 250;107static const size_t kManyThreadsNumThreads =108  (SANITIZER_WORDSIZE == 32) ? 40 : 200;109 110static void *ManyThreadsWithStatsWorker(void *arg) {111  (void)arg;112  for (size_t iter = 0; iter < kManyThreadsIterations; iter++) {113    for (size_t size_index = 0; size_index < 4; size_index++) {114      free(Ident(malloc(kManyThreadsMallocSizes[size_index])));115    }116  }117  // Just one large allocation.118  free(Ident(malloc(1 << 20)));119  return 0;120}121 122TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) {123  size_t before_test, after_test, i;124  pthread_t threads[kManyThreadsNumThreads];125  before_test = __sanitizer_get_current_allocated_bytes();126  for (i = 0; i < kManyThreadsNumThreads; i++) {127    PTHREAD_CREATE(&threads[i], 0,128                   (void* (*)(void *x))ManyThreadsWithStatsWorker, (void*)i);129  }130  for (i = 0; i < kManyThreadsNumThreads; i++) {131    PTHREAD_JOIN(threads[i], 0);132  }133  after_test = __sanitizer_get_current_allocated_bytes();134  // ASan stats also reflect memory usage of internal ASan RTL structs,135  // so we can't check for equality here.136  EXPECT_LT(after_test, before_test + (1UL<<20));137}138#endif139 140static void DoDoubleFree() {141  int *x = Ident(new int);142  delete Ident(x);143  delete Ident(x);144}145 146static void MyDeathCallback() {147  fprintf(stderr, "MyDeathCallback\n");148  fflush(0);  // On Windows, stderr doesn't flush on crash.149}150 151TEST(AddressSanitizerInterface, DeathCallbackTest) {152  __asan_set_death_callback(MyDeathCallback);153  EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback");154  __asan_set_death_callback(NULL);155}156 157#define GOOD_ACCESS(ptr, offset)  \158    EXPECT_FALSE(__asan_address_is_poisoned(ptr + offset))159 160#define BAD_ACCESS(ptr, offset) \161    EXPECT_TRUE(__asan_address_is_poisoned(ptr + offset))162 163static const char* kUseAfterPoisonErrorMessage = "use-after-poison";164 165TEST(AddressSanitizerInterface, SimplePoisonMemoryRegionTest) {166  char *array = Ident((char*)malloc(120));167  // poison array[40..80)168  __asan_poison_memory_region(array + 40, 40);169  GOOD_ACCESS(array, 39);170  GOOD_ACCESS(array, 80);171  BAD_ACCESS(array, 40);172  BAD_ACCESS(array, 60);173  BAD_ACCESS(array, 79);174  EXPECT_DEATH(Ident(array[40]), kUseAfterPoisonErrorMessage);175  __asan_unpoison_memory_region(array + 40, 40);176  // access previously poisoned memory.177  GOOD_ACCESS(array, 40);178  GOOD_ACCESS(array, 79);179  free(array);180}181 182TEST(AddressSanitizerInterface, OverlappingPoisonMemoryRegionTest) {183  char *array = Ident((char*)malloc(120));184  // Poison [0..40) and [80..120)185  __asan_poison_memory_region(array, 40);186  __asan_poison_memory_region(array + 80, 40);187  BAD_ACCESS(array, 20);188  GOOD_ACCESS(array, 60);189  BAD_ACCESS(array, 100);190  // Poison whole array - [0..120)191  __asan_poison_memory_region(array, 120);192  BAD_ACCESS(array, 60);193  // Unpoison [24..96)194  __asan_unpoison_memory_region(array + 24, 72);195  BAD_ACCESS(array, 23);196  GOOD_ACCESS(array, 24);197  GOOD_ACCESS(array, 60);198  GOOD_ACCESS(array, 95);199  BAD_ACCESS(array, 96);200  free(array);201}202 203TEST(AddressSanitizerInterface, PushAndPopWithPoisoningTest) {204  // Vector of capacity 20205  char *vec = Ident((char*)malloc(20));206  __asan_poison_memory_region(vec, 20);207  for (size_t i = 0; i < 7; i++) {208    // Simulate push_back.209    __asan_unpoison_memory_region(vec + i, 1);210    GOOD_ACCESS(vec, i);211    BAD_ACCESS(vec, i + 1);212  }213  for (size_t i = 7; i > 0; i--) {214    // Simulate pop_back.215    __asan_poison_memory_region(vec + i - 1, 1);216    BAD_ACCESS(vec, i - 1);217    if (i > 1) GOOD_ACCESS(vec, i - 2);218  }219  free(vec);220}221 222#if !defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3223// Make sure that each aligned block of size "2^granularity" doesn't have224// "true" value before "false" value.225static void MakeShadowValid(bool *shadow, int length, int granularity) {226  bool can_be_poisoned = true;227  for (int i = length - 1; i >= 0; i--) {228    if (!shadow[i])229      can_be_poisoned = false;230    if (!can_be_poisoned)231      shadow[i] = false;232    if (i % (1 << granularity) == 0) {233      can_be_poisoned = true;234    }235  }236}237 238TEST(AddressSanitizerInterface, PoisoningStressTest) {239  const size_t kSize = 24;240  bool expected[kSize];241  char *arr = Ident((char*)malloc(kSize));242  for (size_t l1 = 0; l1 < kSize; l1++) {243    for (size_t s1 = 1; l1 + s1 <= kSize; s1++) {244      for (size_t l2 = 0; l2 < kSize; l2++) {245        for (size_t s2 = 1; l2 + s2 <= kSize; s2++) {246          // Poison [l1, l1+s1), [l2, l2+s2) and check result.247          __asan_unpoison_memory_region(arr, kSize);248          __asan_poison_memory_region(arr + l1, s1);249          __asan_poison_memory_region(arr + l2, s2);250          memset(expected, false, kSize);251          memset(expected + l1, true, s1);252          MakeShadowValid(expected, kSize, /*granularity*/ 3);253          memset(expected + l2, true, s2);254          MakeShadowValid(expected, kSize, /*granularity*/ 3);255          for (size_t i = 0; i < kSize; i++) {256            ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));257          }258          // Unpoison [l1, l1+s1) and [l2, l2+s2) and check result.259          __asan_poison_memory_region(arr, kSize);260          __asan_unpoison_memory_region(arr + l1, s1);261          __asan_unpoison_memory_region(arr + l2, s2);262          memset(expected, true, kSize);263          memset(expected + l1, false, s1);264          MakeShadowValid(expected, kSize, /*granularity*/ 3);265          memset(expected + l2, false, s2);266          MakeShadowValid(expected, kSize, /*granularity*/ 3);267          for (size_t i = 0; i < kSize; i++) {268            ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));269          }270        }271      }272    }273  }274  free(arr);275}276#endif  // !defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3277 278TEST(AddressSanitizerInterface, GlobalRedzones) {279  GOOD_ACCESS(glob1, 1 - 1);280  GOOD_ACCESS(glob2, 2 - 1);281  GOOD_ACCESS(glob3, 3 - 1);282  GOOD_ACCESS(glob4, 4 - 1);283  GOOD_ACCESS(glob5, 5 - 1);284  GOOD_ACCESS(glob6, 6 - 1);285  GOOD_ACCESS(glob7, 7 - 1);286  GOOD_ACCESS(glob8, 8 - 1);287  GOOD_ACCESS(glob9, 9 - 1);288  GOOD_ACCESS(glob10, 10 - 1);289  GOOD_ACCESS(glob11, 11 - 1);290  GOOD_ACCESS(glob12, 12 - 1);291  GOOD_ACCESS(glob13, 13 - 1);292  GOOD_ACCESS(glob14, 14 - 1);293  GOOD_ACCESS(glob15, 15 - 1);294  GOOD_ACCESS(glob16, 16 - 1);295  GOOD_ACCESS(glob17, 17 - 1);296  GOOD_ACCESS(glob1000, 1000 - 1);297  GOOD_ACCESS(glob10000, 10000 - 1);298  GOOD_ACCESS(glob100000, 100000 - 1);299 300  BAD_ACCESS(glob1, 1);301  BAD_ACCESS(glob2, 2);302  BAD_ACCESS(glob3, 3);303  BAD_ACCESS(glob4, 4);304  BAD_ACCESS(glob5, 5);305  BAD_ACCESS(glob6, 6);306  BAD_ACCESS(glob7, 7);307  BAD_ACCESS(glob8, 8);308  BAD_ACCESS(glob9, 9);309  BAD_ACCESS(glob10, 10);310  BAD_ACCESS(glob11, 11);311  BAD_ACCESS(glob12, 12);312  BAD_ACCESS(glob13, 13);313  BAD_ACCESS(glob14, 14);314  BAD_ACCESS(glob15, 15);315  BAD_ACCESS(glob16, 16);316  BAD_ACCESS(glob17, 17);317  BAD_ACCESS(glob1000, 1000);318  BAD_ACCESS(glob1000, 1100);  // Redzone is at least 101 bytes.319  BAD_ACCESS(glob10000, 10000);320  BAD_ACCESS(glob10000, 11000);  // Redzone is at least 1001 bytes.321  BAD_ACCESS(glob100000, 100000);322  BAD_ACCESS(glob100000, 110000);  // Redzone is at least 10001 bytes.323}324 325TEST(AddressSanitizerInterface, PoisonedRegion) {326  size_t rz = 16;327  for (size_t size = 1; size <= 64; size++) {328    char *p = new char[size];329    for (size_t beg = 0; beg < size + rz; beg++) {330      for (size_t end = beg; end < size + rz; end++) {331        void *first_poisoned = __asan_region_is_poisoned(p + beg, end - beg);332        if (beg == end) {333          EXPECT_FALSE(first_poisoned);334        } else if (beg < size && end <= size) {335          EXPECT_FALSE(first_poisoned);336        } else if (beg >= size) {337          EXPECT_EQ(p + beg, first_poisoned);338        } else {339          EXPECT_GT(end, size);340          EXPECT_EQ(p + size, first_poisoned);341        }342      }343    }344    delete [] p;345  }346}347 348// This is a performance benchmark for manual runs.349// asan's memset interceptor calls mem_is_zero for the entire shadow region.350// the profile should look like this:351//     89.10%   [.] __memset_sse2352//     10.50%   [.] __sanitizer::mem_is_zero353// I.e. mem_is_zero should consume ~ SHADOW_GRANULARITY less CPU cycles354// than memset itself.355TEST(AddressSanitizerInterface, DISABLED_StressLargeMemset) {356  size_t size = 1 << 20;357  char *x = new char[size];358  for (int i = 0; i < 100000; i++)359    Ident(memset)(x, 0, size);360  delete [] x;361}362 363// Same here, but we run memset with small sizes.364TEST(AddressSanitizerInterface, DISABLED_StressSmallMemset) {365  size_t size = 32;366  char *x = new char[size];367  for (int i = 0; i < 100000000; i++)368    Ident(memset)(x, 0, size);369  delete [] x;370}371static const char *kInvalidPoisonMessage = "invalid-poison-memory-range";372static const char *kInvalidUnpoisonMessage = "invalid-unpoison-memory-range";373 374TEST(AddressSanitizerInterface, DISABLED_InvalidPoisonAndUnpoisonCallsTest) {375  char *array = Ident((char*)malloc(120));376  __asan_unpoison_memory_region(array, 120);377  // Try to unpoison not owned memory378  EXPECT_DEATH(__asan_unpoison_memory_region(array, 121),379               kInvalidUnpoisonMessage);380  EXPECT_DEATH(__asan_unpoison_memory_region(array - 1, 120),381               kInvalidUnpoisonMessage);382 383  __asan_poison_memory_region(array, 120);384  // Try to poison not owned memory.385  EXPECT_DEATH(__asan_poison_memory_region(array, 121), kInvalidPoisonMessage);386  EXPECT_DEATH(__asan_poison_memory_region(array - 1, 120),387               kInvalidPoisonMessage);388  free(array);389}390 391TEST(AddressSanitizerInterface, GetOwnershipStressTest) {392  std::vector<char *> pointers;393  std::vector<size_t> sizes;394  const size_t kNumMallocs = 1 << 9;395  for (size_t i = 0; i < kNumMallocs; i++) {396    size_t size = i * 100 + 1;397    pointers.push_back((char*)malloc(size));398    sizes.push_back(size);399  }400  for (size_t i = 0; i < 4000000; i++) {401    EXPECT_FALSE(__sanitizer_get_ownership(&pointers));402    EXPECT_FALSE(__sanitizer_get_ownership((void*)0x1234));403    size_t idx = i % kNumMallocs;404    EXPECT_TRUE(__sanitizer_get_ownership(pointers[idx]));405    EXPECT_EQ(sizes[idx], __sanitizer_get_allocated_size(pointers[idx]));406  }407  for (size_t i = 0, n = pointers.size(); i < n; i++)408    free(pointers[i]);409}410 411TEST(AddressSanitizerInterface, HandleNoReturnTest) {412  char array[40];413  __asan_poison_memory_region(array, sizeof(array));414  BAD_ACCESS(array, 20);415  __asan_handle_no_return();416  // Fake stack does not need to be unpoisoned.417  if (__asan_get_current_fake_stack())418    return;419  // It unpoisons the whole thread stack.420  GOOD_ACCESS(array, 20);421}422