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/asan_heap.h"
16 :
17 : #include "base/rand_util.h"
18 : #include "base/sha1.h"
19 : #include "gtest/gtest.h"
20 : #include "syzygy/agent/asan/asan_logger.h"
21 : #include "syzygy/agent/asan/asan_shadow.h"
22 : #include "syzygy/agent/asan/unittest_util.h"
23 : #include "syzygy/trace/common/clock.h"
24 :
25 : namespace agent {
26 : namespace asan {
27 :
28 : namespace {
29 :
30 : // A derived class to expose protected members for unit-testing.
31 : class TestShadow : public Shadow {
32 : public:
33 : using Shadow::kShadowSize;
34 : using Shadow::shadow_;
35 : };
36 :
37 : // A derived class to expose protected members for unit-testing.
38 : class TestHeapProxy : public HeapProxy {
39 : public:
40 : using HeapProxy::BlockHeader;
41 : using HeapProxy::BlockTrailer;
42 : using HeapProxy::FindAddressBlock;
43 : using HeapProxy::GetAllocSize;
44 : using HeapProxy::GetBadAccessKind;
45 : using HeapProxy::GetTimeSinceFree;
46 : using HeapProxy::ToBlockHeader;
47 : using HeapProxy::GetBlockTrailer;
48 :
49 E : explicit TestHeapProxy(StackCaptureCache* stack_cache, AsanLogger* logger)
50 : : HeapProxy(stack_cache, logger) {
51 E : }
52 :
53 : // Verify that the access to @p addr contained in @p header is an underflow.
54 E : bool IsUnderflowAccess(uint8* addr, BlockHeader* header) {
55 E : return GetBadAccessKind(addr, header) == HEAP_BUFFER_UNDERFLOW;
56 E : }
57 :
58 : // Verify that the access to @p addr contained in @p header is an overflow.
59 E : bool IsOverflowAccess(uint8* addr, BlockHeader* header) {
60 E : return GetBadAccessKind(addr, header) == HEAP_BUFFER_OVERFLOW;
61 E : }
62 :
63 : // Verify that the access to @p addr contained in @p header is an use after
64 : // free.
65 E : bool IsUseAfterAccess(uint8* addr, BlockHeader* header) {
66 E : return GetBadAccessKind(addr, header) == USE_AFTER_FREE;
67 E : }
68 :
69 E : bool IsQuarantined(BlockHeader* header) {
70 E : EXPECT_TRUE(header != NULL);
71 E : return header->state == QUARANTINED;
72 E : }
73 :
74 : // Determines if the address @p mem corresponds to a block in quarantine.
75 E : bool InQuarantine(const void* mem) {
76 E : base::AutoLock lock(lock_);
77 E : BlockHeader* current_block = head_;
78 E : while (current_block != NULL) {
79 E : void* block_alloc = static_cast<void*>(ToAlloc(current_block));
80 E : EXPECT_TRUE(block_alloc != NULL);
81 E : if (block_alloc == mem) {
82 E : EXPECT_TRUE(current_block->state == QUARANTINED);
83 E : return true;
84 : }
85 E : current_block = GetBlockTrailer(current_block)->next_free_block;
86 E : }
87 E : return false;
88 E : }
89 : };
90 :
91 : class HeapTest : public testing::TestWithAsanLogger {
92 : public:
93 E : HeapTest() : stack_cache_(&logger_), proxy_(&stack_cache_, &logger_) {
94 E : }
95 :
96 E : virtual void SetUp() OVERRIDE {
97 E : testing::TestWithAsanLogger::SetUp();
98 :
99 E : HeapProxy::Init();
100 E : Shadow::SetUp();
101 :
102 E : logger_.set_instance_id(instance_id());
103 E : logger_.Init();
104 E : ASSERT_TRUE(proxy_.Create(0, 0, 0));
105 E : }
106 :
107 E : virtual void TearDown() OVERRIDE {
108 E : ASSERT_TRUE(proxy_.Destroy());
109 E : Shadow::TearDown();
110 E : testing::TestWithAsanLogger::TearDown();
111 E : }
112 :
113 : // Verifies that [alloc, alloc + size) is accessible, and that
114 : // [alloc - 1] and [alloc+size] are poisoned.
115 E : void VerifyAllocAccess(void* alloc, size_t size) {
116 E : uint8* mem = reinterpret_cast<uint8*>(alloc);
117 E : ASSERT_FALSE(Shadow::IsAccessible(mem - 1));
118 E : ASSERT_EQ(Shadow::GetShadowMarkerForAddress(mem - 1),
119 : Shadow::kHeapLeftRedzone);
120 E : for (size_t i = 0; i < size; ++i)
121 E : ASSERT_TRUE(Shadow::IsAccessible(mem + i));
122 E : ASSERT_FALSE(Shadow::IsAccessible(mem + size));
123 E : }
124 :
125 : // Verifies that [alloc-1, alloc+size] is poisoned.
126 E : void VerifyFreedAccess(void* alloc, size_t size) {
127 E : uint8* mem = reinterpret_cast<uint8*>(alloc);
128 E : ASSERT_FALSE(Shadow::IsAccessible(mem - 1));
129 E : ASSERT_EQ(Shadow::GetShadowMarkerForAddress(mem - 1),
130 : Shadow::kHeapLeftRedzone);
131 E : for (size_t i = 0; i < size; ++i) {
132 E : ASSERT_FALSE(Shadow::IsAccessible(mem + i));
133 E : ASSERT_EQ(Shadow::GetShadowMarkerForAddress(mem + i),
134 : Shadow::kHeapFreedByte);
135 E : }
136 E : ASSERT_FALSE(Shadow::IsAccessible(mem + size));
137 E : }
138 :
139 E : void RandomSetMemory(void* alloc, size_t size) {
140 E : base::RandBytes(alloc, size);
141 E : }
142 :
143 : protected:
144 : // Arbitrary constant for all size limit.
145 : static const size_t kMaxAllocSize = 134584;
146 :
147 : AsanLogger logger_;
148 : StackCaptureCache stack_cache_;
149 : TestHeapProxy proxy_;
150 : };
151 :
152 : } // namespace
153 :
154 E : TEST_F(HeapTest, ToFromHandle) {
155 E : HANDLE handle = HeapProxy::ToHandle(&proxy_);
156 E : ASSERT_TRUE(handle != NULL);
157 E : ASSERT_EQ(&proxy_, HeapProxy::FromHandle(handle));
158 E : }
159 :
160 E : TEST_F(HeapTest, SetQuarantineMaxSize) {
161 E : size_t quarantine_size = proxy_.quarantine_max_size() * 2;
162 : // Increments the quarantine max size if it was set to 0.
163 E : if (quarantine_size == 0)
164 i : quarantine_size++;
165 E : DCHECK_GT(quarantine_size, 0U);
166 E : proxy_.SetQuarantineMaxSize(quarantine_size);
167 E : ASSERT_EQ(quarantine_size, proxy_.quarantine_max_size());
168 E : }
169 :
170 E : TEST_F(HeapTest, PopOnSetQuarantineMaxSize) {
171 E : const size_t kAllocSize = 100;
172 E : const size_t real_alloc_size = TestHeapProxy::GetAllocSize(kAllocSize);
173 E : LPVOID mem = proxy_.Alloc(0, kAllocSize);
174 E : ASSERT_FALSE(proxy_.InQuarantine(mem));
175 E : proxy_.SetQuarantineMaxSize(real_alloc_size);
176 E : ASSERT_TRUE(proxy_.Free(0, mem));
177 : // The quarantine is just large enough to keep this block.
178 E : ASSERT_TRUE(proxy_.InQuarantine(mem));
179 : // We resize the quarantine to a smaller size, the block should pop out.
180 E : proxy_.SetQuarantineMaxSize(real_alloc_size - 1);
181 E : ASSERT_FALSE(proxy_.InQuarantine(mem));
182 E : }
183 :
184 E : TEST_F(HeapTest, Quarantine) {
185 E : const size_t kAllocSize = 100;
186 E : const size_t real_alloc_size = TestHeapProxy::GetAllocSize(kAllocSize);
187 E : const size_t number_of_allocs = 16;
188 E : proxy_.SetQuarantineMaxSize(real_alloc_size * number_of_allocs);
189 :
190 E : LPVOID mem = proxy_.Alloc(0, kAllocSize);
191 E : ASSERT_TRUE(mem != NULL);
192 E : ASSERT_TRUE(proxy_.Free(0, mem));
193 : // Allocate a bunch of blocks until the first one is pushed out of the
194 : // quarantine.
195 E : for (size_t i = 0;i < number_of_allocs; ++i) {
196 E : ASSERT_TRUE(proxy_.InQuarantine(mem));
197 E : LPVOID mem2 = proxy_.Alloc(0, kAllocSize);
198 E : ASSERT_TRUE(mem2 != NULL);
199 E : ASSERT_TRUE(proxy_.Free(0, mem2));
200 E : ASSERT_TRUE(proxy_.InQuarantine(mem2));
201 E : }
202 :
203 E : ASSERT_FALSE(proxy_.InQuarantine(mem));
204 E : }
205 :
206 E : TEST_F(HeapTest, UnpoisonsQuarantine) {
207 E : const size_t kAllocSize = 100;
208 E : const size_t real_alloc_size = TestHeapProxy::GetAllocSize(kAllocSize);
209 E : proxy_.SetQuarantineMaxSize(real_alloc_size);
210 :
211 : // Allocate a memory block and directly free it, this puts it in the
212 : // quarantine.
213 E : void* mem = proxy_.Alloc(0, kAllocSize);
214 E : ASSERT_TRUE(mem != NULL);
215 E : ASSERT_TRUE(proxy_.Free(0, mem));
216 E : ASSERT_TRUE(proxy_.InQuarantine(mem));
217 :
218 : // Assert that the shadow memory has been correctly poisoned.
219 E : intptr_t mem_start = reinterpret_cast<intptr_t>(proxy_.ToBlockHeader(mem));
220 E : ASSERT_TRUE((mem_start & 7) == 0);
221 E : size_t shadow_start = mem_start >> 3;
222 E : size_t shadow_alloc_size = real_alloc_size >> 3;
223 E : for (size_t i = shadow_start; i < shadow_start + shadow_alloc_size; ++i) {
224 E : ASSERT_NE(TestShadow::kHeapAddressableByte, TestShadow::shadow_[i]);
225 E : }
226 :
227 : // Flush the quarantine.
228 E : proxy_.SetQuarantineMaxSize(0);
229 :
230 : // Assert that the quarantine has been correctly unpoisoned.
231 E : for (size_t i = shadow_start; i < shadow_start + shadow_alloc_size; ++i) {
232 E : ASSERT_EQ(TestShadow::kHeapAddressableByte, TestShadow::shadow_[i]);
233 E : }
234 E : }
235 :
236 E : TEST_F(HeapTest, Realloc) {
237 E : const size_t kAllocSize = 100;
238 : // As a special case, a realloc with a NULL input should succeed.
239 E : LPVOID mem = proxy_.ReAlloc(0, NULL, kAllocSize);
240 E : ASSERT_TRUE(mem != NULL);
241 E : mem = proxy_.ReAlloc(0, mem, kAllocSize + 5);
242 E : ASSERT_TRUE(mem != NULL);
243 :
244 : // We always fail reallocs with the in-place flag.
245 : ASSERT_EQ(NULL,
246 E : proxy_.ReAlloc(HEAP_REALLOC_IN_PLACE_ONLY, NULL, kAllocSize));
247 : ASSERT_EQ(NULL,
248 E : proxy_.ReAlloc(HEAP_REALLOC_IN_PLACE_ONLY, mem, kAllocSize - 10));
249 : ASSERT_EQ(NULL,
250 E : proxy_.ReAlloc(HEAP_REALLOC_IN_PLACE_ONLY, mem, kAllocSize + 10));
251 :
252 E : ASSERT_TRUE(proxy_.Free(0, mem));
253 E : }
254 :
255 E : TEST_F(HeapTest, AllocFree) {
256 E : const size_t kAllocSize = 100;
257 E : LPVOID mem = proxy_.Alloc(0, kAllocSize);
258 E : ASSERT_TRUE(mem != NULL);
259 E : ASSERT_EQ(kAllocSize, proxy_.Size(0, mem));
260 E : const size_t kReAllocSize = 2 * kAllocSize;
261 E : mem = proxy_.ReAlloc(0, mem, kReAllocSize);
262 E : ASSERT_EQ(kReAllocSize, proxy_.Size(0, mem));
263 E : ASSERT_TRUE(proxy_.Free(0, mem));
264 E : }
265 :
266 E : TEST_F(HeapTest, DoubleFree) {
267 E : const size_t kAllocSize = 100;
268 : // Ensure that the quarantine is large enough to keep this block, this is
269 : // needed for the use-after-free check.
270 E : proxy_.SetQuarantineMaxSize(TestHeapProxy::GetAllocSize(kAllocSize));
271 E : LPVOID mem = proxy_.Alloc(0, kAllocSize);
272 E : ASSERT_TRUE(mem != NULL);
273 E : ASSERT_TRUE(proxy_.Free(0, mem));
274 E : ASSERT_TRUE(proxy_.IsQuarantined(proxy_.ToBlockHeader(mem)));
275 E : ASSERT_FALSE(proxy_.Free(0, mem));
276 E : ASSERT_TRUE(LogContains(HeapProxy::kAttemptingDoubleFree));
277 E : }
278 :
279 E : TEST_F(HeapTest, AllocsAccessibility) {
280 : // Ensure that the quarantine is large enough to keep the allocated blocks in
281 : // this test.
282 E : proxy_.SetQuarantineMaxSize(kMaxAllocSize * 2);
283 E : for (size_t size = 10; size < kMaxAllocSize; size = size * 5 + 123) {
284 : // Do an alloc/realloc/free and test that access is correctly managed.
285 E : void* mem = proxy_.Alloc(0, size);
286 E : ASSERT_TRUE(mem != NULL);
287 E : ASSERT_NO_FATAL_FAILURE(VerifyAllocAccess(mem, size));
288 E : RandomSetMemory(mem, size);
289 :
290 E : size_t new_size = size;
291 E : while (new_size == size)
292 E : new_size = base::RandInt(size / 2, size * 2);
293 :
294 E : unsigned char sha1_before[base::kSHA1Length] = {};
295 : base::SHA1HashBytes(reinterpret_cast<unsigned char*>(mem),
296 : std::min(size, new_size),
297 E : sha1_before);
298 :
299 E : void* new_mem = proxy_.ReAlloc(0, mem, size * 2);
300 E : ASSERT_TRUE(new_mem != NULL);
301 E : ASSERT_NE(mem, new_mem);
302 :
303 E : unsigned char sha1_after[base::kSHA1Length] = {};
304 : base::SHA1HashBytes(reinterpret_cast<unsigned char*>(new_mem),
305 : std::min(size, new_size),
306 E : sha1_after);
307 E : ASSERT_EQ(0, memcmp(sha1_before, sha1_after, base::kSHA1Length));
308 :
309 E : ASSERT_NO_FATAL_FAILURE(VerifyFreedAccess(mem, size));
310 E : ASSERT_NO_FATAL_FAILURE(VerifyAllocAccess(new_mem, size * 2));
311 :
312 E : ASSERT_TRUE(proxy_.Free(0, new_mem));
313 E : ASSERT_NO_FATAL_FAILURE(VerifyFreedAccess(new_mem, size * 2));
314 E : }
315 E : }
316 :
317 E : TEST_F(HeapTest, AllocZeroBytes) {
318 E : void* mem1 = proxy_.Alloc(0, 0);
319 E : ASSERT_TRUE(mem1 != NULL);
320 E : void* mem2 = proxy_.Alloc(0, 0);
321 E : ASSERT_TRUE(mem2 != NULL);
322 E : ASSERT_NE(mem1, mem2);
323 E : ASSERT_TRUE(proxy_.Free(0, mem1));
324 E : ASSERT_TRUE(proxy_.Free(0, mem2));
325 E : }
326 :
327 E : TEST_F(HeapTest, Size) {
328 E : for (size_t size = 10; size < kMaxAllocSize; size = size * 5 + 123) {
329 E : void* mem = proxy_.Alloc(0, size);
330 E : ASSERT_FALSE(mem == NULL);
331 E : ASSERT_EQ(size, proxy_.Size(0, mem));
332 E : ASSERT_TRUE(proxy_.Free(0, mem));
333 E : }
334 E : }
335 :
336 E : TEST_F(HeapTest, Validate) {
337 E : for (size_t size = 10; size < kMaxAllocSize; size = size * 5 + 123) {
338 E : void* mem = proxy_.Alloc(0, size);
339 E : ASSERT_FALSE(mem == NULL);
340 E : ASSERT_TRUE(proxy_.Validate(0, mem));
341 E : ASSERT_TRUE(proxy_.Free(0, mem));
342 E : }
343 E : }
344 :
345 E : TEST_F(HeapTest, Compact) {
346 : // Compact should return a non-zero size.
347 E : ASSERT_LT(0U, proxy_.Compact(0));
348 :
349 : // TODO(siggi): It may not be possible to allocate the size returned due
350 : // to padding - fix and test.
351 E : }
352 :
353 E : TEST_F(HeapTest, LockUnlock) {
354 : // We can't really test these, aside from not crashing.
355 E : ASSERT_TRUE(proxy_.Lock());
356 E : ASSERT_TRUE(proxy_.Unlock());
357 E : }
358 :
359 E : TEST_F(HeapTest, Walk) {
360 : // We assume at least two entries to walk through.
361 E : PROCESS_HEAP_ENTRY entry = {};
362 E : ASSERT_TRUE(proxy_.Walk(&entry));
363 E : ASSERT_TRUE(proxy_.Walk(&entry));
364 E : }
365 :
366 E : TEST_F(HeapTest, SetQueryInformation) {
367 E : ULONG compat_flag = -1;
368 E : unsigned long ret = 0;
369 : // Get the current value of the compat flag.
370 : ASSERT_TRUE(
371 : proxy_.QueryInformation(HeapCompatibilityInformation,
372 E : &compat_flag, sizeof(compat_flag), &ret));
373 E : ASSERT_EQ(sizeof(compat_flag), ret);
374 E : ASSERT_TRUE(compat_flag != -1);
375 :
376 : // Put the heap in LFH, which should always succeed, except when a debugger
377 : // is attached. When a debugger is attached, the heap is wedged in certain
378 : // debug settings.
379 E : if (base::debug::BeingDebugged()) {
380 i : LOG(WARNING) << "Can't test HeapProxy::SetInformation under debugger.";
381 i : return;
382 : }
383 :
384 E : compat_flag = 2;
385 : ASSERT_TRUE(
386 : proxy_.SetInformation(HeapCompatibilityInformation,
387 E : &compat_flag, sizeof(compat_flag)));
388 E : }
389 :
390 E : TEST_F(HeapTest, FindAddressBlock) {
391 E : const size_t kAllocSize = 100;
392 E : void* mem = proxy_.Alloc(0, kAllocSize);
393 E : ASSERT_FALSE(mem == NULL);
394 E : ASSERT_FALSE(proxy_.FindAddressBlock(static_cast<const uint8*>(mem)) == NULL);
395 : uint8* out_of_bounds_address =
396 E : static_cast<uint8*>(mem) + kAllocSize * 2;
397 E : ASSERT_TRUE(proxy_.FindAddressBlock(out_of_bounds_address) == NULL);
398 E : ASSERT_TRUE(proxy_.Free(0, mem));
399 E : }
400 :
401 E : TEST_F(HeapTest, GetBadAccessKind) {
402 E : const size_t kAllocSize = 100;
403 : // Ensure that the quarantine is large enough to keep this block, this is
404 : // needed for the use-after-free check.
405 E : proxy_.SetQuarantineMaxSize(TestHeapProxy::GetAllocSize(kAllocSize));
406 E : uint8* mem = static_cast<uint8*>(proxy_.Alloc(0, kAllocSize));
407 E : ASSERT_FALSE(mem == NULL);
408 : TestHeapProxy::BlockHeader* header =
409 E : const_cast<TestHeapProxy::BlockHeader*>(proxy_.ToBlockHeader(mem));
410 E : uint8* heap_underflow_address = mem - 1;
411 E : uint8* heap_overflow_address = mem + kAllocSize * sizeof(uint8);
412 E : ASSERT_TRUE(proxy_.IsUnderflowAccess(heap_underflow_address, header));
413 E : ASSERT_TRUE(proxy_.IsOverflowAccess(heap_overflow_address, header));
414 E : ASSERT_TRUE(proxy_.Free(0, mem));
415 E : ASSERT_TRUE(proxy_.IsQuarantined(header));
416 E : ASSERT_TRUE(proxy_.IsUseAfterAccess(mem, header));
417 E : }
418 :
419 E : TEST_F(HeapTest, GetTimeSinceFree) {
420 E : const size_t kAllocSize = 100;
421 E : const size_t kSleepTime = 25;
422 :
423 : // Ensure that the quarantine is large enough to keep this block.
424 E : proxy_.SetQuarantineMaxSize(TestHeapProxy::GetAllocSize(kAllocSize));
425 E : uint8* mem = static_cast<uint8*>(proxy_.Alloc(0, kAllocSize));
426 : TestHeapProxy::BlockHeader* header =
427 E : const_cast<TestHeapProxy::BlockHeader*>(proxy_.ToBlockHeader(mem));
428 :
429 E : base::TimeTicks time_before_free = base::TimeTicks::HighResNow();
430 E : ASSERT_EQ(0U, proxy_.GetTimeSinceFree(header));
431 E : ASSERT_TRUE(proxy_.Free(0, mem));
432 E : ASSERT_TRUE(proxy_.IsQuarantined(header));
433 E : ::Sleep(kSleepTime);
434 E : uint64 time_since_free = proxy_.GetTimeSinceFree(header);
435 E : ASSERT_NE(0U, time_since_free);
436 :
437 E : base::TimeDelta time_delta = base::TimeTicks::HighResNow() - time_before_free;
438 E : ASSERT_GT(time_delta.ToInternalValue(), 0U);
439 E : uint64 time_delta_us = static_cast<uint64>(time_delta.ToInternalValue());
440 E : trace::common::ClockInfo clock_info = {};
441 E : trace::common::GetClockInfo(&clock_info);
442 E : if (clock_info.tsc_info.frequency == 0)
443 i : time_delta_us += HeapProxy::kSleepTimeForApproximatingCPUFrequency;
444 :
445 E : ASSERT_GE(time_delta_us, time_since_free);
446 E : }
447 :
448 E : TEST_F(HeapTest, CaptureTID) {
449 E : const size_t kAllocSize = 13;
450 : // Ensure that the quarantine is large enough to keep this block.
451 E : proxy_.SetQuarantineMaxSize(TestHeapProxy::GetAllocSize(kAllocSize));
452 E : uint8* mem = static_cast<uint8*>(proxy_.Alloc(0, kAllocSize));
453 E : ASSERT_TRUE(proxy_.Free(0, mem));
454 E : ASSERT_TRUE(proxy_.IsQuarantined(proxy_.ToBlockHeader(mem)));
455 :
456 : TestHeapProxy::BlockHeader* header =
457 E : const_cast<TestHeapProxy::BlockHeader*>(proxy_.ToBlockHeader(mem));
458 E : ASSERT_TRUE(header != NULL);
459 : TestHeapProxy::BlockTrailer* trailer =
460 E : const_cast<TestHeapProxy::BlockTrailer*>(proxy_.GetBlockTrailer(header));
461 E : ASSERT_TRUE(trailer != NULL);
462 :
463 E : ASSERT_EQ(header->alloc_tid, ::GetCurrentThreadId());
464 E : ASSERT_EQ(trailer->free_tid, ::GetCurrentThreadId());
465 E : }
466 :
467 E : TEST_F(HeapTest, QuarantineDoesntAlterBlockContents) {
468 E : const size_t kAllocSize = 13;
469 : // Ensure that the quarantine is large enough to keep this block..
470 E : proxy_.SetQuarantineMaxSize(TestHeapProxy::GetAllocSize(kAllocSize));
471 E : void* mem = proxy_.Alloc(0, kAllocSize);
472 E : ASSERT_TRUE(mem != NULL);
473 E : RandomSetMemory(mem, kAllocSize);
474 :
475 E : unsigned char sha1_before[base::kSHA1Length] = {};
476 : base::SHA1HashBytes(reinterpret_cast<unsigned char*>(mem),
477 : kAllocSize,
478 E : sha1_before);
479 :
480 : TestHeapProxy::BlockHeader* header =
481 E : const_cast<TestHeapProxy::BlockHeader*>(proxy_.ToBlockHeader(mem));
482 :
483 E : ASSERT_TRUE(proxy_.Free(0, mem));
484 E : ASSERT_TRUE(proxy_.IsQuarantined(header));
485 :
486 E : unsigned char sha1_after[base::kSHA1Length] = {};
487 : base::SHA1HashBytes(reinterpret_cast<unsigned char*>(mem),
488 : kAllocSize,
489 E : sha1_after);
490 :
491 E : ASSERT_EQ(0, memcmp(sha1_before, sha1_after, base::kSHA1Length));
492 E : }
493 :
494 E : TEST_F(HeapTest, InternalStructureArePoisoned) {
495 : EXPECT_EQ(Shadow::kAsanMemoryByte,
496 E : Shadow::GetShadowMarkerForAddress(TestShadow::shadow_));
497 :
498 E : const size_t kAllocSize = 13;
499 : // Ensure that the quarantine is large enough to keep this block..
500 E : proxy_.SetQuarantineMaxSize(TestHeapProxy::GetAllocSize(kAllocSize));
501 E : uint8* mem = static_cast<uint8*>(proxy_.Alloc(0, kAllocSize));
502 : TestHeapProxy::BlockHeader* header =
503 E : const_cast<TestHeapProxy::BlockHeader*>(proxy_.ToBlockHeader(mem));
504 :
505 E : ASSERT_TRUE(header != NULL);
506 : const void* alloc_stack_cache_addr =
507 E : reinterpret_cast<const void*>(header->alloc_stack);
508 : EXPECT_EQ(Shadow::kAsanMemoryByte,
509 E : Shadow::GetShadowMarkerForAddress(alloc_stack_cache_addr));
510 :
511 E : ASSERT_TRUE(proxy_.Free(0, mem));
512 E : }
513 :
514 : } // namespace asan
515 : } // namespace agent
|