brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.1 KiB · ee0ac6a Raw
180 lines · cpp
1//===-- sanitizer_quarantine_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 ThreadSanitizer/AddressSanitizer runtime.10//11//===----------------------------------------------------------------------===//12#include "sanitizer_common/sanitizer_common.h"13#include "sanitizer_common/sanitizer_quarantine.h"14#include "gtest/gtest.h"15 16#include <stdlib.h>17 18namespace __sanitizer {19 20struct QuarantineCallback {21  void Recycle(void *m) {}22  void *Allocate(uptr size) {23    return malloc(size);24  }25  void Deallocate(void *p) {26    free(p);27  }28};29 30typedef QuarantineCache<QuarantineCallback> Cache;31 32static void* kFakePtr = reinterpret_cast<void*>(0xFA83FA83);33static const size_t kBlockSize = 8;34 35static QuarantineCallback cb;36 37static void DeallocateCache(Cache *cache) {38  while (QuarantineBatch *batch = cache->DequeueBatch())39    cb.Deallocate(batch);40}41 42TEST(SanitizerCommon, QuarantineBatchMerge) {43  // Verify the trivial case.44  QuarantineBatch into;45  into.init(kFakePtr, 4UL);46  QuarantineBatch from;47  from.init(kFakePtr, 8UL);48 49  into.merge(&from);50 51  ASSERT_EQ(into.count, 2UL);52  ASSERT_EQ(into.batch[0], kFakePtr);53  ASSERT_EQ(into.batch[1], kFakePtr);54  ASSERT_EQ(into.size, 12UL + sizeof(QuarantineBatch));55  ASSERT_EQ(into.quarantined_size(), 12UL);56 57  ASSERT_EQ(from.count, 0UL);58  ASSERT_EQ(from.size, sizeof(QuarantineBatch));59  ASSERT_EQ(from.quarantined_size(), 0UL);60 61  // Merge the batch to the limit.62  for (uptr i = 2; i < QuarantineBatch::kSize; ++i)63    from.push_back(kFakePtr, 8UL);64  ASSERT_TRUE(into.count + from.count == QuarantineBatch::kSize);65  ASSERT_TRUE(into.can_merge(&from));66 67  into.merge(&from);68  ASSERT_TRUE(into.count == QuarantineBatch::kSize);69 70  // No more space, not even for one element.71  from.init(kFakePtr, 8UL);72 73  ASSERT_FALSE(into.can_merge(&from));74}75 76TEST(SanitizerCommon, QuarantineCacheMergeBatchesEmpty) {77  Cache cache;78  Cache to_deallocate;79  cache.MergeBatches(&to_deallocate);80 81  ASSERT_EQ(to_deallocate.Size(), 0UL);82  ASSERT_EQ(to_deallocate.DequeueBatch(), nullptr);83}84 85TEST(SanitizerCommon, QuarantineCacheMergeBatchesOneBatch) {86  Cache cache;87  cache.Enqueue(cb, kFakePtr, kBlockSize);88  ASSERT_EQ(kBlockSize + sizeof(QuarantineBatch), cache.Size());89 90  Cache to_deallocate;91  cache.MergeBatches(&to_deallocate);92 93  // Nothing to merge, nothing to deallocate.94  ASSERT_EQ(kBlockSize + sizeof(QuarantineBatch), cache.Size());95 96  ASSERT_EQ(to_deallocate.Size(), 0UL);97  ASSERT_EQ(to_deallocate.DequeueBatch(), nullptr);98 99  DeallocateCache(&cache);100}101 102TEST(SanitizerCommon, QuarantineCacheMergeBatchesSmallBatches) {103  // Make a cache with two batches small enough to merge.104  Cache from;105  from.Enqueue(cb, kFakePtr, kBlockSize);106  Cache cache;107  cache.Enqueue(cb, kFakePtr, kBlockSize);108 109  cache.Transfer(&from);110  ASSERT_EQ(kBlockSize * 2 + sizeof(QuarantineBatch) * 2, cache.Size());111 112  Cache to_deallocate;113  cache.MergeBatches(&to_deallocate);114 115  // Batches merged, one batch to deallocate.116  ASSERT_EQ(kBlockSize * 2 + sizeof(QuarantineBatch), cache.Size());117  ASSERT_EQ(to_deallocate.Size(), sizeof(QuarantineBatch));118 119  DeallocateCache(&cache);120  DeallocateCache(&to_deallocate);121}122 123TEST(SanitizerCommon, QuarantineCacheMergeBatchesTooBigToMerge) {124  const uptr kNumBlocks = QuarantineBatch::kSize - 1;125 126  // Make a cache with two batches small enough to merge.127  Cache from;128  Cache cache;129  for (uptr i = 0; i < kNumBlocks; ++i) {130    from.Enqueue(cb, kFakePtr, kBlockSize);131    cache.Enqueue(cb, kFakePtr, kBlockSize);132  }133  cache.Transfer(&from);134  ASSERT_EQ(kBlockSize * kNumBlocks * 2 +135            sizeof(QuarantineBatch) * 2, cache.Size());136 137  Cache to_deallocate;138  cache.MergeBatches(&to_deallocate);139 140  // Batches cannot be merged.141  ASSERT_EQ(kBlockSize * kNumBlocks * 2 +142            sizeof(QuarantineBatch) * 2, cache.Size());143  ASSERT_EQ(to_deallocate.Size(), 0UL);144 145  DeallocateCache(&cache);146}147 148TEST(SanitizerCommon, QuarantineCacheMergeBatchesALotOfBatches) {149  const uptr kNumBatchesAfterMerge = 3;150  const uptr kNumBlocks = QuarantineBatch::kSize * kNumBatchesAfterMerge;151  const uptr kNumBatchesBeforeMerge = kNumBlocks;152 153  // Make a cache with many small batches.154  Cache cache;155  for (uptr i = 0; i < kNumBlocks; ++i) {156    Cache from;157    from.Enqueue(cb, kFakePtr, kBlockSize);158    cache.Transfer(&from);159  }160 161  ASSERT_EQ(kBlockSize * kNumBlocks +162            sizeof(QuarantineBatch) * kNumBatchesBeforeMerge, cache.Size());163 164  Cache to_deallocate;165  cache.MergeBatches(&to_deallocate);166 167  // All blocks should fit into 3 batches.168  ASSERT_EQ(kBlockSize * kNumBlocks +169            sizeof(QuarantineBatch) * kNumBatchesAfterMerge, cache.Size());170 171  ASSERT_EQ(to_deallocate.Size(),172            sizeof(QuarantineBatch) *173                (kNumBatchesBeforeMerge - kNumBatchesAfterMerge));174 175  DeallocateCache(&cache);176  DeallocateCache(&to_deallocate);177}178 179}  // namespace __sanitizer180