1 : // Copyright 2013 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 : // Common unittest fixtures and utilities for the Asan runtime library.
16 :
17 : #include "syzygy/agent/asan/unittest_util.h"
18 :
19 : #include <algorithm>
20 :
21 : #include "base/bind.h"
22 : #include "base/command_line.h"
23 : #include "base/environment.h"
24 : #include "base/debug/alias.h"
25 : #include "base/process/kill.h"
26 : #include "base/process/launch.h"
27 : #include "base/strings/string_number_conversions.h"
28 : #include "base/strings/stringprintf.h"
29 : #include "base/strings/utf_string_conversions.h"
30 : #include "syzygy/agent/asan/block.h"
31 : #include "syzygy/agent/asan/error_info.h"
32 : #include "syzygy/agent/asan/rtl_impl.h"
33 : #include "syzygy/agent/asan/runtime.h"
34 : #include "syzygy/agent/common/stack_capture.h"
35 : #include "syzygy/trace/protocol/call_trace_defs.h"
36 :
37 : namespace testing {
38 :
39 : namespace {
40 :
41 : typedef agent::asan::HeapManagerInterface::HeapId HeapId;
42 :
43 : using agent::asan::BlockHeader;
44 : using agent::asan::BlockInfo;
45 : using agent::asan::BlockLayout;
46 : using agent::common::StackCapture;
47 :
48 : } // namespace
49 :
50 : const wchar_t kSyzyAsanRtlDll[] = L"syzyasan_rtl.dll";
51 : // The maximum time we're willing to wait for the logger process to get
52 : // started/killed. This is very generous, but also prevents the unittests
53 : // from hanging if the event never fires.
54 : static const size_t kLoggerTimeOutMs = 10000;
55 :
56 : namespace {
57 :
58 : FARPROC check_access_fn = NULL;
59 : bool direction_flag_forward = true;
60 :
61 : // An exception filter that grabs and sets an exception pointer, and
62 : // triggers only for access violations.
63 E : DWORD AccessViolationFilter(EXCEPTION_POINTERS* e, EXCEPTION_POINTERS** pe) {
64 E : if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
65 E : *pe = e;
66 E : return EXCEPTION_EXECUTE_HANDLER;
67 : }
68 i : return EXCEPTION_CONTINUE_SEARCH;
69 E : }
70 :
71 : // Tries to access the given address, validating whether or not an
72 : // access violation occurs.
73 i : bool TestReadAccess(void* address, bool expect_access_violation) {
74 i : uint8_t* m = reinterpret_cast<uint8_t*>(address);
75 i : ULONG_PTR p = reinterpret_cast<ULONG_PTR>(address);
76 :
77 : // Try a read.
78 i : uint8_t value = 0;
79 i : EXCEPTION_POINTERS* e = NULL;
80 i : __try {
81 i : value = m[0];
82 i : if (expect_access_violation)
83 i : return false;
84 i : }
85 i : __except(AccessViolationFilter(GetExceptionInformation(), &e)) {
86 i : if (!expect_access_violation)
87 i : return false;
88 : if (e->ExceptionRecord == NULL ||
89 i : e->ExceptionRecord->NumberParameters < 2 ||
90 : e->ExceptionRecord->ExceptionInformation[1] != p) {
91 i : return false;
92 : }
93 i : return true;
94 : }
95 :
96 : // Ensure that |value| doesn't get optimized away. If so, the attempted
97 : // read never occurs.
98 i : base::debug::Alias(&value);
99 :
100 i : return true;
101 i : }
102 :
103 : // Tries to write at the given address, validating whether or not an
104 : // access violation occurs.
105 i : bool TestWriteAccess(void* address, bool expect_access_violation) {
106 i : uint8_t* m = reinterpret_cast<uint8_t*>(address);
107 i : ULONG_PTR p = reinterpret_cast<ULONG_PTR>(address);
108 :
109 : // Try a write.
110 i : EXCEPTION_POINTERS* e = NULL;
111 i : __try {
112 i : m[0] = 0;
113 i : if (expect_access_violation)
114 i : return false;
115 i : }
116 i : __except(AccessViolationFilter(GetExceptionInformation(), &e)) {
117 i : if (!expect_access_violation)
118 i : return false;
119 : if (e->ExceptionRecord == NULL ||
120 i : e->ExceptionRecord->NumberParameters < 2 ||
121 : e->ExceptionRecord->ExceptionInformation[1] != p) {
122 i : return false;
123 : }
124 : }
125 :
126 i : return true;
127 i : }
128 :
129 : // Tries to access (read/write) at the given address, validating whether or
130 : // not an access violation occurs.
131 E : bool TestAccess(void* address, bool expect_access_violation) {
132 E : return TestReadAccess(address, expect_access_violation) &&
133 : TestWriteAccess(address, expect_access_violation);
134 E : }
135 :
136 : } // namespace
137 :
138 : MemoryAccessorTester* MemoryAccessorTester::instance_ = NULL;
139 :
140 : // Define the function pointers.
141 : #define DEFINE_FUNCTION_PTR_VARIABLE(convention, ret, name, args, argnames) \
142 : name##FunctionPtr TestAsanRtl::name##Function;
143 : ASAN_RTL_FUNCTIONS(DEFINE_FUNCTION_PTR_VARIABLE)
144 : #undef DEFINE_FUNCTION_PTR_VARIABLE
145 :
146 : // Define versions of all of the functions that expect an error to be thrown by
147 : // the AsanErrorCallback, and in turn raise an exception if the underlying
148 : // function didn't fail.
149 : #define DEFINE_FAILING_FUNCTION(convention, ret, name, args, argnames) \
150 : bool name##FunctionFailed args { \
151 : __try { \
152 : testing::TestAsanRtl::name##Function argnames; \
153 : } __except(::GetExceptionCode() == EXCEPTION_ARRAY_BOUNDS_EXCEEDED) { \
154 : return true; \
155 : } \
156 : return false; \
157 : } \
158 : void testing::TestAsanRtl::name##FunctionFailing args { \
159 : ASSERT_TRUE(name##FunctionFailed argnames); \
160 : }
161 E : ASAN_RTL_FUNCTIONS(DEFINE_FAILING_FUNCTION)
162 : #undef DEFINE_FAILING_FUNCTION
163 :
164 : TestWithAsanLogger::TestWithAsanLogger()
165 E : : logger_running_(false), log_contents_read_(false) {
166 E : }
167 :
168 E : void TestWithAsanLogger::SetUp() {
169 : // Create the log file.
170 E : ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
171 E : CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &log_file_path_));
172 :
173 : // Open files used to redirect standard in/out/err of the logger, to not
174 : // pollute the console.
175 E : logger_stdin_file_.reset(base::OpenFile(
176 : temp_dir_.path().AppendASCII("agent_logger_stdin.txt"), "w"));
177 E : CHECK(logger_stdin_file_);
178 E : logger_stdout_file_.reset(base::OpenFile(
179 : temp_dir_.path().AppendASCII("agent_logger_stdout.txt"), "w"));
180 E : CHECK(logger_stdout_file_);
181 E : logger_stderr_file_.reset(base::OpenFile(
182 : temp_dir_.path().AppendASCII("agent_logger_stderr.txt"), "w"));
183 E : CHECK(logger_stderr_file_);
184 :
185 : // Save the environment we found.
186 E : std::unique_ptr<base::Environment> env(base::Environment::Create());
187 E : env->GetVar(kSyzygyRpcInstanceIdEnvVar, &old_logger_env_);
188 :
189 : // Configure the environment (to pass the instance id to the agent DLL).
190 : // We append "-0" to the process id to avoid potential conflict with other
191 : // tests.
192 E : instance_id_ = base::UintToString16(::GetCurrentProcessId()) + L"-0";
193 E : AppendToLoggerEnv(base::StringPrintf("%ls,%ls",
194 : kSyzyAsanRtlDll,
195 : instance_id_.c_str()));
196 :
197 E : log_contents_read_ = false;
198 E : StartLogger();
199 E : }
200 :
201 E : void TestWithAsanLogger::TearDown() {
202 E : StopLogger();
203 :
204 : // Restore the environment variable as we found it.
205 E : std::unique_ptr<base::Environment> env(base::Environment::Create());
206 E : env->SetVar(kSyzygyRpcInstanceIdEnvVar, old_logger_env_);
207 E : }
208 :
209 E : bool TestWithAsanLogger::LogContains(const base::StringPiece& message) {
210 E : if (!log_contents_read_ && logger_running_) {
211 E : CHECK(base::ReadFileToString(log_file_path_, &log_contents_));
212 E : log_contents_read_ = true;
213 : }
214 E : return log_contents_.find(message.as_string()) != std::string::npos;
215 E : }
216 :
217 E : void TestWithAsanLogger::DeleteTempFileAndDirectory() {
218 E : StopLogger();
219 E : logger_stdin_file_.reset();
220 E : logger_stdout_file_.reset();
221 E : logger_stderr_file_.reset();
222 E : if (temp_dir_.IsValid())
223 E : temp_dir_.Delete();
224 E : }
225 :
226 E : void TestWithAsanLogger::StartLogger() {
227 : // Launch the logger as a separate process and make sure it succeeds.
228 E : base::CommandLine cmd_line(testing::GetExeRelativePath(L"agent_logger.exe"));
229 E : cmd_line.AppendSwitchNative("instance-id", instance_id_);
230 E : cmd_line.AppendSwitchNative("output-file", log_file_path_.value());
231 E : cmd_line.AppendSwitchNative("minidump-dir", temp_dir_.path().value());
232 E : cmd_line.AppendArgNative(L"start");
233 E : base::LaunchOptions options;
234 E : options.start_hidden = true;
235 E : options.stdin_handle = reinterpret_cast<HANDLE>(
236 : _get_osfhandle(_fileno(logger_stdin_file_.get())));
237 E : options.stdout_handle = reinterpret_cast<HANDLE>(
238 : _get_osfhandle(_fileno(logger_stdout_file_.get())));
239 E : options.stderr_handle = reinterpret_cast<HANDLE>(
240 : _get_osfhandle(_fileno(logger_stderr_file_.get())));
241 E : options.inherit_handles = true; // As per documentation.
242 E : base::Process process = base::LaunchProcess(cmd_line, options);
243 E : ASSERT_TRUE(process.IsValid());
244 :
245 : // Wait for the logger to be ready before continuing.
246 E : std::wstring event_name;
247 E : trace::agent_logger::AgentLogger::GetSyzygyAgentLoggerEventName(
248 : instance_id_, &event_name);
249 E : base::win::ScopedHandle event(
250 : ::CreateEvent(NULL, FALSE, FALSE, event_name.c_str()));
251 E : ::WaitForSingleObject(event.Get(), kLoggerTimeOutMs);
252 E : logger_running_ = true;
253 E : }
254 :
255 E : void TestWithAsanLogger::StopLogger() {
256 E : if (!logger_running_)
257 E : return;
258 : // Launch the logger as a separate process to stop it and make sure it
259 : // succeeds.
260 E : base::CommandLine cmd_line(base::FilePath(L"agent_logger.exe"));
261 E : cmd_line.AppendSwitchNative("instance-id", instance_id_);
262 E : cmd_line.AppendArgNative(L"stop");
263 E : base::LaunchOptions options;
264 E : options.start_hidden = true;
265 E : base::Process process = base::LaunchProcess(cmd_line, options);
266 E : ASSERT_TRUE(process.IsValid());
267 :
268 E : int exit_code = 0;
269 E : ASSERT_TRUE(process.WaitForExitWithTimeout(
270 E : base::TimeDelta::FromMilliseconds(kLoggerTimeOutMs), &exit_code));
271 E : logger_running_ = false;
272 E : }
273 :
274 E : void TestWithAsanLogger::ResetLog() {
275 E : StopLogger();
276 E : CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &log_file_path_));
277 E : StartLogger();
278 E : log_contents_read_ = false;
279 E : }
280 :
281 E : void TestWithAsanLogger::AppendToLoggerEnv(const std::string &instance) {
282 E : std::string instance_id;
283 E : std::unique_ptr<base::Environment> env(base::Environment::Create());
284 E : env->GetVar(kSyzygyRpcInstanceIdEnvVar, &instance_id);
285 :
286 E : instance_id.append(";");
287 E : instance_id.append(instance);
288 :
289 E : env->SetVar(kSyzygyRpcInstanceIdEnvVar, instance_id);
290 E : }
291 :
292 : FakeAsanBlock::FakeAsanBlock(Shadow* shadow,
293 : size_t alloc_alignment_log,
294 : StackCaptureCache* stack_cache)
295 E : : is_initialized(false), alloc_alignment_log(alloc_alignment_log),
296 E : alloc_alignment(1 << alloc_alignment_log), shadow_(shadow),
297 E : stack_cache(stack_cache) {
298 E : DCHECK_NE(static_cast<Shadow*>(nullptr), shadow);
299 E : DCHECK_NE(static_cast<StackCaptureCache*>(nullptr), stack_cache);
300 : // Align the beginning of the buffer to the current granularity. Ensure that
301 : // there's room to store magic bytes in front of this block.
302 E : buffer_align_begin = reinterpret_cast<uint8_t*>(
303 : common::AlignUp(reinterpret_cast<size_t>(buffer) + 1, alloc_alignment));
304 E : ::memset(&block_info, 0, sizeof(block_info));
305 E : }
306 :
307 E : FakeAsanBlock::~FakeAsanBlock() {
308 E : EXPECT_NE(0U, block_info.block_size);
309 E : shadow_->Unpoison(buffer_align_begin, block_info.block_size);
310 E : ::memset(buffer, 0, sizeof(buffer));
311 E : }
312 :
313 E : bool FakeAsanBlock::InitializeBlock(size_t alloc_size) {
314 E : BlockLayout layout = {};
315 E : EXPECT_TRUE(BlockPlanLayout(alloc_alignment,
316 : alloc_alignment,
317 : alloc_size,
318 : 0,
319 : 0,
320 E : &layout));
321 :
322 : // Initialize the Asan block.
323 E : BlockInitialize(layout, buffer_align_begin, false, &block_info);
324 E : EXPECT_NE(reinterpret_cast<void*>(NULL), block_info.body);
325 :
326 E : StackCapture stack;
327 E : stack.InitFromStack();
328 E : block_info.header->alloc_stack = stack_cache->SaveStackTrace(stack);
329 :
330 E : shadow_->PoisonAllocatedBlock(block_info);
331 E : BlockSetChecksum(block_info);
332 :
333 : // Calculate the size of the zone of the buffer that we use to ensure that
334 : // we don't corrupt the heap.
335 E : buffer_header_size = buffer_align_begin - buffer;
336 E : buffer_trailer_size = kBufferSize - buffer_header_size -
337 : block_info.block_size;
338 E : EXPECT_GT(kBufferSize, layout.block_size + buffer_header_size);
339 :
340 : // Initialize the buffer header and trailer.
341 E : ::memset(buffer, kBufferHeaderValue, buffer_header_size);
342 E : ::memset(buffer_align_begin + block_info.block_size, kBufferTrailerValue,
343 : buffer_trailer_size);
344 :
345 E : EXPECT_TRUE(common::IsAligned(reinterpret_cast<size_t>(block_info.body),
346 E : alloc_alignment));
347 E : EXPECT_TRUE(common::IsAligned(
348 : reinterpret_cast<size_t>(buffer_align_begin) + block_info.block_size,
349 E : agent::asan::kShadowRatio));
350 E : EXPECT_EQ(buffer_align_begin, block_info.RawBlock());
351 :
352 : void* expected_user_ptr = reinterpret_cast<void*>(
353 E : buffer_align_begin + std::max(sizeof(BlockHeader), alloc_alignment));
354 E : EXPECT_EQ(block_info.body, expected_user_ptr);
355 :
356 E : size_t i = 0;
357 : // Ensure that the buffer header is accessible and correctly tagged.
358 E : for (; i < buffer_header_size; ++i) {
359 E : EXPECT_EQ(kBufferHeaderValue, buffer[i]);
360 E : EXPECT_TRUE(shadow_->IsAccessible(buffer + i));
361 E : }
362 E : size_t user_block_offset = block_info.RawBody() - buffer;
363 : // Ensure that the block header isn't accessible.
364 E : for (; i < user_block_offset; ++i)
365 E : EXPECT_FALSE(shadow_->IsAccessible(buffer + i));
366 :
367 : // Ensure that the user block is accessible.
368 E : size_t block_trailer_offset = i + alloc_size;
369 E : for (; i < block_trailer_offset; ++i)
370 E : EXPECT_TRUE(shadow_->IsAccessible(buffer + i));
371 :
372 : // Ensure that the block trailer isn't accessible.
373 E : for (; i < buffer_header_size + block_info.block_size; ++i)
374 E : EXPECT_FALSE(shadow_->IsAccessible(buffer + i));
375 :
376 : // Ensure that the buffer trailer is accessible and correctly tagged.
377 E : for (; i < kBufferSize; ++i) {
378 E : EXPECT_EQ(kBufferTrailerValue, buffer[i]);
379 E : EXPECT_TRUE(shadow_->IsAccessible(buffer + i));
380 E : }
381 :
382 E : is_initialized = true;
383 E : return true;
384 E : }
385 :
386 : bool FakeAsanBlock::TestBlockMetadata() {
387 : if (!is_initialized)
388 : return false;
389 :
390 : // Ensure that the block header is valid. BlockGetHeaderFromBody takes
391 : // care of checking the magic number in the signature of the block.
392 : BlockHeader* block_header = block_info.header;
393 : EXPECT_NE(static_cast<BlockHeader*>(NULL), block_header);
394 : BlockInfo block_info = {};
395 : EXPECT_TRUE(BlockInfoFromMemory(block_header, &block_info));
396 : const uint8_t* cursor = buffer_align_begin;
397 : EXPECT_EQ(::GetCurrentThreadId(), block_info.trailer->alloc_tid);
398 : EXPECT_TRUE(block_header->alloc_stack != NULL);
399 : EXPECT_EQ(agent::asan::ALLOCATED_BLOCK, block_header->state);
400 : EXPECT_TRUE(shadow_->IsBlockStartByte(cursor++));
401 : for (; cursor < block_info.RawBody(); ++cursor)
402 : EXPECT_TRUE(shadow_->IsLeftRedzone(cursor));
403 : const uint8_t* aligned_trailer_begin =
404 : reinterpret_cast<const uint8_t*>(common::AlignUp(
405 : reinterpret_cast<size_t>(block_info.body) + block_info.body_size,
406 : agent::asan::kShadowRatio));
407 : for (const uint8_t* pos = aligned_trailer_begin;
408 : pos < buffer_align_begin + block_info.block_size; ++pos) {
409 : EXPECT_TRUE(shadow_->IsRightRedzone(pos));
410 : }
411 :
412 : return true;
413 : }
414 :
415 E : bool FakeAsanBlock::MarkBlockAsQuarantinedImpl(bool flood_filled) {
416 E : if (!is_initialized)
417 i : return false;
418 :
419 E : EXPECT_NE(static_cast<BlockHeader*>(NULL), block_info.header);
420 E : EXPECT_TRUE(block_info.header->free_stack == NULL);
421 E : EXPECT_TRUE(block_info.trailer != NULL);
422 E : EXPECT_EQ(0U, block_info.trailer->free_tid);
423 :
424 E : shadow_->MarkAsFreed(block_info.body, block_info.body_size);
425 E : StackCapture stack;
426 E : stack.InitFromStack();
427 E : block_info.header->free_stack = stack_cache->SaveStackTrace(stack);
428 E : block_info.trailer->free_tid = ::GetCurrentThreadId();
429 E : block_info.trailer->free_ticks = ::GetTickCount();
430 :
431 E : if (flood_filled) {
432 E : block_info.header->state = agent::asan::QUARANTINED_FLOODED_BLOCK;
433 E : ::memset(block_info.body, agent::asan::kBlockFloodFillByte,
434 : block_info.body_size);
435 E : } else {
436 E : block_info.header->state = agent::asan::QUARANTINED_BLOCK;
437 : }
438 :
439 E : BlockSetChecksum(block_info);
440 :
441 E : size_t i = 0;
442 : // Ensure that the buffer header is accessible and correctly tagged.
443 E : for (; i < buffer_header_size; ++i) {
444 E : EXPECT_EQ(kBufferHeaderValue, buffer[i]);
445 E : EXPECT_TRUE(shadow_->IsAccessible(buffer + i));
446 E : }
447 : // Ensure that the whole block isn't accessible.
448 E : for (; i < buffer_header_size + block_info.block_size; ++i)
449 E : EXPECT_FALSE(shadow_->IsAccessible(buffer + i));
450 :
451 : // Ensure that the buffer trailer is accessible and correctly tagged.
452 E : for (; i < kBufferSize; ++i) {
453 E : EXPECT_EQ(kBufferTrailerValue, buffer[i]);
454 E : EXPECT_TRUE(shadow_->IsAccessible(buffer + i));
455 E : }
456 E : return true;
457 E : }
458 :
459 E : bool FakeAsanBlock::MarkBlockAsQuarantined() {
460 E : return MarkBlockAsQuarantinedImpl(false);
461 E : }
462 :
463 E : bool FakeAsanBlock::MarkBlockAsQuarantinedFlooded() {
464 E : return MarkBlockAsQuarantinedImpl(true);
465 E : }
466 :
467 : namespace {
468 :
469 : #define RTL_CAPTURE_CONTEXT(context, expected_eip) { \
470 : /* Save caller save registers. */ \
471 : __asm push eax \
472 : __asm push ecx \
473 : __asm push edx \
474 : /* Call Capture context. */ \
475 : __asm push context \
476 : __asm call dword ptr[RtlCaptureContext] \
477 : /* Restore caller save registers. */ \
478 : __asm pop edx \
479 : __asm pop ecx \
480 : __asm pop eax \
481 : /* Restore registers which are stomped by RtlCaptureContext. */ \
482 : __asm push eax \
483 : __asm pushfd \
484 : __asm mov eax, context \
485 : __asm mov dword ptr[eax + CONTEXT.Ebp], ebp \
486 : __asm mov dword ptr[eax + CONTEXT.Esp], esp \
487 : /* NOTE: we need to add 8 bytes because EAX + EFLAGS are on the stack. */ \
488 : __asm add dword ptr[eax + CONTEXT.Esp], 8 \
489 : __asm mov dword ptr[eax + CONTEXT.Eip], offset expected_eip \
490 : __asm popfd \
491 : __asm pop eax \
492 : }
493 :
494 : // Check whether 2 contexts are equal.
495 : // @param c1 The first context to check.
496 : // @param c2 The second context to check.
497 : void ExpectEqualContexts(const CONTEXT& c1,
498 : const CONTEXT& c2,
499 E : bool ignore_flags) {
500 : // Segment registers.
501 E : EXPECT_EQ(static_cast<WORD>(c1.SegGs), static_cast<WORD>(c2.SegGs));
502 E : EXPECT_EQ(static_cast<WORD>(c1.SegFs), static_cast<WORD>(c2.SegFs));
503 E : EXPECT_EQ(static_cast<WORD>(c1.SegEs), static_cast<WORD>(c2.SegEs));
504 E : EXPECT_EQ(static_cast<WORD>(c1.SegDs), static_cast<WORD>(c2.SegDs));
505 :
506 : // General registers.
507 E : EXPECT_EQ(c1.Edi, c2.Edi);
508 E : EXPECT_EQ(c1.Esi, c2.Esi);
509 E : EXPECT_EQ(c1.Ebx, c2.Ebx);
510 E : EXPECT_EQ(c1.Edx, c2.Edx);
511 E : EXPECT_EQ(c1.Ecx, c2.Ecx);
512 E : EXPECT_EQ(c1.Eax, c2.Eax);
513 :
514 : // "Control" registers.
515 E : EXPECT_EQ(c1.Ebp, c2.Ebp);
516 E : EXPECT_EQ(c1.Eip, c2.Eip);
517 E : EXPECT_EQ(static_cast<WORD>(c1.SegCs), static_cast<WORD>(c2.SegCs));
518 E : if (!ignore_flags)
519 E : EXPECT_EQ(c1.EFlags, c2.EFlags);
520 E : EXPECT_EQ(c1.Esp, c2.Esp);
521 E : EXPECT_EQ(static_cast<WORD>(c1.SegSs), static_cast<WORD>(c2.SegSs));
522 E : }
523 :
524 : } // namespace
525 :
526 : MemoryAccessorTester::MemoryAccessorTester()
527 E : : expected_error_type_(agent::asan::UNKNOWN_BAD_ACCESS),
528 E : memory_error_detected_(false),
529 E : ignore_flags_(false) {
530 E : EXPECT_EQ(static_cast<MemoryAccessorTester*>(NULL), instance_);
531 :
532 E : Initialize();
533 E : instance_ = this;
534 E : }
535 :
536 : MemoryAccessorTester::MemoryAccessorTester(IgnoreFlags /* ignore_flags */)
537 E : : expected_error_type_(agent::asan::UNKNOWN_BAD_ACCESS),
538 E : memory_error_detected_(false),
539 E : ignore_flags_(true) {
540 E : EXPECT_EQ(static_cast<MemoryAccessorTester*>(NULL), instance_);
541 :
542 E : Initialize();
543 E : instance_ = this;
544 E : }
545 :
546 E : MemoryAccessorTester::~MemoryAccessorTester() {
547 E : EXPECT_EQ(this, instance_);
548 E : instance_ = NULL;
549 E : }
550 :
551 E : void MemoryAccessorTester::Initialize() {
552 E : ::memset(&context_before_hook_, 0xCD, sizeof(context_before_hook_));
553 E : ::memset(&context_after_hook_, 0xCE, sizeof(context_after_hook_));
554 E : ::memset(&error_context_, 0xCF, sizeof(error_context_));
555 E : ::memset(&last_error_info_, 0, sizeof(last_error_info_));
556 E : }
557 :
558 : namespace {
559 :
560 : void CheckAccessAndCaptureContexts(
561 i : CONTEXT* before, CONTEXT* after, void* location) {
562 : __asm {
563 i : pushad
564 i : pushfd
565 :
566 : // Avoid undefined behavior by forcing values.
567 i : mov eax, 0x01234567
568 i : mov ebx, 0x70123456
569 i : mov ecx, 0x12345678
570 i : mov edx, 0x56701234
571 i : mov esi, 0xCCAACCAA
572 i : mov edi, 0xAACCAACC
573 :
574 i : RTL_CAPTURE_CONTEXT(before, check_access_expected_eip)
575 :
576 : // Push EDX as we're required to do by the custom calling convention.
577 i : push edx
578 : // Ptr is the pointer to check.
579 i : mov edx, location
580 : // Call through.
581 i : call dword ptr[check_access_fn + 0]
582 : check_access_expected_eip:
583 :
584 i : RTL_CAPTURE_CONTEXT(after, check_access_expected_eip)
585 :
586 i : popfd
587 i : popad
588 : }
589 i : }
590 :
591 : } // namespace
592 :
593 : void MemoryAccessorTester::CheckAccessAndCompareContexts(
594 E : FARPROC access_fn, void* ptr) {
595 E : memory_error_detected_ = false;
596 :
597 E : check_access_fn = access_fn;
598 :
599 E : CheckAccessAndCaptureContexts(
600 : &context_before_hook_, &context_after_hook_, ptr);
601 :
602 E : ExpectEqualContexts(context_before_hook_,
603 : context_after_hook_,
604 : ignore_flags_);
605 E : if (memory_error_detected_) {
606 E : ExpectEqualContexts(context_before_hook_,
607 : error_context_,
608 : ignore_flags_);
609 : }
610 :
611 E : check_access_fn = NULL;
612 E : }
613 :
614 : namespace {
615 :
616 : void CheckSpecialAccess(CONTEXT* before, CONTEXT* after,
617 i : void* dst, void* src, int len) {
618 : __asm {
619 i : pushad
620 i : pushfd
621 :
622 : // Override the direction flag.
623 i : cld
624 i : cmp direction_flag_forward, 0
625 i : jne skip_reverse_direction
626 i : std
627 : skip_reverse_direction:
628 :
629 : // Avoid undefined behavior by forcing values.
630 i : mov eax, 0x01234567
631 i : mov ebx, 0x70123456
632 i : mov edx, 0x56701234
633 :
634 : // Setup registers used by the special instruction.
635 i : mov ecx, len
636 i : mov esi, src
637 i : mov edi, dst
638 :
639 i : RTL_CAPTURE_CONTEXT(before, special_access_expected_eip)
640 :
641 : // Call through.
642 i : call dword ptr[check_access_fn + 0]
643 : special_access_expected_eip:
644 :
645 i : RTL_CAPTURE_CONTEXT(after, special_access_expected_eip)
646 :
647 i : popfd
648 i : popad
649 : }
650 i : }
651 :
652 : } // namespace
653 :
654 : void MemoryAccessorTester::CheckSpecialAccessAndCompareContexts(
655 : FARPROC access_fn, StringOperationDirection direction,
656 E : void* dst, void* src, int len) {
657 E : memory_error_detected_ = false;
658 :
659 E : direction_flag_forward = (direction == DIRECTION_FORWARD);
660 E : check_access_fn = access_fn;
661 :
662 E : CheckSpecialAccess(
663 : &context_before_hook_, &context_after_hook_, dst, src, len);
664 :
665 E : ExpectEqualContexts(context_before_hook_,
666 : context_after_hook_,
667 : ignore_flags_);
668 E : if (memory_error_detected_) {
669 E : ExpectEqualContexts(context_before_hook_,
670 : error_context_,
671 : ignore_flags_);
672 : }
673 :
674 E : check_access_fn = NULL;
675 E : }
676 :
677 E : void MemoryAccessorTester::AsanErrorCallbackImpl(AsanErrorInfo* error_info) {
678 : // TODO(sebmarchand): Stash the error info in a fixture-static variable and
679 : // assert on specific conditions after the fact.
680 E : EXPECT_NE(reinterpret_cast<AsanErrorInfo*>(NULL), error_info);
681 E : EXPECT_NE(agent::asan::UNKNOWN_BAD_ACCESS, error_info->error_type);
682 :
683 E : EXPECT_EQ(expected_error_type_, error_info->error_type);
684 E : if (error_info->error_type >= agent::asan::USE_AFTER_FREE) {
685 : // We should at least have the stack trace of the allocation of this block.
686 E : EXPECT_GT(error_info->block_info.alloc_stack_size, 0U);
687 E : EXPECT_NE(0U, error_info->block_info.alloc_tid);
688 E : if (error_info->error_type == agent::asan::USE_AFTER_FREE ||
689 : error_info->error_type == agent::asan::DOUBLE_FREE) {
690 E : EXPECT_GT(error_info->block_info.free_stack_size, 0U);
691 E : EXPECT_NE(0U, error_info->block_info.free_tid);
692 E : } else {
693 E : EXPECT_EQ(error_info->block_info.free_stack_size, 0U);
694 E : EXPECT_EQ(0U, error_info->block_info.free_tid);
695 : }
696 : }
697 :
698 E : if (error_info->error_type == agent::asan::HEAP_BUFFER_OVERFLOW) {
699 E : EXPECT_TRUE(strstr(error_info->shadow_info, "beyond") != NULL);
700 E : } else if (error_info->error_type == agent::asan::HEAP_BUFFER_UNDERFLOW) {
701 E : EXPECT_TRUE(strstr(error_info->shadow_info, "before") != NULL);
702 : }
703 :
704 E : memory_error_detected_ = true;
705 E : last_error_info_ = *error_info;
706 :
707 : // Copy the corrupt range's information.
708 E : if (error_info->heap_is_corrupt) {
709 E : EXPECT_GE(1U, error_info->corrupt_range_count);
710 E : for (size_t i = 0; i < error_info->corrupt_range_count; ++i) {
711 E : last_corrupt_ranges_.push_back(CorruptRangeInfo());
712 E : CorruptRangeInfo* range_info = &last_corrupt_ranges_.back();
713 E : range_info->first = error_info->corrupt_ranges[i];
714 E : AsanBlockInfoVector* block_infos = &range_info->second;
715 E : for (size_t j = 0; j < range_info->first.block_info_count; ++j) {
716 E : agent::asan::AsanBlockInfo block_info = range_info->first.block_info[j];
717 E : for (size_t k = 0;
718 E : k < range_info->first.block_info[j].alloc_stack_size;
719 E : ++k) {
720 E : block_info.alloc_stack[k] =
721 : range_info->first.block_info[j].alloc_stack[k];
722 E : }
723 E : for (size_t k = 0;
724 E : k < range_info->first.block_info[j].free_stack_size;
725 i : ++k) {
726 i : block_info.free_stack[k] =
727 : range_info->first.block_info[j].free_stack[k];
728 i : }
729 E : block_infos->push_back(block_info);
730 E : }
731 E : }
732 : }
733 :
734 E : error_context_ = error_info->context;
735 E : }
736 :
737 E : void MemoryAccessorTester::AsanErrorCallback(AsanErrorInfo* error_info) {
738 E : ASSERT_NE(reinterpret_cast<MemoryAccessorTester*>(NULL), instance_);
739 :
740 E : instance_->AsanErrorCallbackImpl(error_info);
741 E : }
742 :
743 : void MemoryAccessorTester::AssertMemoryErrorIsDetected(
744 E : FARPROC access_fn, void* ptr, BadAccessKind bad_access_type) {
745 E : expected_error_type_ = bad_access_type;
746 E : CheckAccessAndCompareContexts(access_fn, ptr);
747 E : ASSERT_TRUE(memory_error_detected_);
748 E : }
749 :
750 : void MemoryAccessorTester::ExpectSpecialMemoryErrorIsDetected(
751 : FARPROC access_fn,
752 : StringOperationDirection direction,
753 : bool expect_error,
754 : void* dst,
755 : void* src,
756 : int32_t length,
757 E : BadAccessKind bad_access_type) {
758 E : DCHECK(dst != NULL);
759 E : DCHECK(src != NULL);
760 E : ASSERT_TRUE(check_access_fn == NULL);
761 :
762 E : expected_error_type_ = bad_access_type;
763 :
764 : // Perform memory accesses inside the range.
765 E : ASSERT_NO_FATAL_FAILURE(
766 : CheckSpecialAccessAndCompareContexts(
767 E : access_fn, direction, dst, src, length));
768 :
769 E : EXPECT_EQ(expect_error, memory_error_detected_);
770 E : check_access_fn = NULL;
771 E : }
772 :
773 : TestMemoryInterceptors::TestMemoryInterceptors()
774 E : : heap_(NULL), src_(NULL), dst_(NULL) {
775 E : }
776 :
777 E : void TestMemoryInterceptors::SetUp() {
778 E : testing::TestWithAsanLogger::SetUp();
779 :
780 : // Make sure the logging routes to our instance.
781 E : AppendToLoggerEnv(base::StringPrintf("syzyasan_rtl_unittests.exe,%u",
782 : ::GetCurrentProcessId()));
783 :
784 E : asan_runtime_.SetUp(std::wstring());
785 :
786 : // Heap checking on error is expensive, so turn it down here.
787 E : asan_runtime_.params().check_heap_on_failure = false;
788 :
789 E : agent::asan::SetUpRtl(&asan_runtime_);
790 :
791 E : asan_runtime_.SetErrorCallBack(
792 : base::Bind(testing::MemoryAccessorTester::AsanErrorCallback));
793 E : heap_ = asan_HeapCreate(0, 0, 0);
794 E : ASSERT_TRUE(heap_ != NULL);
795 :
796 E : src_ = reinterpret_cast<byte*>(asan_HeapAlloc(heap_, 0, kAllocSize));
797 E : dst_ = reinterpret_cast<byte*>(asan_HeapAlloc(heap_, 0, kAllocSize));
798 E : ASSERT_TRUE(src_ && dst_);
799 :
800 : // String instructions may compare memory contents and bail early on
801 : // differences, so fill the buffers to make sure the checks go the full
802 : // distance.
803 E : ::memset(src_, 0xFF, kAllocSize);
804 E : ::memset(dst_, 0xFF, kAllocSize);
805 E : }
806 :
807 E : void TestMemoryInterceptors::TearDown() {
808 E : if (heap_ != NULL) {
809 E : asan_HeapFree(heap_, 0, src_);
810 E : asan_HeapFree(heap_, 0, dst_);
811 :
812 E : asan_HeapDestroy(heap_);
813 E : heap_ = NULL;
814 : }
815 E : agent::asan::TearDownRtl();
816 E : asan_runtime_.TearDown();
817 E : testing::TestWithAsanLogger::TearDown();
818 E : }
819 :
820 : void TestMemoryInterceptors::TestValidAccess(
821 E : const InterceptFunction* fns, size_t num_fns) {
822 E : for (size_t i = 0; i < num_fns; ++i) {
823 E : const InterceptFunction& fn = fns[i];
824 :
825 E : MemoryAccessorTester tester;
826 E : tester.CheckAccessAndCompareContexts(
827 : reinterpret_cast<FARPROC>(fn.function), src_);
828 :
829 E : ASSERT_FALSE(tester.memory_error_detected());
830 E : }
831 E : }
832 :
833 : void TestMemoryInterceptors::TestValidAccessIgnoreFlags(
834 E : const InterceptFunction* fns, size_t num_fns) {
835 E : for (size_t i = 0; i < num_fns; ++i) {
836 E : const InterceptFunction& fn = fns[i];
837 :
838 E : MemoryAccessorTester tester(MemoryAccessorTester::IGNORE_FLAGS);
839 E : tester.CheckAccessAndCompareContexts(
840 : reinterpret_cast<FARPROC>(fn.function), src_);
841 :
842 E : ASSERT_FALSE(tester.memory_error_detected());
843 E : }
844 E : }
845 :
846 : void TestMemoryInterceptors::TestOverrunAccess(
847 E : const InterceptFunction* fns, size_t num_fns) {
848 E : for (size_t i = 0; i < num_fns; ++i) {
849 E : const InterceptFunction& fn = fns[i];
850 :
851 E : MemoryAccessorTester tester;
852 E : tester.AssertMemoryErrorIsDetected(
853 : reinterpret_cast<FARPROC>(fn.function),
854 : src_ + kAllocSize,
855 : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
856 :
857 E : ASSERT_TRUE(tester.memory_error_detected());
858 E : }
859 E : }
860 :
861 : void TestMemoryInterceptors::TestOverrunAccessIgnoreFlags(
862 E : const InterceptFunction* fns, size_t num_fns) {
863 E : for (size_t i = 0; i < num_fns; ++i) {
864 E : const InterceptFunction& fn = fns[i];
865 :
866 E : MemoryAccessorTester tester(MemoryAccessorTester::IGNORE_FLAGS);
867 E : tester.AssertMemoryErrorIsDetected(
868 : reinterpret_cast<FARPROC>(fn.function),
869 : src_ + kAllocSize,
870 : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
871 :
872 E : ASSERT_TRUE(tester.memory_error_detected());
873 E : }
874 E : }
875 :
876 : void TestMemoryInterceptors::TestUnderrunAccess(
877 E : const InterceptFunction* fns, size_t num_fns) {
878 E : for (size_t i = 0; i < num_fns; ++i) {
879 E : const InterceptFunction& fn = fns[i];
880 :
881 : // TODO(someone): the 32 byte access checker does not fire on 32 byte
882 : // underrun. I guess the checkers test a single shadow byte at most
883 : // whereas it'd be more correct for access checkers to test as many
884 : // shadow bytes as is appropriate for the range of memory they touch.
885 E : MemoryAccessorTester tester;
886 E : tester.AssertMemoryErrorIsDetected(
887 : reinterpret_cast<FARPROC>(fn.function),
888 : src_ - 8,
889 : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_UNDERFLOW);
890 :
891 E : ASSERT_TRUE(tester.memory_error_detected());
892 E : }
893 E : }
894 :
895 : void TestMemoryInterceptors::TestUnderrunAccessIgnoreFlags(
896 E : const InterceptFunction* fns, size_t num_fns) {
897 E : for (size_t i = 0; i < num_fns; ++i) {
898 E : const InterceptFunction& fn = fns[i];
899 :
900 : // TODO(someone): the 32 byte access checker does not fire on 32 byte
901 : // underrun. I guess the checkers test a single shadow byte at most
902 : // whereas it'd be more correct for access checkers to test as many
903 : // shadow bytes as is appropriate for the range of memory they touch.
904 E : MemoryAccessorTester tester(MemoryAccessorTester::IGNORE_FLAGS);
905 E : tester.AssertMemoryErrorIsDetected(
906 : reinterpret_cast<FARPROC>(fn.function),
907 : src_ - 8,
908 : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_UNDERFLOW);
909 :
910 E : ASSERT_TRUE(tester.memory_error_detected());
911 E : }
912 E : }
913 :
914 : void TestMemoryInterceptors::TestStringValidAccess(
915 E : const StringInterceptFunction* fns, size_t num_fns) {
916 E : for (size_t i = 0; i < num_fns; ++i) {
917 E : const StringInterceptFunction& fn = fns[i];
918 :
919 E : MemoryAccessorTester tester;
920 E : tester.CheckSpecialAccessAndCompareContexts(
921 : reinterpret_cast<FARPROC>(fn.function),
922 : MemoryAccessorTester::DIRECTION_FORWARD,
923 : dst_, src_, kAllocSize / fn.size);
924 E : ASSERT_FALSE(tester.memory_error_detected());
925 :
926 E : tester.CheckSpecialAccessAndCompareContexts(
927 : reinterpret_cast<FARPROC>(fn.function),
928 : MemoryAccessorTester::DIRECTION_BACKWARD,
929 : dst_ + kAllocSize - fn.size, src_ + kAllocSize - fn.size,
930 : kAllocSize / fn.size);
931 :
932 E : ASSERT_FALSE(tester.memory_error_detected());
933 E : }
934 E : }
935 :
936 : void TestMemoryInterceptors::TestStringOverrunAccess(
937 E : const StringInterceptFunction* fns, size_t num_fns) {
938 E : for (size_t i = 0; i < num_fns; ++i) {
939 E : const StringInterceptFunction& fn = fns[i];
940 :
941 E : MemoryAccessorTester tester;
942 E : size_t oob_len = 0;
943 E : byte* oob_dst = NULL;
944 E : byte* oob_src = NULL;
945 :
946 : // Half the string function intercepts are for rep-prefixed instructions,
947 : // which count on "ecx", and the other half is for non-prefixed
948 : // instructions that always perform a single access.
949 : // Compute appropriate pointers for both variants, forwards.
950 E : if (fn.uses_counter) {
951 E : oob_len = kAllocSize / fn.size;
952 E : oob_dst = dst_ + fn.size;
953 E : oob_src = src_ + fn.size;
954 E : } else {
955 E : oob_len = 1;
956 E : oob_dst = dst_ + kAllocSize;
957 E : oob_src = src_ + kAllocSize;
958 : }
959 :
960 E : ASSERT_NE(agent::asan::ASAN_UNKNOWN_ACCESS, fn.dst_access_mode);
961 : // Overflow on dst forwards.
962 E : tester.ExpectSpecialMemoryErrorIsDetected(
963 : reinterpret_cast<FARPROC>(fn.function),
964 : MemoryAccessorTester::DIRECTION_FORWARD, true,
965 : oob_dst, src_, oob_len,
966 : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
967 :
968 E : if (fn.src_access_mode != agent::asan::ASAN_UNKNOWN_ACCESS) {
969 : // Overflow on src forwards.
970 E : tester.ExpectSpecialMemoryErrorIsDetected(
971 : reinterpret_cast<FARPROC>(fn.function),
972 : MemoryAccessorTester::DIRECTION_FORWARD, true,
973 : dst_, oob_src, oob_len,
974 : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
975 : }
976 :
977 : // Compute appropriate pointers for both variants, backwards.
978 E : if (fn.uses_counter) {
979 E : oob_len = kAllocSize / fn.size;
980 E : } else {
981 E : oob_len = 1;
982 : }
983 :
984 E : oob_dst = dst_ + kAllocSize;
985 E : oob_src = src_ + kAllocSize;
986 :
987 E : ASSERT_NE(agent::asan::ASAN_UNKNOWN_ACCESS, fn.dst_access_mode);
988 : // Overflow on dst backwards.
989 E : tester.ExpectSpecialMemoryErrorIsDetected(
990 : reinterpret_cast<FARPROC>(fn.function),
991 : MemoryAccessorTester::DIRECTION_BACKWARD, true,
992 : oob_dst, src_ + kAllocSize - fn.size, oob_len,
993 : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
994 :
995 E : if (fn.src_access_mode != agent::asan::ASAN_UNKNOWN_ACCESS) {
996 : // Overflow on src backwards.
997 E : tester.ExpectSpecialMemoryErrorIsDetected(
998 : reinterpret_cast<FARPROC>(fn.function),
999 : MemoryAccessorTester::DIRECTION_BACKWARD, true,
1000 : dst_ + kAllocSize - fn.size, oob_dst, oob_len,
1001 : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
1002 : }
1003 E : }
1004 E : }
1005 :
1006 E : bool IsAccessible(void* address) {
1007 E : return testing::TestAccess(address, false);
1008 E : }
1009 :
1010 E : bool IsNotAccessible(void* address) {
1011 E : return testing::TestAccess(address, true);
1012 E : }
1013 :
1014 : DebugShadow::Metadata::Metadata()
1015 : : address(nullptr), size(0),
1016 : marker(agent::asan::kHeapAddressableMarker) {
1017 : }
1018 :
1019 : DebugShadow::Metadata::Metadata(
1020 : const void* address, size_t size, ShadowMarker marker)
1021 : : address(address), size(size), marker(marker) {
1022 : stack_capture.InitFromStack();
1023 : }
1024 :
1025 : DebugShadow::Metadata::Metadata(const Metadata& rhs)
1026 : : address(rhs.address), size(rhs.size), marker(rhs.marker) {
1027 : if (rhs.stack_capture.num_frames() > 0) {
1028 : stack_capture.InitFromExistingStack(rhs.stack_capture);
1029 : }
1030 : }
1031 :
1032 : DebugShadow::Metadata& DebugShadow::Metadata::operator=(const Metadata& rhs) {
1033 : address = rhs.address;
1034 : size = rhs.size;
1035 : marker = rhs.marker;
1036 : if (rhs.stack_capture.num_frames() > 0) {
1037 : stack_capture.InitFromExistingStack(rhs.stack_capture);
1038 : }
1039 : return *this;
1040 : }
1041 :
1042 : void DebugShadow::SetShadowMemory(
1043 : const void* address, size_t length, ShadowMarker marker) {
1044 : ClearIntersection(address, length);
1045 : if (marker != agent::asan::kHeapAddressableMarker) {
1046 : Range range(reinterpret_cast<uintptr_t>(address), length);
1047 : Metadata data(address, length, marker);
1048 :
1049 : ShadowAddressSpace::RangeMapIter it;
1050 : CHECK(shadow_address_space_.Insert(range, data, &it));
1051 :
1052 : // If this is memory being returned to a reserved pool, then potentially
1053 : // merge with neighboring such ranges. This keeps the address space as
1054 : // human legible as possible.
1055 : if (marker == agent::asan::kAsanReservedMarker) {
1056 : auto it1 = it;
1057 : auto it2 = it;
1058 : bool merge = false;
1059 : Metadata data = it->second;
1060 :
1061 : // Check to see if there's a range to the left, and if it needs to be
1062 : // merged.
1063 : if (it != shadow_address_space_.begin()) {
1064 : it1--;
1065 : if (it1->first.end() == it->first.start() &&
1066 : it1->second.marker == it->second.marker) {
1067 : merge = true;
1068 : if (it1->second.size >= data.size)
1069 : data = it1->second;
1070 : } else {
1071 : ++it1;
1072 : }
1073 : }
1074 :
1075 : // Check to see if there's a range to the right, and if it needs to be
1076 : // merged.
1077 : ++it2;
1078 : if (it2 != shadow_address_space_.end()) {
1079 : if (it->first.end() == it2->first.start() &&
1080 : it->second.marker == it2->second.marker) {
1081 : merge = true;
1082 : if (it2->second.size > data.size)
1083 : data = it2->second;
1084 : } else {
1085 : --it2;
1086 : }
1087 : } else {
1088 : --it2;
1089 : }
1090 :
1091 : if (merge) {
1092 : Range range(it1->first.start(),
1093 : it2->first.end() - it1->first.start());
1094 : CHECK(shadow_address_space_.SubsumeInsert(range, data));
1095 : }
1096 : }
1097 : }
1098 : }
1099 :
1100 : void DebugShadow::GetPointerAndSizeImpl(
1101 : void const** self, size_t* size) const {
1102 : DCHECK_NE(static_cast<void**>(nullptr), self);
1103 : DCHECK_NE(static_cast<size_t*>(nullptr), size);
1104 : *self = this;
1105 : *size = sizeof(*this);
1106 : }
1107 :
1108 : void DebugShadow::ClearIntersection(const void* addr, size_t size) {
1109 : uintptr_t start = reinterpret_cast<uintptr_t>(addr);
1110 :
1111 : auto range = Range(reinterpret_cast<uintptr_t>(addr), size);
1112 : ShadowAddressSpace::RangeMapIterPair iter_pair =
1113 : shadow_address_space_.FindIntersecting(range);
1114 :
1115 : bool reinsert_head_range = false;
1116 : Range head_range;
1117 : Metadata head_data;
1118 :
1119 : bool reinsert_tail_range = false;
1120 : Range tail_range;
1121 : Metadata tail_data;
1122 :
1123 : // If the range is non-empty then remember the portion of the head and tail
1124 : // ranges to be reinserted, if any.
1125 : if (iter_pair.first != iter_pair.second) {
1126 : auto it = iter_pair.first;
1127 : if (it->first.start() < start) {
1128 : reinsert_head_range = true;
1129 : head_range = Range(
1130 : it->first.start(),
1131 : start - it->first.start());
1132 : head_data = it->second;
1133 : }
1134 :
1135 : it = iter_pair.second;
1136 : --it;
1137 : if (start + size < it->first.end()) {
1138 : reinsert_tail_range = true;
1139 : tail_range = Range(
1140 : range.end(),
1141 : it->first.end() - range.end());
1142 : tail_data = it->second;
1143 : }
1144 : }
1145 :
1146 : // Delete the entire range.
1147 : shadow_address_space_.Remove(iter_pair);
1148 : if (reinsert_head_range)
1149 : CHECK(shadow_address_space_.Insert(head_range, head_data));
1150 : if (reinsert_tail_range)
1151 : CHECK(shadow_address_space_.Insert(tail_range, tail_data));
1152 : }
1153 :
1154 : } // namespace testing
|