Coverage for /Syzygy/agent/asan/shadow_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%4874870.C++test

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/agent/asan/shadow.h"
  16    :  
  17    :  #include "base/rand_util.h"
  18    :  #include "base/memory/scoped_ptr.h"
  19    :  #include "gtest/gtest.h"
  20    :  #include "syzygy/common/align.h"
  21    :  #include "syzygy/testing/metrics.h"
  22    :  
  23    :  namespace agent {
  24    :  namespace asan {
  25    :  
  26    :  namespace {
  27    :  
  28    :  // A derived class to expose protected members for unit-testing.
  29    :  class TestShadow : public Shadow {
  30    :   public:
  31    :    using Shadow::Reset;
  32    :    using Shadow::ScanLeftForBracketingBlockStart;
  33    :    using Shadow::ScanRightForBracketingBlockEnd;
  34    :    using Shadow::kShadowSize;
  35    :    using Shadow::shadow_;
  36    :  };
  37    :  
  38    :  }  // namespace
  39    :  
  40  E :  TEST(ShadowTest, PoisonUnpoisonAccess) {
  41    :    // Reset the shadow memory.
  42  E :    TestShadow::Reset();
  43  E :    for (size_t count = 0; count < 100; ++count) {
  44    :      // Use a random 8-byte aligned end address.
  45  E :      const size_t size = base::RandInt(1, 16384);
  46    :      const uint8* end_addr =
  47  E :          reinterpret_cast<const uint8*>(base::RandInt(65536, 10*1024*1024) * 8);
  48  E :      const uint8* start_addr = end_addr - size;
  49    :  
  50  E :      for (size_t i = 0; i < size; ++i)
  51  E :        EXPECT_TRUE(Shadow::IsAccessible(start_addr + i));
  52    :  
  53  E :      Shadow::Poison(start_addr, size, kAsanReservedMarker);
  54  E :      for (size_t i = 0; i < size; ++i)
  55  E :        EXPECT_FALSE(Shadow::IsAccessible(start_addr + i));
  56  E :      EXPECT_TRUE(Shadow::IsAccessible(start_addr - 1));
  57  E :      EXPECT_TRUE(Shadow::IsAccessible(start_addr + size));
  58    :  
  59    :      const size_t aligned_size = ::common::AlignUp(size,
  60  E :                                                    kShadowRatio);
  61  E :      const uint8* aligned_start_addr = end_addr - aligned_size;
  62  E :      Shadow::Unpoison(aligned_start_addr, aligned_size);
  63  E :      for (size_t i = 0; i < size; ++i)
  64  E :        EXPECT_TRUE(Shadow::IsAccessible(start_addr + i));
  65  E :    }
  66  E :  }
  67    :  
  68  E :  TEST(ShadowTest, SetUpAndTearDown) {
  69    :    // Reset the shadow memory.
  70  E :    TestShadow::Reset();
  71    :  
  72    :    // Don't check all the shadow bytes otherwise this test will take too much
  73    :    // time.
  74  E :    const size_t kLookupInterval = 25;
  75    :  
  76  E :    intptr_t shadow_array_start = reinterpret_cast<intptr_t>(TestShadow::shadow_);
  77  E :    size_t shadow_start = shadow_array_start >> 3;
  78  E :    size_t shadow_end = shadow_start + (TestShadow::kShadowSize >> 3);
  79    :  
  80  E :    const size_t non_addressable_memory_end = (0x10000 >> 3);
  81    :  
  82  E :    Shadow::SetUp();
  83  E :    for (size_t i = shadow_start; i < shadow_end; i += kLookupInterval)
  84  E :      ASSERT_EQ(kAsanMemoryMarker, TestShadow::shadow_[i]);
  85    :  
  86  E :    for (size_t i = 0; i < non_addressable_memory_end; i += kLookupInterval)
  87  E :      ASSERT_EQ(kInvalidAddressMarker, TestShadow::shadow_[i]);
  88    :  
  89  E :    Shadow::TearDown();
  90  E :    for (size_t i = shadow_start; i < shadow_end; i += kLookupInterval)
  91  E :      ASSERT_EQ(kHeapAddressableMarker, TestShadow::shadow_[i]);
  92    :  
  93  E :    for (size_t i = 0; i < non_addressable_memory_end; i += kLookupInterval)
  94  E :      ASSERT_EQ(kHeapAddressableMarker, TestShadow::shadow_[i]);
  95  E :  }
  96    :  
  97  E :  TEST(ShadowTest, GetNullTerminatedArraySize) {
  98    :    // Reset the shadow memory.
  99  E :    TestShadow::Reset();
 100  E :    const size_t kArrayLength = 100;
 101  E :    const uint8 kMarkerValue = 0xAA;
 102    :  
 103    :    uint8 test_array[kArrayLength];
 104    :    uint8* aligned_test_array = reinterpret_cast<uint8*>(
 105    :        ::common::AlignUp(reinterpret_cast<size_t>(test_array),
 106  E :                          kShadowRatio));
 107    :    size_t aligned_array_length = ::common::AlignDown(kArrayLength -
 108  E :        (aligned_test_array - test_array), kShadowRatio);
 109    :  
 110  E :    ::memset(aligned_test_array, kMarkerValue, aligned_array_length);
 111    :    Shadow::Poison(aligned_test_array, aligned_array_length,
 112  E :                   kAsanReservedMarker);
 113    :  
 114  E :    size_t sizes_to_test[] = { 4, 7, 12, 15, 21, 87, 88 };
 115    :  
 116  E :    for (size_t i = 0; i < arraysize(sizes_to_test); ++i) {
 117  E :      Shadow::Unpoison(aligned_test_array, sizes_to_test[i]);
 118  E :      size_t size = 0;
 119    :  
 120    :      // Put a null byte at the end of the array and call the
 121    :      // GetNullTerminatedArraySize function with a 1-byte template argument. This
 122    :      // simulates the use of this function for a null terminated string.
 123  E :      aligned_test_array[sizes_to_test[i] - 1] = 0;
 124    :      EXPECT_TRUE(Shadow::GetNullTerminatedArraySize<uint8>(aligned_test_array,
 125    :                                                            0U,
 126  E :                                                            &size));
 127  E :      EXPECT_EQ(sizes_to_test[i], size);
 128    :  
 129  E :      if (sizes_to_test[i] % sizeof(uint16) == 0) {
 130    :        // Call the GetNullTerminatedArraySize with a 2-byte template argument.
 131    :        // As there is only one null byte at the end of the array we expect the
 132    :        // function to return false.
 133    :        EXPECT_FALSE(Shadow::GetNullTerminatedArraySize<uint16>(
 134  E :            aligned_test_array, 0U, &size));
 135  E :        EXPECT_EQ(sizes_to_test[i], size);
 136    :        // Put a second null byte at the end of the array and call the function
 137    :        // again, this time we expect the function to succeed.
 138  E :        aligned_test_array[sizes_to_test[i] - sizeof(uint16)] = 0;
 139    :        EXPECT_TRUE(Shadow::GetNullTerminatedArraySize<uint16>(
 140  E :            aligned_test_array, 0U, &size));
 141  E :        EXPECT_EQ(sizes_to_test[i], size);
 142  E :        aligned_test_array[sizes_to_test[i] - sizeof(uint16)] = kMarkerValue;
 143    :      }
 144  E :      aligned_test_array[sizes_to_test[i] - 1] = kMarkerValue;
 145    :  
 146  E :      aligned_test_array[sizes_to_test[i]] = kMarkerValue;
 147    :      EXPECT_FALSE(Shadow::GetNullTerminatedArraySize<uint8>(aligned_test_array,
 148    :                                                             0U,
 149  E :                                                             &size));
 150  E :      EXPECT_EQ(sizes_to_test[i], size);
 151    :      EXPECT_TRUE(Shadow::GetNullTerminatedArraySize<uint8>(aligned_test_array,
 152    :                                                            sizes_to_test[i],
 153  E :                                                            &size));
 154    :  
 155    :      Shadow::Poison(aligned_test_array,
 156    :                     ::common::AlignUp(sizes_to_test[i], kShadowRatio),
 157  E :                     kAsanReservedMarker);
 158  E :    }
 159  E :    Shadow::Unpoison(aligned_test_array, aligned_array_length);
 160  E :  }
 161    :  
 162  E :  TEST(ShadowTest, MarkAsFreed) {
 163  E :    BlockLayout l0 = {}, l1 = {};
 164  E :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 16, 30, 30, &l1));
 165    :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio,
 166  E :                                l1.block_size + 2 * kShadowRatio, 30, 30, &l0));
 167    :  
 168  E :    uint8* data = new uint8[l0.block_size];
 169    :  
 170  E :    uint8* d0 = data;
 171  E :    BlockInfo i0 = {};
 172  E :    BlockInitialize(l0, d0, false, &i0);
 173  E :    Shadow::PoisonAllocatedBlock(i0);
 174    :  
 175  E :    uint8* d1 = i0.body + kShadowRatio;
 176  E :    BlockInfo i1 = {};
 177  E :    BlockInitialize(l1, d1, true, &i1);
 178  E :    Shadow::PoisonAllocatedBlock(i1);
 179    :  
 180  E :    Shadow::MarkAsFreed(i0.body, i0.body_size);
 181  E :    for (uint8* p = i0.block; p < i0.block + i0.block_size; ++p) {
 182  E :      if (p >= i0.block && p < i0.body) {
 183  E :        EXPECT_TRUE(Shadow::IsLeftRedzone(p));
 184  E :      } else if (p >= i0.body && p < i0.trailer_padding) {
 185  E :        if (p >= i1.block && p < i1.body) {
 186  E :          EXPECT_TRUE(Shadow::IsLeftRedzone(p));
 187  E :        } else if (p >= i1.body && p < i1.trailer_padding) {
 188    :          EXPECT_EQ(kHeapFreedMarker,
 189  E :                    Shadow::GetShadowMarkerForAddress(p));
 190  E :        } else if (p >= i1.trailer_padding && p < i1.block + i1.block_size) {
 191  E :          EXPECT_TRUE(Shadow::IsRightRedzone(p));
 192  E :        } else {
 193    :          EXPECT_EQ(kHeapFreedMarker,
 194  E :                    Shadow::GetShadowMarkerForAddress(p));
 195  E :        }
 196  E :      } else if (p >= i0.trailer_padding && p < i0.block + i0.block_size) {
 197  E :        EXPECT_TRUE(Shadow::IsRightRedzone(p));
 198    :      }
 199  E :    }
 200    :  
 201  E :    Shadow::Unpoison(data, l0.block_size);
 202  E :    delete [] data;
 203  E :  }
 204    :  
 205  E :  TEST(ShadowTest, PoisonAllocatedBlock) {
 206  E :    BlockLayout layout = {};
 207  E :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 15, 22, 0, &layout));
 208    :  
 209  E :    uint8* data = new uint8[layout.block_size];
 210  E :    BlockInfo info = {};
 211  E :    BlockInitialize(layout, data, false, &info);
 212    :  
 213  E :    Shadow::PoisonAllocatedBlock(info);
 214    :    EXPECT_EQ(Shadow::GetShadowMarkerForAddress(data + 0 * 8),
 215  E :              kHeapBlockStartMarker0 | 7);
 216    :    EXPECT_EQ(Shadow::GetShadowMarkerForAddress(data + 1 * 8),
 217  E :              kHeapLeftPaddingMarker);
 218    :    EXPECT_EQ(Shadow::GetShadowMarkerForAddress(data + 2 * 8),
 219  E :              kHeapLeftPaddingMarker);
 220    :    EXPECT_EQ(Shadow::GetShadowMarkerForAddress(data + 3 * 8),
 221  E :              0);
 222    :    EXPECT_EQ(Shadow::GetShadowMarkerForAddress(data + 4 * 8),
 223  E :              7);
 224    :    EXPECT_EQ(Shadow::GetShadowMarkerForAddress(data + 5 * 8),
 225  E :              kHeapRightPaddingMarker);
 226    :    EXPECT_EQ(Shadow::GetShadowMarkerForAddress(data + 6 * 8),
 227  E :              kHeapRightPaddingMarker);
 228    :    EXPECT_EQ(Shadow::GetShadowMarkerForAddress(data + 7 * 8),
 229  E :              kHeapBlockEndMarker);
 230    :  
 231  E :    uint8* cursor = info.block;
 232  E :    for (; cursor < info.body; ++cursor)
 233  E :      EXPECT_FALSE(Shadow::IsAccessible(cursor));
 234  E :    for (; cursor < info.body + info.body_size; ++cursor)
 235  E :      EXPECT_TRUE(Shadow::IsAccessible(cursor));
 236  E :    for (; cursor < info.block + info.block_size; ++cursor)
 237  E :      EXPECT_FALSE(Shadow::IsAccessible(cursor));
 238  E :    Shadow::Unpoison(info.block, info.block_size);
 239    :  
 240  E :    delete [] data;
 241  E :  }
 242    :  
 243  E :  TEST(ShadowTest, ScanLeftAndRight) {
 244  E :    size_t offset = Shadow::kShadowSize / 2;
 245  E :    size_t l = 0;
 246  E :    TestShadow::shadow_[offset + 0] = kHeapBlockStartMarker0;
 247  E :    TestShadow::shadow_[offset + 1] = kHeapNestedBlockStartMarker0;
 248  E :    TestShadow::shadow_[offset + 2] = kHeapAddressableMarker;
 249  E :    TestShadow::shadow_[offset + 3] = kHeapNestedBlockEndMarker;
 250  E :    TestShadow::shadow_[offset + 4] = kHeapBlockEndMarker;
 251    :  
 252  E :    EXPECT_TRUE(TestShadow::ScanLeftForBracketingBlockStart(0, offset + 0, &l));
 253  E :    EXPECT_EQ(offset, l);
 254  E :    EXPECT_TRUE(TestShadow::ScanLeftForBracketingBlockStart(0, offset + 1, &l));
 255  E :    EXPECT_EQ(offset + 1, l);
 256  E :    EXPECT_TRUE(TestShadow::ScanLeftForBracketingBlockStart(0, offset + 2, &l));
 257  E :    EXPECT_EQ(offset + 1, l);
 258  E :    EXPECT_TRUE(TestShadow::ScanLeftForBracketingBlockStart(0, offset + 3, &l));
 259  E :    EXPECT_EQ(offset + 1, l);
 260  E :    EXPECT_TRUE(TestShadow::ScanLeftForBracketingBlockStart(0, offset + 4, &l));
 261  E :    EXPECT_EQ(offset, l);
 262    :  
 263  E :    EXPECT_FALSE(TestShadow::ScanLeftForBracketingBlockStart(1, offset + 0, &l));
 264  E :    EXPECT_TRUE(TestShadow::ScanLeftForBracketingBlockStart(1, offset + 1, &l));
 265  E :    EXPECT_EQ(offset, l);
 266  E :    EXPECT_TRUE(TestShadow::ScanLeftForBracketingBlockStart(1, offset + 2, &l));
 267  E :    EXPECT_EQ(offset, l);
 268  E :    EXPECT_TRUE(TestShadow::ScanLeftForBracketingBlockStart(1, offset + 3, &l));
 269  E :    EXPECT_EQ(offset, l);
 270  E :    EXPECT_FALSE(TestShadow::ScanLeftForBracketingBlockStart(1, offset + 4, &l));
 271    :  
 272  E :    EXPECT_FALSE(TestShadow::ScanLeftForBracketingBlockStart(2, offset + 0, &l));
 273  E :    EXPECT_FALSE(TestShadow::ScanLeftForBracketingBlockStart(2, offset + 1, &l));
 274  E :    EXPECT_FALSE(TestShadow::ScanLeftForBracketingBlockStart(2, offset + 2, &l));
 275  E :    EXPECT_FALSE(TestShadow::ScanLeftForBracketingBlockStart(2, offset + 3, &l));
 276  E :    EXPECT_FALSE(TestShadow::ScanLeftForBracketingBlockStart(2, offset + 4, &l));
 277    :  
 278  E :    EXPECT_TRUE(TestShadow::ScanRightForBracketingBlockEnd(0, offset + 0, &l));
 279  E :    EXPECT_EQ(offset + 4, l);
 280  E :    EXPECT_TRUE(TestShadow::ScanRightForBracketingBlockEnd(0, offset + 1, &l));
 281  E :    EXPECT_EQ(offset + 3, l);
 282  E :    EXPECT_TRUE(TestShadow::ScanRightForBracketingBlockEnd(0, offset + 2, &l));
 283  E :    EXPECT_EQ(offset + 3, l);
 284  E :    EXPECT_TRUE(TestShadow::ScanRightForBracketingBlockEnd(0, offset + 3, &l));
 285  E :    EXPECT_EQ(offset + 3, l);
 286  E :    EXPECT_TRUE(TestShadow::ScanRightForBracketingBlockEnd(0, offset + 4, &l));
 287  E :    EXPECT_EQ(offset + 4, l);
 288    :  
 289  E :    EXPECT_FALSE(TestShadow::ScanRightForBracketingBlockEnd(1, offset + 0, &l));
 290  E :    EXPECT_TRUE(TestShadow::ScanRightForBracketingBlockEnd(1, offset + 1, &l));
 291  E :    EXPECT_EQ(offset + 4, l);
 292  E :    EXPECT_TRUE(TestShadow::ScanRightForBracketingBlockEnd(1, offset + 2, &l));
 293  E :    EXPECT_EQ(offset + 4, l);
 294  E :    EXPECT_TRUE(TestShadow::ScanRightForBracketingBlockEnd(1, offset + 3, &l));
 295  E :    EXPECT_EQ(offset + 4, l);
 296  E :    EXPECT_FALSE(TestShadow::ScanRightForBracketingBlockEnd(1, offset + 4, &l));
 297    :  
 298  E :    EXPECT_FALSE(TestShadow::ScanRightForBracketingBlockEnd(2, offset + 0, &l));
 299  E :    EXPECT_FALSE(TestShadow::ScanRightForBracketingBlockEnd(2, offset + 1, &l));
 300  E :    EXPECT_FALSE(TestShadow::ScanRightForBracketingBlockEnd(2, offset + 2, &l));
 301  E :    EXPECT_FALSE(TestShadow::ScanRightForBracketingBlockEnd(2, offset + 3, &l));
 302  E :    EXPECT_FALSE(TestShadow::ScanRightForBracketingBlockEnd(2, offset + 4, &l));
 303    :  
 304  E :    ::memset(TestShadow::shadow_ + offset, 0, 5);
 305  E :  }
 306    :  
 307  E :  TEST(ShadowTest, ScanRightPerfTest) {
 308  E :    size_t offset = Shadow::kShadowSize / 2;
 309  E :    size_t length = 1 * 1024 * 1024;
 310    :  
 311  E :    ::memset(TestShadow::shadow_ + offset, 0, length);
 312    :  
 313  E :    TestShadow::shadow_[offset + 0] = kHeapBlockStartMarker0;
 314    :    // A nested block with freed contents.
 315  E :    TestShadow::shadow_[offset + 50] = kHeapNestedBlockStartMarker0;
 316  E :    ::memset(TestShadow::shadow_ + offset + 51, kHeapFreedMarker, 8);
 317  E :    TestShadow::shadow_[offset + 60] = kHeapNestedBlockEndMarker;
 318    :    // A nested block with a nested block.
 319  E :    TestShadow::shadow_[offset + 100000] = kHeapNestedBlockStartMarker0;
 320  E :    TestShadow::shadow_[offset + 100100] = kHeapNestedBlockStartMarker0;
 321  E :    TestShadow::shadow_[offset + 100400] = kHeapNestedBlockEndMarker;
 322  E :    TestShadow::shadow_[offset + 200000] = kHeapNestedBlockEndMarker;
 323    :    // The end of the outer block.
 324  E :    TestShadow::shadow_[offset + length - 1] = kHeapBlockEndMarker;
 325    :  
 326  E :    uint64 tnet = 0;
 327  E :    for (size_t i = 0; i < 100; ++i) {
 328  E :      size_t l = 0;
 329  E :      uint64 t0 = ::__rdtsc();
 330  E :      TestShadow::ScanRightForBracketingBlockEnd(0, offset + 1, &l);
 331  E :      uint64 t1 = ::__rdtsc();
 332  E :      tnet += t1 - t0;
 333  E :    }
 334    :    testing::EmitMetric("Syzygy.Asan.Shadow.ScanRightForBracketingBlockEnd",
 335  E :                        tnet);
 336    :  
 337    :    // Reset the shadow memory.
 338  E :    ::memset(TestShadow::shadow_ + offset, 0, length);
 339  E :  }
 340    :  
 341  E :  TEST(ShadowTest, IsLeftOrRightRedzone) {
 342  E :    BlockLayout layout = {};
 343  E :    const size_t kAllocSize = 15;
 344  E :    ASSERT_NE(0U, kAllocSize % kShadowRatio);
 345    :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, kAllocSize, 0, 0,
 346  E :                                &layout));
 347    :  
 348  E :    scoped_ptr<uint8> data(new uint8[layout.block_size]);
 349  E :    BlockInfo info = {};
 350  E :    BlockInitialize(layout, data.get(), false, &info);
 351    :  
 352  E :    Shadow::PoisonAllocatedBlock(info);
 353  E :    uint8* cursor = info.block;
 354    :  
 355  E :    for (; cursor < info.body; ++cursor) {
 356  E :      EXPECT_TRUE(Shadow::IsLeftRedzone(cursor));
 357  E :      EXPECT_FALSE(Shadow::IsRightRedzone(cursor));
 358  E :    }
 359  E :    for (; cursor < info.body + info.body_size; ++cursor) {
 360  E :      EXPECT_FALSE(Shadow::IsLeftRedzone(cursor));
 361  E :      EXPECT_FALSE(Shadow::IsRightRedzone(cursor));
 362  E :    }
 363  E :    for (; cursor < info.block + info.block_size; ++cursor) {
 364  E :      EXPECT_FALSE(Shadow::IsLeftRedzone(cursor));
 365  E :      EXPECT_TRUE(Shadow::IsRightRedzone(cursor));
 366  E :    }
 367    :  
 368  E :    Shadow::Unpoison(info.block, info.block_size);
 369  E :  }
 370    :  
 371    :  namespace {
 372    :  
 373    :  void TestBlockInfoFromShadow(const BlockLayout& outer,
 374  E :                               const BlockLayout& nested) {
 375  E :    ASSERT_LE(nested.block_size, outer.body_size);
 376    :  
 377  E :    uint8* data = new uint8[outer.block_size];
 378    :  
 379    :    // Try recovering the block from every position within it when no nested
 380    :    // block exists. Expect finding a nested block to fail.
 381  E :    BlockInfo info = {};
 382  E :    BlockInitialize(outer, data, false, &info);
 383  E :    Shadow::PoisonAllocatedBlock(info);
 384  E :    BlockInfo info_recovered = {};
 385  E :    for (size_t i = 0; i < info.block_size; ++i) {
 386  E :      EXPECT_TRUE(Shadow::BlockInfoFromShadow(info.block + i, &info_recovered));
 387  E :      EXPECT_EQ(0, ::memcmp(&info, &info_recovered, sizeof(info)));
 388    :  
 389    :      // This block should have no parent block as its not nested.
 390    :      EXPECT_FALSE(Shadow::ParentBlockInfoFromShadow(
 391  E :          info, &info_recovered));
 392  E :    }
 393    :  
 394    :    // Place a nested block and try the recovery from every position again.
 395    :    size_t padding = ::common::AlignDown(info.body_size - nested.block_size,
 396  E :                                         kShadowRatio * 2);
 397  E :    uint8* nested_begin = info.body + padding / 2;
 398  E :    uint8* nested_end = nested_begin + nested.block_size;
 399  E :    BlockInfo nested_info = {};
 400  E :    BlockInitialize(nested, nested_begin, true, &nested_info);
 401  E :    nested_info.header->is_nested = true;
 402  E :    Shadow::PoisonAllocatedBlock(nested_info);
 403  E :    for (size_t i = 0; i < info.block_size; ++i) {
 404  E :      uint8* pos = info.block + i;
 405  E :      EXPECT_TRUE(Shadow::BlockInfoFromShadow(pos, &info_recovered));
 406    :  
 407  E :      BlockInfo parent_info = {};
 408    :      bool found_parent = Shadow::ParentBlockInfoFromShadow(
 409  E :          info_recovered, &parent_info);
 410    :  
 411  E :      if (pos >= nested_begin && pos < nested_end) {
 412    :        EXPECT_EQ(0, ::memcmp(&nested_info, &info_recovered,
 413  E :                              sizeof(nested_info)));
 414  E :        EXPECT_TRUE(found_parent);
 415  E :        EXPECT_EQ(0, ::memcmp(&info, &parent_info, sizeof(info)));
 416  E :      } else {
 417  E :        EXPECT_EQ(0, ::memcmp(&info, &info_recovered, sizeof(info)));
 418  E :        EXPECT_FALSE(found_parent);
 419    :      }
 420  E :    }
 421  E :    Shadow::Unpoison(info.block, info.block_size);
 422    :  
 423  E :    delete [] data;
 424  E :  }
 425    :  
 426    :  }  // namespace
 427    :  
 428  E :  TEST(ShadowTest, BlockInfoFromShadow) {
 429    :    // This is a simple layout that will be nested inside of another block.
 430  E :    BlockLayout layout0 = {};
 431  E :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 6, 0, 0, &layout0));
 432    :  
 433    :    // Plan two layouts, one with padding and another with none. The first has
 434    :    // exactly enough space for the nested block, while the second has room to
 435    :    // spare.
 436  E :    BlockLayout layout1 = {};
 437  E :    BlockLayout layout2 = {};
 438    :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio,
 439    :        ::common::AlignUp(layout0.block_size, kShadowRatio) + 4, 0, 0,
 440  E :        &layout1));
 441  E :    ASSERT_EQ(0u, layout1.header_padding_size);
 442  E :    ASSERT_EQ(0u, layout1.trailer_padding_size);
 443    :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio,
 444  E :        layout0.block_size + 2 * kShadowRatio, 32, 13, &layout2));
 445  E :    ASSERT_LT(0u, layout2.header_padding_size);
 446  E :    ASSERT_LT(0u, layout2.trailer_padding_size);
 447    :  
 448  E :    EXPECT_NO_FATAL_FAILURE(TestBlockInfoFromShadow(layout1, layout0));
 449  E :    EXPECT_NO_FATAL_FAILURE(TestBlockInfoFromShadow(layout2, layout0));
 450  E :  }
 451    :  
 452  E :  TEST(ShadowTest, IsBeginningOfBlockBody) {
 453  E :    BlockLayout l = {};
 454  E :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 7, 0, 0, &l));
 455    :  
 456  E :    size_t data_size = l.block_size;
 457  E :    scoped_ptr<uint8> data(new uint8[data_size]);
 458    :  
 459  E :    BlockInfo block_info = {};
 460  E :    BlockInitialize(l, data.get(), false, &block_info);
 461    :  
 462  E :    Shadow::PoisonAllocatedBlock(block_info);
 463    :  
 464  E :    EXPECT_TRUE(Shadow::IsBeginningOfBlockBody(block_info.body));
 465  E :    EXPECT_FALSE(Shadow::IsBeginningOfBlockBody(data.get()));
 466    :  
 467  E :    block_info.header->state = QUARANTINED_BLOCK;
 468  E :    Shadow::MarkAsFreed(block_info.body, block_info.body_size);
 469    :  
 470  E :    EXPECT_TRUE(Shadow::IsBeginningOfBlockBody(block_info.body));
 471  E :    EXPECT_FALSE(Shadow::IsBeginningOfBlockBody(data.get()));
 472    :  
 473  E :    Shadow::Unpoison(data.get(), data_size);
 474  E :  }
 475    :  
 476  E :  TEST(ShadowTest, IsBeginningOfBlockBodyForBlockOfSizeZero) {
 477  E :    BlockLayout l = {};
 478  E :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 0, 0, 0, &l));
 479    :  
 480  E :    size_t data_size = l.block_size;
 481  E :    scoped_ptr<uint8> data(new uint8[data_size]);
 482    :  
 483  E :    BlockInfo block_info = {};
 484  E :    BlockInitialize(l, data.get(), false, &block_info);
 485    :  
 486  E :    Shadow::PoisonAllocatedBlock(block_info);
 487    :  
 488  E :    EXPECT_TRUE(Shadow::IsBeginningOfBlockBody(block_info.body));
 489  E :    EXPECT_FALSE(Shadow::IsBeginningOfBlockBody(data.get()));
 490    :  
 491  E :    block_info.header->state = QUARANTINED_BLOCK;
 492  E :    Shadow::MarkAsFreed(block_info.body, block_info.body_size);
 493    :  
 494  E :    EXPECT_TRUE(Shadow::IsBeginningOfBlockBody(block_info.body));
 495  E :    EXPECT_FALSE(Shadow::IsBeginningOfBlockBody(data.get()));
 496    :  
 497  E :    Shadow::Unpoison(data.get(), data_size);
 498  E :  }
 499    :  
 500  E :  TEST(ShadowTest, MarkAsFreedPerfTest) {
 501  E :    std::vector<uint8> buf;
 502  E :    buf.resize(10 * 1024 * 1024, 0);
 503    :  
 504  E :    uint64 tnet = 0;
 505  E :    for (size_t i = 0; i < 1000; ++i) {
 506  E :      Shadow::Unpoison(buf.data(), buf.size());
 507  E :      uint64 t0 = ::__rdtsc();
 508  E :      Shadow::MarkAsFreed(buf.data(), buf.size());
 509  E :      uint64 t1 = ::__rdtsc();
 510  E :      tnet += t1 - t0;
 511  E :      Shadow::Unpoison(buf.data(), buf.size());
 512  E :    }
 513  E :    testing::EmitMetric("Syzygy.Asan.Shadow.MarkAsFreed", tnet);
 514  E :  }
 515    :  
 516  E :  TEST(ShadowTest, PageBits) {
 517    :    // Set an individual page.
 518  E :    const uint8* addr = reinterpret_cast<const uint8*>(16 * 4096);
 519  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr));
 520  E :    Shadow::MarkPageProtected(addr);
 521  E :    EXPECT_TRUE(Shadow::PageIsProtected(addr));
 522  E :    Shadow::MarkPageProtected(addr);
 523  E :    EXPECT_TRUE(Shadow::PageIsProtected(addr));
 524  E :    Shadow::MarkPageUnprotected(addr);
 525  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr));
 526  E :    Shadow::MarkPageUnprotected(addr);
 527  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr));
 528    :  
 529    :    // Set a range of pages at once.
 530  E :    const uint8* addr2 = addr + 4096;
 531  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr - 4096));
 532  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr));
 533  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr2));
 534  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr2 + 4096));
 535  E :    Shadow::MarkPagesProtected(addr, 2 * 4096);
 536  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr - 4096));
 537  E :    EXPECT_TRUE(Shadow::PageIsProtected(addr));
 538  E :    EXPECT_TRUE(Shadow::PageIsProtected(addr2));
 539  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr2 + 4096));
 540  E :    Shadow::MarkPagesProtected(addr, 2 * 4096);
 541  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr - 4096));
 542  E :    EXPECT_TRUE(Shadow::PageIsProtected(addr));
 543  E :    EXPECT_TRUE(Shadow::PageIsProtected(addr2));
 544  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr2 + 4096));
 545  E :    Shadow::MarkPagesUnprotected(addr, 2 * 4096);
 546  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr - 4096));
 547  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr));
 548  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr2));
 549  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr2 + 4096));
 550  E :    Shadow::MarkPagesUnprotected(addr, 2 * 4096);
 551  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr - 4096));
 552  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr));
 553  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr2));
 554  E :    EXPECT_FALSE(Shadow::PageIsProtected(addr2 + 4096));
 555  E :  }
 556    :  
 557  E :  TEST(ShadowWalkerTest, WalksNonNestedBlocks) {
 558  E :    BlockLayout l = {};
 559  E :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 7, 0, 0, &l));
 560    :  
 561  E :    size_t data_size = l.block_size * 3 + kShadowRatio;
 562  E :    uint8* data = new uint8[data_size];
 563  E :    uint8* data0 = data;
 564  E :    uint8* data1 = data0 + l.block_size + kShadowRatio;
 565  E :    uint8* data2 = data1 + l.block_size;
 566    :  
 567  E :    BlockInfo i0 = {}, i1 = {}, i2 = {};
 568  E :    BlockInitialize(l, data0, false, &i0);
 569  E :    BlockInitialize(l, data1, false, &i1);
 570  E :    BlockInitialize(l, data2, false, &i2);
 571    :  
 572  E :    Shadow::PoisonAllocatedBlock(i0);
 573  E :    Shadow::PoisonAllocatedBlock(i1);
 574  E :    Shadow::PoisonAllocatedBlock(i2);
 575    :  
 576  E :    i2.header->state = QUARANTINED_BLOCK;
 577  E :    Shadow::MarkAsFreed(i2.body, i2.body_size);
 578    :  
 579    :    // Do a non-recursive walk through the shadow.
 580  E :    BlockInfo i = {};
 581  E :    ShadowWalker w0(false, data, data + data_size);
 582  E :    EXPECT_EQ(-1, w0.nesting_depth());
 583  E :    EXPECT_TRUE(w0.Next(&i));
 584  E :    EXPECT_EQ(0, w0.nesting_depth());
 585  E :    EXPECT_TRUE(w0.Next(&i));
 586  E :    EXPECT_EQ(0, w0.nesting_depth());
 587  E :    EXPECT_TRUE(w0.Next(&i));
 588  E :    EXPECT_EQ(0, w0.nesting_depth());
 589  E :    EXPECT_FALSE(w0.Next(&i));
 590  E :    EXPECT_EQ(-1, w0.nesting_depth());
 591    :  
 592    :    // Walk recursively through the shadow and expect the same results.
 593  E :    ShadowWalker w1(true, data, data + data_size);
 594  E :    EXPECT_EQ(-1, w1.nesting_depth());
 595  E :    EXPECT_TRUE(w1.Next(&i));
 596  E :    EXPECT_EQ(0, w1.nesting_depth());
 597  E :    EXPECT_EQ(0, ::memcmp(&i, &i0, sizeof(i)));
 598  E :    EXPECT_TRUE(w1.Next(&i));
 599  E :    EXPECT_EQ(0, w1.nesting_depth());
 600  E :    EXPECT_EQ(0, ::memcmp(&i, &i1, sizeof(i)));
 601  E :    EXPECT_TRUE(w1.Next(&i));
 602  E :    EXPECT_EQ(0, w1.nesting_depth());
 603  E :    EXPECT_EQ(0, ::memcmp(&i, &i2, sizeof(i)));
 604  E :    EXPECT_FALSE(w1.Next(&i));
 605  E :    EXPECT_EQ(-1, w1.nesting_depth());
 606    :  
 607  E :    Shadow::Unpoison(data, data_size);
 608  E :    delete [] data;
 609  E :  }
 610    :  
 611  E :  TEST(ShadowWalkerTest, WalksNestedBlocks) {
 612  E :    BlockLayout b0 = {}, b1 = {}, b2 = {}, b00 = {}, b01 = {}, b10 = {},
 613  E :        b100 = {};
 614  E :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 15, 30, 30, &b00));
 615  E :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 7, 0, 0, &b01));
 616    :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio,
 617  E :        b00.block_size + b01.block_size + kShadowRatio, 0, 0, &b0));
 618  E :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 7, 0, 0, &b100));
 619    :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, b100.block_size, 0, 0,
 620  E :                                &b10));
 621    :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, b10.block_size, 0, 0,
 622  E :                                &b1));
 623  E :    EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 100, 0, 0, &b2));
 624    :  
 625    :    size_t data_size = b0.block_size + b1.block_size + kShadowRatio +
 626  E :        b2.block_size;
 627  E :    uint8* data = new uint8[data_size];
 628    :  
 629    :    // Initialize the depth 0 blocks.
 630  E :    uint8* d0 = data;
 631  E :    uint8* d1 = d0 + b0.block_size;
 632  E :    uint8* d2 = d1 + b1.block_size + kShadowRatio;
 633  E :    BlockInfo i0 = {}, i1 = {}, i2 = {};
 634  E :    BlockInitialize(b0, d0, false, &i0);
 635  E :    BlockInitialize(b1, d1, false, &i1);
 636  E :    BlockInitialize(b2, d2, false, &i2);
 637  E :    Shadow::PoisonAllocatedBlock(i0);
 638  E :    Shadow::PoisonAllocatedBlock(i1);
 639  E :    Shadow::PoisonAllocatedBlock(i2);
 640    :  
 641    :    // Initialize depth 1 blocks.
 642  E :    uint8* d00 = i0.body;
 643  E :    uint8* d01 = d00 + b00.block_size + kShadowRatio;
 644  E :    uint8* d10 = i1.body;
 645  E :    BlockInfo i00 = {}, i01 = {}, i10 = {};
 646  E :    BlockInitialize(b00, d00, true, &i00);
 647  E :    BlockInitialize(b01, d01, true, &i01);
 648  E :    BlockInitialize(b10, d10, true, &i10);
 649  E :    Shadow::PoisonAllocatedBlock(i00);
 650  E :    Shadow::PoisonAllocatedBlock(i01);
 651  E :    Shadow::PoisonAllocatedBlock(i10);
 652    :  
 653    :    // Initialize depth 2 blocks.
 654  E :    uint8* d100 = i10.body;
 655  E :    BlockInfo i100 = {};
 656  E :    BlockInitialize(b100, d100, true, &i100);
 657  E :    Shadow::PoisonAllocatedBlock(i100);
 658  E :    i100.header->state = QUARANTINED_BLOCK;
 659  E :    Shadow::MarkAsFreed(i100.body, i100.body_size);
 660    :  
 661    :    // Do a non-recursive walk through the shadow.
 662  E :    BlockInfo i = {};
 663  E :    ShadowWalker w0(false, data, data + data_size);
 664  E :    EXPECT_EQ(-1, w0.nesting_depth());
 665  E :    EXPECT_TRUE(w0.Next(&i));
 666  E :    EXPECT_EQ(0, w0.nesting_depth());
 667  E :    EXPECT_EQ(0, ::memcmp(&i, &i0, sizeof(i)));
 668  E :    EXPECT_TRUE(w0.Next(&i));
 669  E :    EXPECT_EQ(0, w0.nesting_depth());
 670  E :    EXPECT_EQ(0, ::memcmp(&i, &i1, sizeof(i)));
 671  E :    EXPECT_TRUE(w0.Next(&i));
 672  E :    EXPECT_EQ(0, w0.nesting_depth());
 673  E :    EXPECT_EQ(0, ::memcmp(&i, &i2, sizeof(i)));
 674  E :    EXPECT_FALSE(w0.Next(&i));
 675  E :    EXPECT_EQ(-1, w0.nesting_depth());
 676    :  
 677    :    // Walk recursively through the shadow.
 678  E :    ShadowWalker w1(true, data, data + data_size);
 679  E :    EXPECT_EQ(-1, w1.nesting_depth());
 680  E :    EXPECT_TRUE(w1.Next(&i));
 681  E :    EXPECT_EQ(0, w1.nesting_depth());
 682  E :    EXPECT_EQ(0, ::memcmp(&i, &i0, sizeof(i)));
 683  E :    EXPECT_TRUE(w1.Next(&i));
 684  E :    EXPECT_EQ(1, w1.nesting_depth());
 685  E :    EXPECT_EQ(0, ::memcmp(&i, &i00, sizeof(i)));
 686  E :    EXPECT_TRUE(w1.Next(&i));
 687  E :    EXPECT_EQ(1, w1.nesting_depth());
 688  E :    EXPECT_EQ(0, ::memcmp(&i, &i01, sizeof(i)));
 689  E :    EXPECT_TRUE(w1.Next(&i));
 690  E :    EXPECT_EQ(0, w1.nesting_depth());
 691  E :    EXPECT_EQ(0, ::memcmp(&i, &i1, sizeof(i)));
 692  E :    EXPECT_TRUE(w1.Next(&i));
 693  E :    EXPECT_EQ(1, w1.nesting_depth());
 694  E :    EXPECT_EQ(0, ::memcmp(&i, &i10, sizeof(i)));
 695  E :    EXPECT_TRUE(w1.Next(&i));
 696  E :    EXPECT_EQ(2, w1.nesting_depth());
 697  E :    EXPECT_EQ(0, ::memcmp(&i, &i100, sizeof(i)));
 698  E :    EXPECT_TRUE(w1.Next(&i));
 699  E :    EXPECT_EQ(0, w1.nesting_depth());
 700  E :    EXPECT_EQ(0, ::memcmp(&i, &i2, sizeof(i)));
 701  E :    EXPECT_FALSE(w1.Next(&i));
 702  E :    EXPECT_EQ(-1, w1.nesting_depth());
 703    :  
 704  E :    Shadow::Unpoison(data, data_size);
 705  E :    delete [] data;
 706  E :  }
 707    :  
 708    :  }  // namespace asan
 709    :  }  // namespace agent

Coverage information generated Thu Mar 26 16:15:41 2015.