Index: syzygy/agent/asan/shadow.cc |
diff --git a/syzygy/agent/asan/shadow.cc b/syzygy/agent/asan/shadow.cc |
index b397d5db0dd0fc6b70da2c376a536221da733d4f..575cc3e56f71e47759a31ac091271a597409b4eb 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) { |
@@ -215,7 +216,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 +285,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 +885,23 @@ bool Shadow::ScanLeftForBracketingBlockStart( |
size_t left = cursor; |
int nesting_depth = static_cast<int>(initial_nesting_depth); |
+ |
+ MEMORY_BASIC_INFORMATION memory_info = {}; |
+ SIZE_T ret = |
+ ::VirtualQuery(&shadow_[left], &memory_info, sizeof(memory_info)); |
+ DCHECK_GT(ret, 0u); |
+ if (memory_info.State != MEM_COMMIT) |
+ return false; |
+ |
if (ShadowMarkerHelper::IsBlockEnd(shadow_[left])) |
--nesting_depth; |
while (true) { |
+ if (&shadow_[left] < static_cast<const uint8_t*>(memory_info.BaseAddress)) { |
+ ret = ::VirtualQuery(&shadow_[left], &memory_info, sizeof(memory_info)); |
+ DCHECK_GT(ret, 0u); |
+ if (memory_info.State != MEM_COMMIT) |
+ return false; |
+ } |
if (ShadowMarkerHelper::IsBlockStart(shadow_[left])) { |
if (nesting_depth == 0) { |
*location = left; |
@@ -1107,7 +1122,7 @@ ShadowWalker::ShadowWalker(const Shadow* shadow, |
upper_index_++; |
DCHECK_LE(lower_index_, upper_index_); |
- DCHECK_GE(shadow->length(), upper_index_); |
+ DCHECK_GE(shadow->length(), upper_index_ - lower_index_); |
Reset(); |
} |
@@ -1141,7 +1156,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; |
continue; |
} |