Chromium Code Reviews| Index: syzygy/agent/asan/shadow.cc |
| diff --git a/syzygy/agent/asan/shadow.cc b/syzygy/agent/asan/shadow.cc |
| index b397d5db0dd0fc6b70da2c376a536221da733d4f..35a1dcee4c2db710b5c19cdfd611a0bea5d67e2c 100644 |
| --- a/syzygy/agent/asan/shadow.cc |
| +++ b/syzygy/agent/asan/shadow.cc |
| @@ -33,7 +33,7 @@ base::Lock shadow_instance_lock; |
| // The pointer for the exception handler to know what shadow object is |
| // currently used. Under shadow_instance_lock. |
| // TODO(loskutov): eliminate this by enforcing Shadow to be a singleton. |
| -const Shadow* shadow_instance; |
| +const Shadow* shadow_instance = nullptr; |
| // The exception handler, intended to map the pages for shadow and page_bits |
| // on demand. When a page fault happens, the operating systems calls |
| @@ -41,6 +41,7 @@ const Shadow* shadow_instance; |
| // commited seamlessly for the caller, and then execution continues. |
| // Otherwise, the OS keeps searching for an appropriate handler. |
| LONG NTAPI ShadowExceptionHandler(PEXCEPTION_POINTERS exception_pointers) { |
| + DCHECK_NE(static_cast<const Shadow*>(nullptr), shadow_instance); |
| // Only handle access violations. |
| if (exception_pointers->ExceptionRecord->ExceptionCode != |
| EXCEPTION_ACCESS_VIOLATION) { |
| @@ -76,6 +77,16 @@ LONG NTAPI ShadowExceptionHandler(PEXCEPTION_POINTERS exception_pointers) { |
| ? EXCEPTION_CONTINUE_EXECUTION |
| : EXCEPTION_CONTINUE_SEARCH; |
| } |
| + |
| +// Check if |addr| is in a memory region that has been committed. |
| +bool AddressIsInCommittedMemory(const void* addr) { |
| + MEMORY_BASIC_INFORMATION memory_info = {}; |
| + SIZE_T mem_status = ::VirtualQuery(addr, &memory_info, sizeof(memory_info)); |
| + DCHECK_GT(mem_status, 0u); |
| + if (memory_info.State != MEM_COMMIT) |
| + return false; |
| + return true; |
| +} |
| #endif // defined _WIN64 |
| static const size_t kPageSize = GetPageSize(); |
| @@ -215,7 +226,7 @@ bool Shadow::IsClean() const { |
| auto ret = ::VirtualQuery(cursor, &info, sizeof(info)); |
| DCHECK_GT(ret, 0u); |
| next_cursor = static_cast<uint8_t*>(info.BaseAddress) + info.RegionSize; |
| - if (info.Type == MEM_COMMIT) |
| + if (info.State == MEM_COMMIT) |
| break; |
| cursor = next_cursor; |
| } |
| @@ -284,7 +295,7 @@ void Shadow::Init(bool own_memory, void* shadow, size_t length) { |
| shadow_instance = this; |
| } |
| exception_handler_ = |
| - AddVectoredExceptionHandler(TRUE, ShadowExceptionHandler); |
| + ::AddVectoredExceptionHandler(TRUE, ShadowExceptionHandler); |
| #endif |
| // Handle the case of a failed allocation. |
| @@ -884,9 +895,22 @@ bool Shadow::ScanLeftForBracketingBlockStart( |
| size_t left = cursor; |
| int nesting_depth = static_cast<int>(initial_nesting_depth); |
| +#ifdef _WIN64 |
| + if (!AddressIsInCommittedMemory((&shadow_[left]))) |
|
chrisha
2016/10/13 20:22:49
This is going to cost a VirtualQuery per value of
Sébastien Marchand
2016/10/13 21:05:45
No, in the loop I'm evaluating the following condi
Sébastien Marchand
2016/10/14 19:04:14
Ha, didn't realized that VirtualQuery return the i
|
| + return false; |
| + uint8_t* page_begin = ::common::AlignDown(&shadow_[left], kPageSize); |
| +#endif |
| if (ShadowMarkerHelper::IsBlockEnd(shadow_[left])) |
| --nesting_depth; |
| while (true) { |
| +#ifdef _WIN64 |
| + if (&shadow_[left] < page_begin && |
| + !AddressIsInCommittedMemory((&shadow_[left]))) { |
| + return false; |
| + } else { |
| + page_begin = ::common::AlignDown(&shadow_[left], kPageSize); |
| + } |
| +#endif |
| if (ShadowMarkerHelper::IsBlockStart(shadow_[left])) { |
| if (nesting_depth == 0) { |
| *location = left; |
| @@ -1049,6 +1073,11 @@ bool Shadow::BlockInfoFromShadowImpl( |
| size_t left = reinterpret_cast<uintptr_t>(addr) / kShadowRatio; |
| size_t right = left; |
| +#ifdef _WIN64 |
| + if (!AddressIsInCommittedMemory((&shadow_[left]))) |
| + return false; |
| +#endif |
| + |
| if (!ScanLeftForBracketingBlockStart(initial_nesting_depth, left, &left)) |
| return false; |
| if (!ScanRightForBracketingBlockEnd(initial_nesting_depth, right, &right)) |
| @@ -1141,7 +1170,7 @@ bool ShadowWalker::Next(BlockInfo* info) { |
| return false; |
| // Step to the beginning of the next region and try again. |
| - shadow_cursor_ = start_of_region; |
| + shadow_cursor_ = end_of_region; |
|
chrisha
2016/10/13 20:22:49
Oops! My bad. New unittest for this?
Sébastien Marchand
2016/10/14 19:04:14
Addressing this in https://codereview.chromium.org
|
| continue; |
| } |