Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Side by Side Diff: syzygy/agent/asan/shadow_unittest.cc

Issue 2508333002: Remove the is_nested bit from the BlockInfo structure. (Closed)
Patch Set: Address Siggi's comments. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « syzygy/agent/asan/shadow_marker_unittest.cc ('k') | syzygy/agent/asan/unittest_util.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 Google Inc. All Rights Reserved. 1 // Copyright 2012 Google Inc. All Rights Reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with 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 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 // An overflowing range is always inaccessible. 310 // An overflowing range is always inaccessible.
311 EXPECT_EQ(test_array + 3, test_shadow.FindFirstPoisonedByte( 311 EXPECT_EQ(test_array + 3, test_shadow.FindFirstPoisonedByte(
312 test_array + 3, static_cast<size_t>(-3))); 312 test_array + 3, static_cast<size_t>(-3)));
313 313
314 for (size_t i = 0; i < size; ++i) { 314 for (size_t i = 0; i < size; ++i) {
315 // Try valid ranges at every starting position inside the unpoisoned 315 // Try valid ranges at every starting position inside the unpoisoned
316 // range. 316 // range.
317 EXPECT_EQ(nullptr, 317 EXPECT_EQ(nullptr,
318 test_shadow.FindFirstPoisonedByte(test_array + i, size - i)); 318 test_shadow.FindFirstPoisonedByte(test_array + i, size - i));
319 319
320 // Try valid ranges ending at every poisition inside the unpoisoned range. 320 // Try valid ranges ending at every position inside the unpoisoned range.
321 EXPECT_EQ(nullptr, 321 EXPECT_EQ(nullptr,
322 test_shadow.FindFirstPoisonedByte(test_array, size - i)); 322 test_shadow.FindFirstPoisonedByte(test_array, size - i));
323 } 323 }
324 324
325 for (size_t i = 1; i < kShadowRatio; ++i) { 325 for (size_t i = 1; i < kShadowRatio; ++i) {
326 // Try invalid ranges at starting positions outside the unpoisoned range. 326 // Try invalid ranges at starting positions outside the unpoisoned range.
327 EXPECT_EQ(test_array - i, 327 EXPECT_EQ(test_array - i,
328 test_shadow.FindFirstPoisonedByte(test_array - i, size)); 328 test_shadow.FindFirstPoisonedByte(test_array - i, size));
329 329
330 // Try invalid ranges at ending positions outside the unpoisoned range. 330 // Try invalid ranges at ending positions outside the unpoisoned range.
331 EXPECT_EQ(test_array + size, 331 EXPECT_EQ(test_array + size,
332 test_shadow.FindFirstPoisonedByte(test_array, size + i)); 332 test_shadow.FindFirstPoisonedByte(test_array, size + i));
333 } 333 }
334 } 334 }
335 test_shadow.Unpoison(aligned_test_array, aligned_array_length); 335 test_shadow.Unpoison(aligned_test_array, aligned_array_length);
336 } 336 }
337 337
338 TEST_F(ShadowTest, MarkAsFreed) { 338 TEST_F(ShadowTest, MarkAsFreed) {
339 BlockLayout l0 = {}, l1 = {}; 339 BlockLayout l0 = {}, l1 = {};
340 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 16, 30, 30, &l1)); 340 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 16, 30, 30, &l1));
341 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 341 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio,
342 l1.block_size + 2 * kShadowRatio, 30, 30, &l0)); 342 l1.block_size + 2 * kShadowRatio, 30, 30, &l0));
343 343
344 uint8_t* data = new uint8_t[l0.block_size]; 344 uint8_t* data = new uint8_t[l0.block_size];
345 345
346 uint8_t* d0 = data; 346 uint8_t* d0 = data;
347 BlockInfo i0 = {}; 347 BlockInfo i0 = {};
348 BlockInitialize(l0, d0, false, &i0); 348 BlockInitialize(l0, d0, &i0);
349 test_shadow.PoisonAllocatedBlock(i0); 349 test_shadow.PoisonAllocatedBlock(i0);
350 350
351 uint8_t* d1 = i0.RawBody() + kShadowRatio; 351 uint8_t* d1 = i0.RawBody() + kShadowRatio;
352 BlockInfo i1 = {}; 352 BlockInfo i1 = {};
353 BlockInitialize(l1, d1, true, &i1); 353 BlockInitialize(l1, d1, &i1);
354 test_shadow.PoisonAllocatedBlock(i1); 354 test_shadow.PoisonAllocatedBlock(i1);
355 355
356 test_shadow.MarkAsFreed(i0.body, i0.body_size); 356 test_shadow.MarkAsFreed(i0.body, i0.body_size);
357 for (uint8_t* p = i0.RawBlock(); p < i0.RawBlock() + i0.block_size; ++p) { 357 for (uint8_t* p = i0.RawBlock(); p < i0.RawBlock() + i0.block_size; ++p) {
358 if (p >= i0.RawBlock() && p < i0.RawBody()) { 358 if (p >= i0.RawBlock() && p < i0.RawBody()) {
359 EXPECT_TRUE(test_shadow.IsLeftRedzone(p)); 359 EXPECT_TRUE(test_shadow.IsLeftRedzone(p));
360 } else if (p >= i0.RawBody() && 360 } else if (p >= i0.RawBody() &&
361 p < i0.RawTrailerPadding()) { 361 p < i0.RawTrailerPadding()) {
362 if (p >= i1.RawBlock() && p < i1.RawBody()) { 362 if (p >= i1.RawBlock() && p < i1.RawBody()) {
363 EXPECT_TRUE(test_shadow.IsLeftRedzone(p)); 363 EXPECT_TRUE(test_shadow.IsLeftRedzone(p));
(...skipping 16 matching lines...) Expand all
380 test_shadow.Unpoison(data, l0.block_size); 380 test_shadow.Unpoison(data, l0.block_size);
381 delete [] data; 381 delete [] data;
382 } 382 }
383 383
384 TEST_F(ShadowTest, PoisonAllocatedBlock) { 384 TEST_F(ShadowTest, PoisonAllocatedBlock) {
385 BlockLayout layout = {}; 385 BlockLayout layout = {};
386 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 15, 22, 0, &layout)); 386 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 15, 22, 0, &layout));
387 387
388 uint8_t* data = new uint8_t[layout.block_size]; 388 uint8_t* data = new uint8_t[layout.block_size];
389 BlockInfo info = {}; 389 BlockInfo info = {};
390 BlockInitialize(layout, data, false, &info); 390 BlockInitialize(layout, data, &info);
391 391
392 test_shadow.PoisonAllocatedBlock(info); 392 test_shadow.PoisonAllocatedBlock(info);
393 EXPECT_EQ(test_shadow.GetShadowMarkerForAddress(data + 0 * 8), 393 EXPECT_EQ(test_shadow.GetShadowMarkerForAddress(data + 0 * 8),
394 kHeapBlockStartMarker0 | 7); 394 kHeapBlockStartMarker0 | 7);
395 EXPECT_EQ(test_shadow.GetShadowMarkerForAddress(data + 1 * 8), 395 EXPECT_EQ(test_shadow.GetShadowMarkerForAddress(data + 1 * 8),
396 kHeapLeftPaddingMarker); 396 kHeapLeftPaddingMarker);
397 EXPECT_EQ(test_shadow.GetShadowMarkerForAddress(data + 2 * 8), 397 EXPECT_EQ(test_shadow.GetShadowMarkerForAddress(data + 2 * 8),
398 kHeapLeftPaddingMarker); 398 kHeapLeftPaddingMarker);
399 EXPECT_EQ(test_shadow.GetShadowMarkerForAddress(data + 3 * 8), 399 EXPECT_EQ(test_shadow.GetShadowMarkerForAddress(data + 3 * 8),
400 0); 400 0);
(...skipping 22 matching lines...) Expand all
423 EXPECT_FALSE(test_shadow.IsAccessible(cursor)); 423 EXPECT_FALSE(test_shadow.IsAccessible(cursor));
424 test_shadow.Unpoison(info.RawBlock(), info.block_size); 424 test_shadow.Unpoison(info.RawBlock(), info.block_size);
425 425
426 delete [] data; 426 delete [] data;
427 } 427 }
428 428
429 TEST_F(ShadowTest, ScanLeftAndRight) { 429 TEST_F(ShadowTest, ScanLeftAndRight) {
430 size_t offset = test_shadow.length() / 2; 430 size_t offset = test_shadow.length() / 2;
431 size_t l = 0; 431 size_t l = 0;
432 test_shadow.shadow_[offset + 0] = kHeapBlockStartMarker0; 432 test_shadow.shadow_[offset + 0] = kHeapBlockStartMarker0;
433 test_shadow.shadow_[offset + 1] = kHeapNestedBlockStartMarker0; 433 test_shadow.shadow_[offset + 1] = kHeapAddressableMarker;
434 test_shadow.shadow_[offset + 2] = kHeapAddressableMarker; 434 test_shadow.shadow_[offset + 2] = kHeapBlockEndMarker;
435 test_shadow.shadow_[offset + 3] = kHeapNestedBlockEndMarker;
436 test_shadow.shadow_[offset + 4] = kHeapBlockEndMarker;
437 435
438 EXPECT_TRUE(test_shadow.ScanLeftForBracketingBlockStart(0, offset + 0, &l)); 436 EXPECT_TRUE(test_shadow.ScanLeftForBracketingBlockStart(offset + 0, &l));
439 EXPECT_EQ(offset, l); 437 EXPECT_EQ(offset, l);
440 EXPECT_TRUE(test_shadow.ScanLeftForBracketingBlockStart(0, offset + 1, &l)); 438 EXPECT_TRUE(test_shadow.ScanLeftForBracketingBlockStart(offset + 1, &l));
441 EXPECT_EQ(offset + 1, l); 439 EXPECT_EQ(offset, l);
442 EXPECT_TRUE(test_shadow.ScanLeftForBracketingBlockStart(0, offset + 2, &l)); 440 EXPECT_TRUE(test_shadow.ScanLeftForBracketingBlockStart(offset + 2, &l));
443 EXPECT_EQ(offset + 1, l);
444 EXPECT_TRUE(test_shadow.ScanLeftForBracketingBlockStart(0, offset + 3, &l));
445 EXPECT_EQ(offset + 1, l);
446 EXPECT_TRUE(test_shadow.ScanLeftForBracketingBlockStart(0, offset + 4, &l));
447 EXPECT_EQ(offset, l); 441 EXPECT_EQ(offset, l);
448 442
449 EXPECT_FALSE(test_shadow.ScanLeftForBracketingBlockStart(1, offset + 0, &l)); 443 EXPECT_TRUE(test_shadow.ScanRightForBracketingBlockEnd(offset + 0, &l));
450 EXPECT_TRUE(test_shadow.ScanLeftForBracketingBlockStart(1, offset + 1, &l)); 444 EXPECT_EQ(offset + 2, l);
451 EXPECT_EQ(offset, l); 445 EXPECT_TRUE(test_shadow.ScanRightForBracketingBlockEnd(offset + 1, &l));
452 EXPECT_TRUE(test_shadow.ScanLeftForBracketingBlockStart(1, offset + 2, &l)); 446 EXPECT_EQ(offset + 2, l);
453 EXPECT_EQ(offset, l); 447 EXPECT_TRUE(test_shadow.ScanRightForBracketingBlockEnd(offset + 2, &l));
454 EXPECT_TRUE(test_shadow.ScanLeftForBracketingBlockStart(1, offset + 3, &l)); 448 EXPECT_EQ(offset + 2, l);
455 EXPECT_EQ(offset, l);
456 EXPECT_FALSE(test_shadow.ScanLeftForBracketingBlockStart(1, offset + 4, &l));
457
458 EXPECT_FALSE(test_shadow.ScanLeftForBracketingBlockStart(2, offset + 0, &l));
459 EXPECT_FALSE(test_shadow.ScanLeftForBracketingBlockStart(2, offset + 1, &l));
460 EXPECT_FALSE(test_shadow.ScanLeftForBracketingBlockStart(2, offset + 2, &l));
461 EXPECT_FALSE(test_shadow.ScanLeftForBracketingBlockStart(2, offset + 3, &l));
462 EXPECT_FALSE(test_shadow.ScanLeftForBracketingBlockStart(2, offset + 4, &l));
463
464 EXPECT_TRUE(test_shadow.ScanRightForBracketingBlockEnd(0, offset + 0, &l));
465 EXPECT_EQ(offset + 4, l);
466 EXPECT_TRUE(test_shadow.ScanRightForBracketingBlockEnd(0, offset + 1, &l));
467 EXPECT_EQ(offset + 3, l);
468 EXPECT_TRUE(test_shadow.ScanRightForBracketingBlockEnd(0, offset + 2, &l));
469 EXPECT_EQ(offset + 3, l);
470 EXPECT_TRUE(test_shadow.ScanRightForBracketingBlockEnd(0, offset + 3, &l));
471 EXPECT_EQ(offset + 3, l);
472 EXPECT_TRUE(test_shadow.ScanRightForBracketingBlockEnd(0, offset + 4, &l));
473 EXPECT_EQ(offset + 4, l);
474
475 EXPECT_FALSE(test_shadow.ScanRightForBracketingBlockEnd(1, offset + 0, &l));
476 EXPECT_TRUE(test_shadow.ScanRightForBracketingBlockEnd(1, offset + 1, &l));
477 EXPECT_EQ(offset + 4, l);
478 EXPECT_TRUE(test_shadow.ScanRightForBracketingBlockEnd(1, offset + 2, &l));
479 EXPECT_EQ(offset + 4, l);
480 EXPECT_TRUE(test_shadow.ScanRightForBracketingBlockEnd(1, offset + 3, &l));
481 EXPECT_EQ(offset + 4, l);
482 EXPECT_FALSE(test_shadow.ScanRightForBracketingBlockEnd(1, offset + 4, &l));
483
484 EXPECT_FALSE(test_shadow.ScanRightForBracketingBlockEnd(2, offset + 0, &l));
485 EXPECT_FALSE(test_shadow.ScanRightForBracketingBlockEnd(2, offset + 1, &l));
486 EXPECT_FALSE(test_shadow.ScanRightForBracketingBlockEnd(2, offset + 2, &l));
487 EXPECT_FALSE(test_shadow.ScanRightForBracketingBlockEnd(2, offset + 3, &l));
488 EXPECT_FALSE(test_shadow.ScanRightForBracketingBlockEnd(2, offset + 4, &l));
489 449
490 ::memset(test_shadow.shadow_ + offset, 0, 5); 450 ::memset(test_shadow.shadow_ + offset, 0, 5);
491 } 451 }
492 452
493 TEST_F(ShadowTest, ScanRightPerfTest) { 453 TEST_F(ShadowTest, ScanRightPerfTest) {
494 size_t offset = test_shadow.length() / 2; 454 size_t offset = test_shadow.length() / 2;
495 size_t length = 1 * 1024 * 1024; 455 size_t length = 1 * 1024 * 1024;
496 456
497 ::memset(test_shadow.shadow_ + offset, 0, length); 457 ::memset(test_shadow.shadow_ + offset, 0, length);
498 458
499 test_shadow.shadow_[offset + 0] = kHeapBlockStartMarker0; 459 test_shadow.shadow_[offset + 0] = kHeapBlockStartMarker0;
500 // A nested block with freed contents. 460 // The end of the block.
501 test_shadow.shadow_[offset + 50] = kHeapNestedBlockStartMarker0;
502 ::memset(test_shadow.shadow_ + offset + 51, kHeapFreedMarker, 8);
503 test_shadow.shadow_[offset + 60] = kHeapNestedBlockEndMarker;
504 // A nested block with a nested block.
505 test_shadow.shadow_[offset + 100000] = kHeapNestedBlockStartMarker0;
506 test_shadow.shadow_[offset + 100100] = kHeapNestedBlockStartMarker0;
507 test_shadow.shadow_[offset + 100400] = kHeapNestedBlockEndMarker;
508 test_shadow.shadow_[offset + 200000] = kHeapNestedBlockEndMarker;
509 // The end of the outer block.
510 test_shadow.shadow_[offset + length - 1] = kHeapBlockEndMarker; 461 test_shadow.shadow_[offset + length - 1] = kHeapBlockEndMarker;
511 462
512 uint64_t tnet = 0; 463 uint64_t tnet = 0;
513 for (size_t i = 0; i < 100; ++i) { 464 for (size_t i = 0; i < 100; ++i) {
514 size_t l = 0; 465 size_t l = 0;
515 uint64_t t0 = ::__rdtsc(); 466 uint64_t t0 = ::__rdtsc();
516 test_shadow.ScanRightForBracketingBlockEnd(0, offset + 1, &l); 467 test_shadow.ScanRightForBracketingBlockEnd(offset + 1, &l);
517 uint64_t t1 = ::__rdtsc(); 468 uint64_t t1 = ::__rdtsc();
518 tnet += t1 - t0; 469 tnet += t1 - t0;
519 } 470 }
520 testing::EmitMetric("Syzygy.Asan.Shadow.ScanRightForBracketingBlockEnd", 471 testing::EmitMetric("Syzygy.Asan.Shadow.ScanRightForBracketingBlockEnd",
521 tnet); 472 tnet);
522 473
523 // Reset the shadow memory. 474 // Reset the shadow memory.
524 ::memset(test_shadow.shadow_ + offset, 0, length); 475 ::memset(test_shadow.shadow_ + offset, 0, length);
525 } 476 }
526 477
527 TEST_F(ShadowTest, IsLeftOrRightRedzone) { 478 TEST_F(ShadowTest, IsLeftOrRightRedzone) {
528 BlockLayout layout = {}; 479 BlockLayout layout = {};
529 const size_t kAllocSize = 15; 480 const size_t kAllocSize = 15;
530 ASSERT_NE(0U, kAllocSize % kShadowRatio); 481 ASSERT_NE(0U, kAllocSize % kShadowRatio);
531 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, kAllocSize, 0, 0, 482 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, kAllocSize, 0, 0,
532 &layout)); 483 &layout));
533 484
534 std::unique_ptr<uint8_t[]> data(new uint8_t[layout.block_size]); 485 std::unique_ptr<uint8_t[]> data(new uint8_t[layout.block_size]);
535 BlockInfo info = {}; 486 BlockInfo info = {};
536 BlockInitialize(layout, data.get(), false, &info); 487 BlockInitialize(layout, data.get(), &info);
537 488
538 test_shadow.PoisonAllocatedBlock(info); 489 test_shadow.PoisonAllocatedBlock(info);
539 uint8_t* block = reinterpret_cast<uint8_t*>(info.header); 490 uint8_t* block = reinterpret_cast<uint8_t*>(info.header);
540 uint8_t* cursor = block; 491 uint8_t* cursor = block;
541 492
542 for (; cursor < info.RawBody(); ++cursor) { 493 for (; cursor < info.RawBody(); ++cursor) {
543 EXPECT_TRUE(test_shadow.IsLeftRedzone(cursor)); 494 EXPECT_TRUE(test_shadow.IsLeftRedzone(cursor));
544 EXPECT_FALSE(test_shadow.IsRightRedzone(cursor)); 495 EXPECT_FALSE(test_shadow.IsRightRedzone(cursor));
545 } 496 }
546 for (; cursor < info.RawBody() + info.body_size; ++cursor) { 497 for (; cursor < info.RawBody() + info.body_size; ++cursor) {
547 EXPECT_FALSE(test_shadow.IsLeftRedzone(cursor)); 498 EXPECT_FALSE(test_shadow.IsLeftRedzone(cursor));
548 EXPECT_FALSE(test_shadow.IsRightRedzone(cursor)); 499 EXPECT_FALSE(test_shadow.IsRightRedzone(cursor));
549 } 500 }
550 for (; cursor < block + info.block_size; ++cursor) { 501 for (; cursor < block + info.block_size; ++cursor) {
551 EXPECT_FALSE(test_shadow.IsLeftRedzone(cursor)); 502 EXPECT_FALSE(test_shadow.IsLeftRedzone(cursor));
552 EXPECT_TRUE(test_shadow.IsRightRedzone(cursor)); 503 EXPECT_TRUE(test_shadow.IsRightRedzone(cursor));
553 } 504 }
554 505
555 test_shadow.Unpoison(block, info.block_size); 506 test_shadow.Unpoison(block, info.block_size);
556 } 507 }
557 508
558 namespace { 509 namespace {
559 510
560 void TestBlockInfoFromShadow(Shadow* shadow, 511 void TestBlockInfoFromShadow(Shadow* shadow, const BlockLayout& block_layout) {
561 const BlockLayout& outer,
562 const BlockLayout& nested) {
563 ASSERT_TRUE(shadow != nullptr); 512 ASSERT_TRUE(shadow != nullptr);
564 ASSERT_LE(nested.block_size, outer.body_size);
565 513
566 uint8_t* data = new uint8_t[outer.block_size]; 514 uint8_t* data = new uint8_t[block_layout.block_size];
567 515
568 // Try recovering the block from every position within it when no nested
569 // block exists. Expect finding a nested block to fail.
570 BlockInfo info = {}; 516 BlockInfo info = {};
571 BlockInitialize(outer, data, false, &info); 517 BlockInitialize(block_layout, data, &info);
572 shadow->PoisonAllocatedBlock(info); 518 shadow->PoisonAllocatedBlock(info);
573 BlockInfo info_recovered = {}; 519 BlockInfo info_recovered = {};
574 for (size_t i = 0; i < info.block_size; ++i) { 520 for (size_t i = 0; i < info.block_size; ++i) {
575 EXPECT_TRUE(shadow->BlockInfoFromShadow( 521 EXPECT_TRUE(shadow->BlockInfoFromShadow(
576 info.RawBlock() + i, &info_recovered)); 522 info.RawBlock() + i, &info_recovered));
577 EXPECT_EQ(0, ::memcmp(&info, &info_recovered, sizeof(info))); 523 EXPECT_EQ(0, ::memcmp(&info, &info_recovered, sizeof(info)));
578
579 // This block should have no parent block as its not nested.
580 EXPECT_FALSE(shadow->ParentBlockInfoFromShadow(
581 info, &info_recovered));
582 } 524 }
583 525
584 // Place a nested block and try the recovery from every position again.
585 size_t padding = ::common::AlignDown(info.body_size - nested.block_size,
586 kShadowRatio * 2);
587 uint8_t* nested_begin = info.RawBody() + padding / 2;
588 uint8_t* nested_end = nested_begin + nested.block_size;
589 BlockInfo nested_info = {};
590 BlockInitialize(nested, nested_begin, true, &nested_info);
591 nested_info.header->is_nested = true;
592 shadow->PoisonAllocatedBlock(nested_info);
593 for (size_t i = 0; i < info.block_size; ++i) {
594 uint8_t* pos = info.RawBlock() + i;
595 EXPECT_TRUE(shadow->BlockInfoFromShadow(pos, &info_recovered));
596
597 BlockInfo parent_info = {};
598 bool found_parent = shadow->ParentBlockInfoFromShadow(
599 info_recovered, &parent_info);
600
601 if (pos >= nested_begin && pos < nested_end) {
602 EXPECT_EQ(0, ::memcmp(&nested_info, &info_recovered,
603 sizeof(nested_info)));
604 EXPECT_TRUE(found_parent);
605 EXPECT_EQ(0, ::memcmp(&info, &parent_info, sizeof(info)));
606 } else {
607 EXPECT_EQ(0, ::memcmp(&info, &info_recovered, sizeof(info)));
608 EXPECT_FALSE(found_parent);
609 }
610 }
611 shadow->Unpoison(info.header, info.block_size);
612
613 delete [] data; 526 delete [] data;
614 } 527 }
615 528
616 } // namespace 529 } // namespace
617 530
618 TEST_F(ShadowTest, BlockInfoFromShadow) { 531 TEST_F(ShadowTest, BlockInfoFromShadow) {
619 // This is a simple layout that will be nested inside of another block.
620 BlockLayout layout0 = {}; 532 BlockLayout layout0 = {};
621 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 6, 0, 0, &layout0)); 533 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 6, 0, 0, &layout0));
622 534
623 // Plan two layouts, one with padding and another with none. The first has 535 uint8_t* data = new uint8_t[layout0.block_size];
624 // exactly enough space for the nested block, while the second has room to
625 // spare.
626 BlockLayout layout1 = {};
627 BlockLayout layout2 = {};
628 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio,
629 static_cast<uint32_t>(
630 ::common::AlignUp(layout0.block_size, kShadowRatio) + 4), 0, 0,
631 &layout1));
632 ASSERT_EQ(0u, layout1.header_padding_size);
633 ASSERT_EQ(0u, layout1.trailer_padding_size);
634 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio,
635 layout0.block_size + 2 * kShadowRatio, 32, 13, &layout2));
636 ASSERT_LT(0u, layout2.header_padding_size);
637 ASSERT_LT(0u, layout2.trailer_padding_size);
638 536
639 EXPECT_NO_FATAL_FAILURE(TestBlockInfoFromShadow( 537 BlockInfo info = {};
640 &test_shadow, layout1, layout0)); 538 BlockInitialize(layout0, data, &info);
641 EXPECT_NO_FATAL_FAILURE(TestBlockInfoFromShadow( 539 test_shadow.PoisonAllocatedBlock(info);
642 &test_shadow, layout2, layout0)); 540 BlockInfo info_recovered = {};
541 for (size_t i = 0; i < info.block_size; ++i) {
542 EXPECT_TRUE(
543 test_shadow.BlockInfoFromShadow(info.RawBlock() + i, &info_recovered));
544 EXPECT_EQ(0, ::memcmp(&info, &info_recovered, sizeof(info)));
545 }
546 delete[] data;
643 } 547 }
644 548
645 TEST_F(ShadowTest, IsBeginningOfBlockBody) { 549 TEST_F(ShadowTest, IsBeginningOfBlockBody) {
646 BlockLayout l = {}; 550 BlockLayout l = {};
647 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 7, 0, 0, &l)); 551 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 7, 0, 0, &l));
648 552
649 size_t data_size = l.block_size; 553 size_t data_size = l.block_size;
650 std::unique_ptr<uint8_t[]> data(new uint8_t[data_size]); 554 std::unique_ptr<uint8_t[]> data(new uint8_t[data_size]);
651 555
652 BlockInfo block_info = {}; 556 BlockInfo block_info = {};
653 BlockInitialize(l, data.get(), false, &block_info); 557 BlockInitialize(l, data.get(), &block_info);
654 558
655 test_shadow.PoisonAllocatedBlock(block_info); 559 test_shadow.PoisonAllocatedBlock(block_info);
656 560
657 EXPECT_TRUE(test_shadow.IsBeginningOfBlockBody(block_info.body)); 561 EXPECT_TRUE(test_shadow.IsBeginningOfBlockBody(block_info.body));
658 EXPECT_FALSE(test_shadow.IsBeginningOfBlockBody(data.get())); 562 EXPECT_FALSE(test_shadow.IsBeginningOfBlockBody(data.get()));
659 563
660 block_info.header->state = QUARANTINED_BLOCK; 564 block_info.header->state = QUARANTINED_BLOCK;
661 test_shadow.MarkAsFreed(block_info.body, block_info.body_size); 565 test_shadow.MarkAsFreed(block_info.body, block_info.body_size);
662 566
663 EXPECT_TRUE(test_shadow.IsBeginningOfBlockBody(block_info.body)); 567 EXPECT_TRUE(test_shadow.IsBeginningOfBlockBody(block_info.body));
664 EXPECT_FALSE(test_shadow.IsBeginningOfBlockBody(data.get())); 568 EXPECT_FALSE(test_shadow.IsBeginningOfBlockBody(data.get()));
665 569
666 test_shadow.Unpoison(data.get(), data_size); 570 test_shadow.Unpoison(data.get(), data_size);
667 } 571 }
668 572
669 TEST_F(ShadowTest, IsBeginningOfBlockBodyForBlockOfSizeZero) { 573 TEST_F(ShadowTest, IsBeginningOfBlockBodyForBlockOfSizeZero) {
670 BlockLayout l = {}; 574 BlockLayout l = {};
671 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 0, 0, 0, &l)); 575 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 0, 0, 0, &l));
672 576
673 size_t data_size = l.block_size; 577 size_t data_size = l.block_size;
674 std::unique_ptr<uint8_t[]> data(new uint8_t[data_size]); 578 std::unique_ptr<uint8_t[]> data(new uint8_t[data_size]);
675 579
676 BlockInfo block_info = {}; 580 BlockInfo block_info = {};
677 BlockInitialize(l, data.get(), false, &block_info); 581 BlockInitialize(l, data.get(), &block_info);
678 582
679 test_shadow.PoisonAllocatedBlock(block_info); 583 test_shadow.PoisonAllocatedBlock(block_info);
680 584
681 EXPECT_TRUE(test_shadow.IsBeginningOfBlockBody(block_info.body)); 585 EXPECT_TRUE(test_shadow.IsBeginningOfBlockBody(block_info.body));
682 EXPECT_FALSE(test_shadow.IsBeginningOfBlockBody(data.get())); 586 EXPECT_FALSE(test_shadow.IsBeginningOfBlockBody(data.get()));
683 587
684 block_info.header->state = QUARANTINED_FLOODED_BLOCK; 588 block_info.header->state = QUARANTINED_FLOODED_BLOCK;
685 test_shadow.MarkAsFreed(block_info.body, block_info.body_size); 589 test_shadow.MarkAsFreed(block_info.body, block_info.body_size);
686 590
687 EXPECT_TRUE(test_shadow.IsBeginningOfBlockBody(block_info.body)); 591 EXPECT_TRUE(test_shadow.IsBeginningOfBlockBody(block_info.body));
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
751 655
752 // A fixture for shadow walker tests. 656 // A fixture for shadow walker tests.
753 class ShadowWalkerTest : public testing::Test { 657 class ShadowWalkerTest : public testing::Test {
754 public: 658 public:
755 TestShadow test_shadow; 659 TestShadow test_shadow;
756 }; 660 };
757 661
758 } // namespace 662 } // namespace
759 663
760 TEST_F(ShadowWalkerTest, WalkEmptyRange) { 664 TEST_F(ShadowWalkerTest, WalkEmptyRange) {
761 ShadowWalker w(&test_shadow, true, &test_shadow, &test_shadow); 665 ShadowWalker w(&test_shadow, &test_shadow, &test_shadow);
762 BlockInfo i = {}; 666 BlockInfo i = {};
763 EXPECT_FALSE(w.Next(&i)); 667 EXPECT_FALSE(w.Next(&i));
764 } 668 }
765 669
766 TEST_F(ShadowWalkerTest, WalkRangeAtEndOfAddressSpace) { 670 TEST_F(ShadowWalkerTest, WalkRangeAtEndOfAddressSpace) {
767 TestShadow ts1(4, 30); // 4GB. 671 TestShadow ts1(4, 30); // 4GB.
768 ShadowWalker w( 672 ShadowWalker w(&ts1, reinterpret_cast<const void*>(ts1.memory_size() - 100),
769 &ts1, true, 673 reinterpret_cast<const void*>(ts1.memory_size()));
770 reinterpret_cast<const void*>(ts1.memory_size() - 100),
771 reinterpret_cast<const void*>(ts1.memory_size()));
772 BlockInfo i = {}; 674 BlockInfo i = {};
773 EXPECT_FALSE(w.Next(&i)); 675 EXPECT_FALSE(w.Next(&i));
774 } 676 }
775 677
776 TEST_F(ShadowWalkerTest, WalksNonNestedBlocks) { 678 TEST_F(ShadowWalkerTest, WalksBlocks) {
777 BlockLayout l = {}; 679 BlockLayout l = {};
778 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 7, 0, 0, &l)); 680 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 7, 0, 0, &l));
779 681
780 size_t data_size = l.block_size * 3 + kShadowRatio; 682 size_t data_size = l.block_size * 3 + kShadowRatio;
781 uint8_t* data = new uint8_t[data_size]; 683 uint8_t* data = new uint8_t[data_size];
782 uint8_t* data0 = data; 684 uint8_t* data0 = data;
783 uint8_t* data1 = data0 + l.block_size + kShadowRatio; 685 uint8_t* data1 = data0 + l.block_size + kShadowRatio;
784 uint8_t* data2 = data1 + l.block_size; 686 uint8_t* data2 = data1 + l.block_size;
785 687
786 BlockInfo i0 = {}, i1 = {}, i2 = {}; 688 BlockInfo i0 = {}, i1 = {}, i2 = {};
787 BlockInitialize(l, data0, false, &i0); 689 BlockInitialize(l, data0, &i0);
788 BlockInitialize(l, data1, false, &i1); 690 BlockInitialize(l, data1, &i1);
789 BlockInitialize(l, data2, false, &i2); 691 BlockInitialize(l, data2, &i2);
790 692
791 test_shadow.PoisonAllocatedBlock(i0); 693 test_shadow.PoisonAllocatedBlock(i0);
792 test_shadow.PoisonAllocatedBlock(i1); 694 test_shadow.PoisonAllocatedBlock(i1);
793 test_shadow.PoisonAllocatedBlock(i2); 695 test_shadow.PoisonAllocatedBlock(i2);
794 696
795 i2.header->state = QUARANTINED_BLOCK; 697 i2.header->state = QUARANTINED_BLOCK;
796 test_shadow.MarkAsFreed(i2.body, i2.body_size); 698 test_shadow.MarkAsFreed(i2.body, i2.body_size);
797 699
798 // Do a non-recursive walk through the shadow. 700 // Do a non-recursive walk through the shadow.
799 BlockInfo i = {}; 701 BlockInfo i = {};
800 ShadowWalker w0(&test_shadow, false, data, data + data_size); 702 ShadowWalker w0(&test_shadow, data, data + data_size);
801 EXPECT_EQ(-1, w0.nesting_depth());
802 EXPECT_TRUE(w0.Next(&i)); 703 EXPECT_TRUE(w0.Next(&i));
803 EXPECT_EQ(0, w0.nesting_depth());
804 EXPECT_TRUE(w0.Next(&i)); 704 EXPECT_TRUE(w0.Next(&i));
805 EXPECT_EQ(0, w0.nesting_depth());
806 EXPECT_TRUE(w0.Next(&i)); 705 EXPECT_TRUE(w0.Next(&i));
807 EXPECT_EQ(0, w0.nesting_depth());
808 EXPECT_FALSE(w0.Next(&i)); 706 EXPECT_FALSE(w0.Next(&i));
809 EXPECT_EQ(-1, w0.nesting_depth());
810
811 // Walk recursively through the shadow and expect the same results.
812 ShadowWalker w1(&test_shadow, true, data, data + data_size);
813 EXPECT_EQ(-1, w1.nesting_depth());
814 EXPECT_TRUE(w1.Next(&i));
815 EXPECT_EQ(0, w1.nesting_depth());
816 EXPECT_EQ(0, ::memcmp(&i, &i0, sizeof(i)));
817 EXPECT_TRUE(w1.Next(&i));
818 EXPECT_EQ(0, w1.nesting_depth());
819 EXPECT_EQ(0, ::memcmp(&i, &i1, sizeof(i)));
820 EXPECT_TRUE(w1.Next(&i));
821 EXPECT_EQ(0, w1.nesting_depth());
822 EXPECT_EQ(0, ::memcmp(&i, &i2, sizeof(i)));
823 EXPECT_FALSE(w1.Next(&i));
824 EXPECT_EQ(-1, w1.nesting_depth());
825 707
826 test_shadow.Unpoison(data, data_size); 708 test_shadow.Unpoison(data, data_size);
827 delete [] data; 709 delete [] data;
828 }
829
830 TEST_F(ShadowWalkerTest, WalksNestedBlocks) {
831 BlockLayout b0 = {}, b1 = {}, b2 = {}, b00 = {}, b01 = {}, b10 = {},
832 b100 = {};
833 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 15, 30, 30, &b00));
834 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 7, 0, 0, &b01));
835 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio,
836 b00.block_size + b01.block_size + kShadowRatio, 0, 0, &b0));
837 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 7, 0, 0, &b100));
838 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, b100.block_size, 0, 0,
839 &b10));
840 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, b10.block_size, 0, 0,
841 &b1));
842 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 100, 0, 0, &b2));
843
844 size_t data_size = b0.block_size + b1.block_size + kShadowRatio +
845 b2.block_size;
846 uint8_t* data = new uint8_t[data_size];
847
848 // Initialize the depth 0 blocks.
849 uint8_t* d0 = data;
850 uint8_t* d1 = d0 + b0.block_size;
851 uint8_t* d2 = d1 + b1.block_size + kShadowRatio;
852 BlockInfo i0 = {}, i1 = {}, i2 = {};
853 BlockInitialize(b0, d0, false, &i0);
854 BlockInitialize(b1, d1, false, &i1);
855 BlockInitialize(b2, d2, false, &i2);
856 test_shadow.PoisonAllocatedBlock(i0);
857 test_shadow.PoisonAllocatedBlock(i1);
858 test_shadow.PoisonAllocatedBlock(i2);
859
860 // Initialize depth 1 blocks.
861 uint8_t* d00 = i0.RawBody();
862 uint8_t* d01 = d00 + b00.block_size + kShadowRatio;
863 uint8_t* d10 = i1.RawBody();
864 BlockInfo i00 = {}, i01 = {}, i10 = {};
865 BlockInitialize(b00, d00, true, &i00);
866 BlockInitialize(b01, d01, true, &i01);
867 BlockInitialize(b10, d10, true, &i10);
868 test_shadow.PoisonAllocatedBlock(i00);
869 test_shadow.PoisonAllocatedBlock(i01);
870 test_shadow.PoisonAllocatedBlock(i10);
871
872 // Initialize depth 2 blocks.
873 uint8_t* d100 = i10.RawBody();
874 BlockInfo i100 = {};
875 BlockInitialize(b100, d100, true, &i100);
876 test_shadow.PoisonAllocatedBlock(i100);
877 i100.header->state = QUARANTINED_FLOODED_BLOCK;
878 test_shadow.MarkAsFreed(i100.body, i100.body_size);
879
880 // Do a non-recursive walk through the shadow.
881 BlockInfo i = {};
882 ShadowWalker w0(&test_shadow, false, data, data + data_size);
883 EXPECT_EQ(-1, w0.nesting_depth());
884 EXPECT_TRUE(w0.Next(&i));
885 EXPECT_EQ(0, w0.nesting_depth());
886 EXPECT_EQ(0, ::memcmp(&i, &i0, sizeof(i)));
887 EXPECT_TRUE(w0.Next(&i));
888 EXPECT_EQ(0, w0.nesting_depth());
889 EXPECT_EQ(0, ::memcmp(&i, &i1, sizeof(i)));
890 EXPECT_TRUE(w0.Next(&i));
891 EXPECT_EQ(0, w0.nesting_depth());
892 EXPECT_EQ(0, ::memcmp(&i, &i2, sizeof(i)));
893 EXPECT_FALSE(w0.Next(&i));
894 EXPECT_EQ(-1, w0.nesting_depth());
895
896 // Walk recursively through the shadow.
897 ShadowWalker w1(&test_shadow, true, data, data + data_size);
898 EXPECT_EQ(-1, w1.nesting_depth());
899 EXPECT_TRUE(w1.Next(&i));
900 EXPECT_EQ(0, w1.nesting_depth());
901 EXPECT_EQ(0, ::memcmp(&i, &i0, sizeof(i)));
902 EXPECT_TRUE(w1.Next(&i));
903 EXPECT_EQ(1, w1.nesting_depth());
904 EXPECT_EQ(0, ::memcmp(&i, &i00, sizeof(i)));
905 EXPECT_TRUE(w1.Next(&i));
906 EXPECT_EQ(1, w1.nesting_depth());
907 EXPECT_EQ(0, ::memcmp(&i, &i01, sizeof(i)));
908 EXPECT_TRUE(w1.Next(&i));
909 EXPECT_EQ(0, w1.nesting_depth());
910 EXPECT_EQ(0, ::memcmp(&i, &i1, sizeof(i)));
911 EXPECT_TRUE(w1.Next(&i));
912 EXPECT_EQ(1, w1.nesting_depth());
913 EXPECT_EQ(0, ::memcmp(&i, &i10, sizeof(i)));
914 EXPECT_TRUE(w1.Next(&i));
915 EXPECT_EQ(2, w1.nesting_depth());
916 EXPECT_EQ(0, ::memcmp(&i, &i100, sizeof(i)));
917 EXPECT_TRUE(w1.Next(&i));
918 EXPECT_EQ(0, w1.nesting_depth());
919 EXPECT_EQ(0, ::memcmp(&i, &i2, sizeof(i)));
920 EXPECT_FALSE(w1.Next(&i));
921 EXPECT_EQ(-1, w1.nesting_depth());
922
923 test_shadow.Unpoison(data, data_size);
924 delete [] data;
925 } 710 }
926 711
927 TEST_F(ShadowWalkerTest, WalkShadowWithUncommittedRanges) { 712 TEST_F(ShadowWalkerTest, WalkShadowWithUncommittedRanges) {
928 // Create a 512k memory block. 713 // Create a 512k memory block.
929 const size_t kMemorySize = 512 * 1024; 714 const size_t kMemorySize = 512 * 1024;
930 uint8_t memory_block[kMemorySize]; 715 uint8_t memory_block[kMemorySize];
931 const size_t shadow_size = Shadow::RequiredLength(); 716 const size_t shadow_size = Shadow::RequiredLength();
932 717
933 // Allocate the shadow memory, only reserve the memory. 718 // Allocate the shadow memory, only reserve the memory.
934 uint8_t* shadow_memory = static_cast<uint8_t*>( 719 uint8_t* shadow_memory = static_cast<uint8_t*>(
(...skipping 25 matching lines...) Expand all
960 ::common::AlignDown(shadow_address, GetPageSize()); 745 ::common::AlignDown(shadow_address, GetPageSize());
961 // Commit the shadow memory for this block. 746 // Commit the shadow memory for this block.
962 EXPECT_EQ(static_cast<void*>(shadow_address_page_begin), 747 EXPECT_EQ(static_cast<void*>(shadow_address_page_begin),
963 ::VirtualAlloc(shadow_address, GetPageSize(), MEM_COMMIT, 748 ::VirtualAlloc(shadow_address, GetPageSize(), MEM_COMMIT,
964 PAGE_READWRITE)); 749 PAGE_READWRITE));
965 750
966 // Address of the memory for this block. 751 // Address of the memory for this block.
967 uint8_t* page_address = ::common::AlignUp( 752 uint8_t* page_address = ::common::AlignUp(
968 memory_block + i * GetPageSize() * kShadowRatio, kShadowRatio); 753 memory_block + i * GetPageSize() * kShadowRatio, kShadowRatio);
969 BlockInfo block_info = {}; 754 BlockInfo block_info = {};
970 BlockInitialize(l, page_address, false, &block_info); 755 BlockInitialize(l, page_address, &block_info);
971 block_info_vec.push_back(block_info); 756 block_info_vec.push_back(block_info);
972 757
973 // Poison the block. 758 // Poison the block.
974 ts1.PoisonAllocatedBlock(block_info); 759 ts1.PoisonAllocatedBlock(block_info);
975 } 760 }
976 761
977 size_t block_count = 0; 762 size_t block_count = 0;
978 ShadowWalker w(&ts1, true, memory_block, memory_block + kMemorySize); 763 ShadowWalker w(&ts1, memory_block, memory_block + kMemorySize);
979 BlockInfo i = {}; 764 BlockInfo i = {};
980 while (w.Next(&i)) { 765 while (w.Next(&i)) {
981 EXPECT_LT(block_count, block_info_vec.size()); 766 EXPECT_LT(block_count, block_info_vec.size());
982 EXPECT_EQ(block_info_vec[block_count].header, i.header); 767 EXPECT_EQ(block_info_vec[block_count].header, i.header);
983 EXPECT_EQ(block_info_vec[block_count].body, i.body); 768 EXPECT_EQ(block_info_vec[block_count].body, i.body);
984 EXPECT_EQ(block_info_vec[block_count].trailer, i.trailer); 769 EXPECT_EQ(block_info_vec[block_count].trailer, i.trailer);
985 block_count++; 770 block_count++;
986 } 771 }
987 EXPECT_EQ(block_info_vec.size(), block_count); 772 EXPECT_EQ(block_info_vec.size(), block_count);
988 EXPECT_FALSE(w.Next(&i)); 773 EXPECT_FALSE(w.Next(&i));
989 774
990 EXPECT_GT(::VirtualFree(shadow_memory, 0, MEM_RELEASE), 0U); 775 EXPECT_GT(::VirtualFree(shadow_memory, 0, MEM_RELEASE), 0U);
991 } 776 }
992 777
993 } // namespace asan 778 } // namespace asan
994 } // namespace agent 779 } // namespace agent
OLDNEW
« no previous file with comments | « syzygy/agent/asan/shadow_marker_unittest.cc ('k') | syzygy/agent/asan/unittest_util.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698