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* m = reinterpret_cast<uint8*>(address);
75 i : ULONG_PTR p = reinterpret_cast<ULONG_PTR>(address);
76 :
77 : // Try a read.
78 i : uint8 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 : e->ExceptionRecord->NumberParameters < 2 ||
90 i : e->ExceptionRecord->ExceptionInformation[1] != p) {
91 i : return false;
92 : }
93 i : return true;
94 i : }
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* m = reinterpret_cast<uint8*>(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 : e->ExceptionRecord->NumberParameters < 2 ||
121 i : e->ExceptionRecord->ExceptionInformation[1] != p) {
122 i : return false;
123 : }
124 i : }
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 : return TestReadAccess(address, expect_access_violation) &&
133 E : 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 : logger_stdin_file_.reset(base::OpenFile(
176 E : temp_dir_.path().AppendASCII("agent_logger_stdin.txt"), "w"));
177 E : CHECK(logger_stdin_file_);
178 : logger_stdout_file_.reset(base::OpenFile(
179 E : temp_dir_.path().AppendASCII("agent_logger_stdout.txt"), "w"));
180 E : CHECK(logger_stdout_file_);
181 : logger_stderr_file_.reset(base::OpenFile(
182 E : temp_dir_.path().AppendASCII("agent_logger_stderr.txt"), "w"));
183 E : CHECK(logger_stderr_file_);
184 :
185 : // Save the environment we found.
186 E : scoped_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 : AppendToLoggerEnv(base::StringPrintf("%ls,%ls",
194 : kSyzyAsanRtlDll,
195 E : 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 : scoped_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 : options.stdin_handle = reinterpret_cast<HANDLE>(
236 E : _get_osfhandle(_fileno(logger_stdin_file_.get())));
237 : options.stdout_handle = reinterpret_cast<HANDLE>(
238 E : _get_osfhandle(_fileno(logger_stdout_file_.get())));
239 : options.stderr_handle = reinterpret_cast<HANDLE>(
240 E : _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 : trace::agent_logger::AgentLogger::GetSyzygyAgentLoggerEventName(
248 E : instance_id_, &event_name);
249 : base::win::ScopedHandle event(
250 E : ::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 : 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 : scoped_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 : : is_initialized(false), alloc_alignment_log(alloc_alignment_log),
296 : 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 : buffer_align_begin = reinterpret_cast<uint8*>(common::AlignUp(
303 E : 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 : 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 : buffer_trailer_size = kBufferSize - buffer_header_size -
337 E : 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 : ::memset(buffer_align_begin + block_info.block_size, kBufferTrailerValue,
343 E : buffer_trailer_size);
344 :
345 : EXPECT_TRUE(common::IsAligned(reinterpret_cast<size_t>(block_info.body),
346 E : alloc_alignment));
347 : 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* 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* aligned_trailer_begin = reinterpret_cast<const uint8*>(
404 : common::AlignUp(reinterpret_cast<size_t>(block_info.body) +
405 : block_info.body_size,
406 : agent::asan::kShadowRatio));
407 : for (const uint8* pos = aligned_trailer_begin;
408 : pos < buffer_align_begin + block_info.block_size;
409 : ++pos) {
410 : EXPECT_TRUE(shadow_->IsRightRedzone(pos));
411 : }
412 :
413 : return true;
414 : }
415 :
416 E : bool FakeAsanBlock::MarkBlockAsQuarantinedImpl(bool flood_filled) {
417 E : if (!is_initialized)
418 i : return false;
419 :
420 E : EXPECT_NE(static_cast<BlockHeader*>(NULL), block_info.header);
421 E : EXPECT_TRUE(block_info.header->free_stack == NULL);
422 E : EXPECT_TRUE(block_info.trailer != NULL);
423 E : EXPECT_EQ(0U, block_info.trailer->free_tid);
424 :
425 E : shadow_->MarkAsFreed(block_info.body, block_info.body_size);
426 E : StackCapture stack;
427 E : stack.InitFromStack();
428 E : block_info.header->free_stack = stack_cache->SaveStackTrace(stack);
429 E : block_info.trailer->free_tid = ::GetCurrentThreadId();
430 E : block_info.trailer->free_ticks = ::GetTickCount();
431 :
432 E : if (flood_filled) {
433 E : block_info.header->state = agent::asan::QUARANTINED_FLOODED_BLOCK;
434 : ::memset(block_info.body, agent::asan::kBlockFloodFillByte,
435 E : block_info.body_size);
436 E : } else {
437 E : block_info.header->state = agent::asan::QUARANTINED_BLOCK;
438 : }
439 :
440 E : BlockSetChecksum(block_info);
441 :
442 E : size_t i = 0;
443 : // Ensure that the buffer header is accessible and correctly tagged.
444 E : for (; i < buffer_header_size; ++i) {
445 E : EXPECT_EQ(kBufferHeaderValue, buffer[i]);
446 E : EXPECT_TRUE(shadow_->IsAccessible(buffer + i));
447 E : }
448 : // Ensure that the whole block isn't accessible.
449 E : for (; i < buffer_header_size + block_info.block_size; ++i)
450 E : EXPECT_FALSE(shadow_->IsAccessible(buffer + i));
451 :
452 : // Ensure that the buffer trailer is accessible and correctly tagged.
453 E : for (; i < kBufferSize; ++i) {
454 E : EXPECT_EQ(kBufferTrailerValue, buffer[i]);
455 E : EXPECT_TRUE(shadow_->IsAccessible(buffer + i));
456 E : }
457 E : return true;
458 E : }
459 :
460 E : bool FakeAsanBlock::MarkBlockAsQuarantined() {
461 E : return MarkBlockAsQuarantinedImpl(false);
462 E : }
463 :
464 E : bool FakeAsanBlock::MarkBlockAsQuarantinedFlooded() {
465 E : return MarkBlockAsQuarantinedImpl(true);
466 E : }
467 :
468 : namespace {
469 :
470 : #define RTL_CAPTURE_CONTEXT(context, expected_eip) { \
471 : /* Save caller save registers. */ \
472 : __asm push eax \
473 : __asm push ecx \
474 : __asm push edx \
475 : /* Call Capture context. */ \
476 : __asm push context \
477 : __asm call dword ptr[RtlCaptureContext] \
478 : /* Restore caller save registers. */ \
479 : __asm pop edx \
480 : __asm pop ecx \
481 : __asm pop eax \
482 : /* Restore registers which are stomped by RtlCaptureContext. */ \
483 : __asm push eax \
484 : __asm pushfd \
485 : __asm mov eax, context \
486 : __asm mov dword ptr[eax + CONTEXT.Ebp], ebp \
487 : __asm mov dword ptr[eax + CONTEXT.Esp], esp \
488 : /* NOTE: we need to add 8 bytes because EAX + EFLAGS are on the stack. */ \
489 : __asm add dword ptr[eax + CONTEXT.Esp], 8 \
490 : __asm mov dword ptr[eax + CONTEXT.Eip], offset expected_eip \
491 : __asm popfd \
492 : __asm pop eax \
493 : }
494 :
495 : // Check whether 2 contexts are equal.
496 : // @param c1 The first context to check.
497 : // @param c2 The second context to check.
498 : void ExpectEqualContexts(const CONTEXT& c1,
499 : const CONTEXT& c2,
500 E : bool ignore_flags) {
501 : // Segment registers.
502 E : EXPECT_EQ(static_cast<WORD>(c1.SegGs), static_cast<WORD>(c2.SegGs));
503 E : EXPECT_EQ(static_cast<WORD>(c1.SegFs), static_cast<WORD>(c2.SegFs));
504 E : EXPECT_EQ(static_cast<WORD>(c1.SegEs), static_cast<WORD>(c2.SegEs));
505 E : EXPECT_EQ(static_cast<WORD>(c1.SegDs), static_cast<WORD>(c2.SegDs));
506 :
507 : // General registers.
508 E : EXPECT_EQ(c1.Edi, c2.Edi);
509 E : EXPECT_EQ(c1.Esi, c2.Esi);
510 E : EXPECT_EQ(c1.Ebx, c2.Ebx);
511 E : EXPECT_EQ(c1.Edx, c2.Edx);
512 E : EXPECT_EQ(c1.Ecx, c2.Ecx);
513 E : EXPECT_EQ(c1.Eax, c2.Eax);
514 :
515 : // "Control" registers.
516 E : EXPECT_EQ(c1.Ebp, c2.Ebp);
517 E : EXPECT_EQ(c1.Eip, c2.Eip);
518 E : EXPECT_EQ(static_cast<WORD>(c1.SegCs), static_cast<WORD>(c2.SegCs));
519 E : if (!ignore_flags)
520 E : EXPECT_EQ(c1.EFlags, c2.EFlags);
521 E : EXPECT_EQ(c1.Esp, c2.Esp);
522 E : EXPECT_EQ(static_cast<WORD>(c1.SegSs), static_cast<WORD>(c2.SegSs));
523 E : }
524 :
525 : } // namespace
526 :
527 : MemoryAccessorTester::MemoryAccessorTester()
528 : : expected_error_type_(agent::asan::UNKNOWN_BAD_ACCESS),
529 : memory_error_detected_(false),
530 E : ignore_flags_(false) {
531 E : EXPECT_EQ(static_cast<MemoryAccessorTester*>(NULL), instance_);
532 :
533 E : Initialize();
534 E : instance_ = this;
535 E : }
536 :
537 : MemoryAccessorTester::MemoryAccessorTester(IgnoreFlags /* ignore_flags */)
538 : : expected_error_type_(agent::asan::UNKNOWN_BAD_ACCESS),
539 : memory_error_detected_(false),
540 E : ignore_flags_(true) {
541 E : EXPECT_EQ(static_cast<MemoryAccessorTester*>(NULL), instance_);
542 :
543 E : Initialize();
544 E : instance_ = this;
545 E : }
546 :
547 E : MemoryAccessorTester::~MemoryAccessorTester() {
548 E : EXPECT_EQ(this, instance_);
549 E : instance_ = NULL;
550 E : }
551 :
552 E : void MemoryAccessorTester::Initialize() {
553 E : ::memset(&context_before_hook_, 0xCD, sizeof(context_before_hook_));
554 E : ::memset(&context_after_hook_, 0xCE, sizeof(context_after_hook_));
555 E : ::memset(&error_context_, 0xCF, sizeof(error_context_));
556 E : ::memset(&last_error_info_, 0, sizeof(last_error_info_));
557 E : }
558 :
559 : namespace {
560 :
561 : void CheckAccessAndCaptureContexts(
562 i : CONTEXT* before, CONTEXT* after, void* location) {
563 : __asm {
564 i : pushad
565 i : pushfd
566 :
567 : // Avoid undefined behavior by forcing values.
568 i : mov eax, 0x01234567
569 i : mov ebx, 0x70123456
570 i : mov ecx, 0x12345678
571 i : mov edx, 0x56701234
572 i : mov esi, 0xCCAACCAA
573 i : mov edi, 0xAACCAACC
574 :
575 i : RTL_CAPTURE_CONTEXT(before, check_access_expected_eip)
576 :
577 : // Push EDX as we're required to do by the custom calling convention.
578 i : push edx
579 : // Ptr is the pointer to check.
580 i : mov edx, location
581 : // Call through.
582 i : call dword ptr[check_access_fn + 0]
583 : check_access_expected_eip:
584 :
585 i : RTL_CAPTURE_CONTEXT(after, check_access_expected_eip)
586 :
587 i : popfd
588 i : popad
589 : }
590 i : }
591 :
592 : } // namespace
593 :
594 : void MemoryAccessorTester::CheckAccessAndCompareContexts(
595 E : FARPROC access_fn, void* ptr) {
596 E : memory_error_detected_ = false;
597 :
598 E : check_access_fn = access_fn;
599 :
600 : CheckAccessAndCaptureContexts(
601 E : &context_before_hook_, &context_after_hook_, ptr);
602 :
603 : ExpectEqualContexts(context_before_hook_,
604 : context_after_hook_,
605 E : ignore_flags_);
606 E : if (memory_error_detected_) {
607 : ExpectEqualContexts(context_before_hook_,
608 : error_context_,
609 E : ignore_flags_);
610 : }
611 :
612 E : check_access_fn = NULL;
613 E : }
614 :
615 : namespace {
616 :
617 : void CheckSpecialAccess(CONTEXT* before, CONTEXT* after,
618 i : void* dst, void* src, int len) {
619 : __asm {
620 i : pushad
621 i : pushfd
622 :
623 : // Override the direction flag.
624 i : cld
625 i : cmp direction_flag_forward, 0
626 i : jne skip_reverse_direction
627 i : std
628 : skip_reverse_direction:
629 :
630 : // Avoid undefined behavior by forcing values.
631 i : mov eax, 0x01234567
632 i : mov ebx, 0x70123456
633 i : mov edx, 0x56701234
634 :
635 : // Setup registers used by the special instruction.
636 i : mov ecx, len
637 i : mov esi, src
638 i : mov edi, dst
639 :
640 i : RTL_CAPTURE_CONTEXT(before, special_access_expected_eip)
641 :
642 : // Call through.
643 i : call dword ptr[check_access_fn + 0]
644 : special_access_expected_eip:
645 :
646 i : RTL_CAPTURE_CONTEXT(after, special_access_expected_eip)
647 :
648 i : popfd
649 i : popad
650 : }
651 i : }
652 :
653 : } // namespace
654 :
655 : void MemoryAccessorTester::CheckSpecialAccessAndCompareContexts(
656 : FARPROC access_fn, StringOperationDirection direction,
657 E : void* dst, void* src, int len) {
658 E : memory_error_detected_ = false;
659 :
660 E : direction_flag_forward = (direction == DIRECTION_FORWARD);
661 E : check_access_fn = access_fn;
662 :
663 : CheckSpecialAccess(
664 E : &context_before_hook_, &context_after_hook_, dst, src, len);
665 :
666 : ExpectEqualContexts(context_before_hook_,
667 : context_after_hook_,
668 E : ignore_flags_);
669 E : if (memory_error_detected_) {
670 : ExpectEqualContexts(context_before_hook_,
671 : error_context_,
672 E : ignore_flags_);
673 : }
674 :
675 E : check_access_fn = NULL;
676 E : }
677 :
678 E : void MemoryAccessorTester::AsanErrorCallbackImpl(AsanErrorInfo* error_info) {
679 : // TODO(sebmarchand): Stash the error info in a fixture-static variable and
680 : // assert on specific conditions after the fact.
681 E : EXPECT_NE(reinterpret_cast<AsanErrorInfo*>(NULL), error_info);
682 E : EXPECT_NE(agent::asan::UNKNOWN_BAD_ACCESS, error_info->error_type);
683 :
684 E : EXPECT_EQ(expected_error_type_, error_info->error_type);
685 E : if (error_info->error_type >= agent::asan::USE_AFTER_FREE) {
686 : // We should at least have the stack trace of the allocation of this block.
687 E : EXPECT_GT(error_info->block_info.alloc_stack_size, 0U);
688 E : EXPECT_NE(0U, error_info->block_info.alloc_tid);
689 : if (error_info->error_type == agent::asan::USE_AFTER_FREE ||
690 E : error_info->error_type == agent::asan::DOUBLE_FREE) {
691 E : EXPECT_GT(error_info->block_info.free_stack_size, 0U);
692 E : EXPECT_NE(0U, error_info->block_info.free_tid);
693 E : } else {
694 E : EXPECT_EQ(error_info->block_info.free_stack_size, 0U);
695 E : EXPECT_EQ(0U, error_info->block_info.free_tid);
696 : }
697 : }
698 :
699 E : if (error_info->error_type == agent::asan::HEAP_BUFFER_OVERFLOW) {
700 E : EXPECT_TRUE(strstr(error_info->shadow_info, "beyond") != NULL);
701 E : } else if (error_info->error_type == agent::asan::HEAP_BUFFER_UNDERFLOW) {
702 E : EXPECT_TRUE(strstr(error_info->shadow_info, "before") != NULL);
703 : }
704 :
705 E : memory_error_detected_ = true;
706 E : last_error_info_ = *error_info;
707 :
708 : // Copy the corrupt range's information.
709 E : if (error_info->heap_is_corrupt) {
710 E : EXPECT_GE(1U, error_info->corrupt_range_count);
711 E : for (size_t i = 0; i < error_info->corrupt_range_count; ++i) {
712 E : last_corrupt_ranges_.push_back(CorruptRangeInfo());
713 E : CorruptRangeInfo* range_info = &last_corrupt_ranges_.back();
714 E : range_info->first = error_info->corrupt_ranges[i];
715 E : AsanBlockInfoVector* block_infos = &range_info->second;
716 E : for (size_t j = 0; j < range_info->first.block_info_count; ++j) {
717 E : agent::asan::AsanBlockInfo block_info = range_info->first.block_info[j];
718 E : for (size_t k = 0;
719 E : k < range_info->first.block_info[j].alloc_stack_size;
720 E : ++k) {
721 : block_info.alloc_stack[k] =
722 E : range_info->first.block_info[j].alloc_stack[k];
723 E : }
724 E : for (size_t k = 0;
725 E : k < range_info->first.block_info[j].free_stack_size;
726 E : ++k) {
727 : block_info.free_stack[k] =
728 i : range_info->first.block_info[j].free_stack[k];
729 i : }
730 E : block_infos->push_back(block_info);
731 E : }
732 E : }
733 : }
734 :
735 E : error_context_ = error_info->context;
736 E : }
737 :
738 E : void MemoryAccessorTester::AsanErrorCallback(AsanErrorInfo* error_info) {
739 E : ASSERT_NE(reinterpret_cast<MemoryAccessorTester*>(NULL), instance_);
740 :
741 E : instance_->AsanErrorCallbackImpl(error_info);
742 E : }
743 :
744 : void MemoryAccessorTester::AssertMemoryErrorIsDetected(
745 E : FARPROC access_fn, void* ptr, BadAccessKind bad_access_type) {
746 E : expected_error_type_ = bad_access_type;
747 E : CheckAccessAndCompareContexts(access_fn, ptr);
748 E : ASSERT_TRUE(memory_error_detected_);
749 E : }
750 :
751 : void MemoryAccessorTester::ExpectSpecialMemoryErrorIsDetected(
752 : FARPROC access_fn, StringOperationDirection direction,
753 : bool expect_error, void* dst, void* src, int32 length,
754 E : BadAccessKind bad_access_type) {
755 E : DCHECK(dst != NULL);
756 E : DCHECK(src != NULL);
757 E : ASSERT_TRUE(check_access_fn == NULL);
758 :
759 E : expected_error_type_ = bad_access_type;
760 :
761 : // Perform memory accesses inside the range.
762 : ASSERT_NO_FATAL_FAILURE(
763 : CheckSpecialAccessAndCompareContexts(
764 E : access_fn, direction, dst, src, length));
765 :
766 E : EXPECT_EQ(expect_error, memory_error_detected_);
767 E : check_access_fn = NULL;
768 E : }
769 :
770 : TestMemoryInterceptors::TestMemoryInterceptors()
771 E : : heap_(NULL), src_(NULL), dst_(NULL) {
772 E : }
773 :
774 E : void TestMemoryInterceptors::SetUp() {
775 E : testing::TestWithAsanLogger::SetUp();
776 :
777 : // Make sure the logging routes to our instance.
778 : AppendToLoggerEnv(base::StringPrintf("syzyasan_rtl_unittests.exe,%u",
779 E : ::GetCurrentProcessId()));
780 :
781 E : asan_runtime_.SetUp(std::wstring());
782 :
783 : // Heap checking on error is expensive, so turn it down here.
784 E : asan_runtime_.params().check_heap_on_failure = false;
785 :
786 E : agent::asan::SetUpRtl(&asan_runtime_);
787 :
788 : asan_runtime_.SetErrorCallBack(
789 E : base::Bind(testing::MemoryAccessorTester::AsanErrorCallback));
790 E : heap_ = asan_HeapCreate(0, 0, 0);
791 E : ASSERT_TRUE(heap_ != NULL);
792 :
793 E : src_ = reinterpret_cast<byte*>(asan_HeapAlloc(heap_, 0, kAllocSize));
794 E : dst_ = reinterpret_cast<byte*>(asan_HeapAlloc(heap_, 0, kAllocSize));
795 E : ASSERT_TRUE(src_ && dst_);
796 :
797 : // String instructions may compare memory contents and bail early on
798 : // differences, so fill the buffers to make sure the checks go the full
799 : // distance.
800 E : ::memset(src_, 0xFF, kAllocSize);
801 E : ::memset(dst_, 0xFF, kAllocSize);
802 E : }
803 :
804 E : void TestMemoryInterceptors::TearDown() {
805 E : if (heap_ != NULL) {
806 E : asan_HeapFree(heap_, 0, src_);
807 E : asan_HeapFree(heap_, 0, dst_);
808 :
809 E : asan_HeapDestroy(heap_);
810 E : heap_ = NULL;
811 : }
812 E : agent::asan::TearDownRtl();
813 E : asan_runtime_.TearDown();
814 E : testing::TestWithAsanLogger::TearDown();
815 E : }
816 :
817 : void TestMemoryInterceptors::TestValidAccess(
818 E : const InterceptFunction* fns, size_t num_fns) {
819 E : for (size_t i = 0; i < num_fns; ++i) {
820 E : const InterceptFunction& fn = fns[i];
821 :
822 E : MemoryAccessorTester tester;
823 : tester.CheckAccessAndCompareContexts(
824 E : reinterpret_cast<FARPROC>(fn.function), src_);
825 :
826 E : ASSERT_FALSE(tester.memory_error_detected());
827 E : }
828 E : }
829 :
830 : void TestMemoryInterceptors::TestValidAccessIgnoreFlags(
831 E : const InterceptFunction* fns, size_t num_fns) {
832 E : for (size_t i = 0; i < num_fns; ++i) {
833 E : const InterceptFunction& fn = fns[i];
834 :
835 E : MemoryAccessorTester tester(MemoryAccessorTester::IGNORE_FLAGS);
836 : tester.CheckAccessAndCompareContexts(
837 E : reinterpret_cast<FARPROC>(fn.function), src_);
838 :
839 E : ASSERT_FALSE(tester.memory_error_detected());
840 E : }
841 E : }
842 :
843 : void TestMemoryInterceptors::TestOverrunAccess(
844 E : const InterceptFunction* fns, size_t num_fns) {
845 E : for (size_t i = 0; i < num_fns; ++i) {
846 E : const InterceptFunction& fn = fns[i];
847 :
848 E : MemoryAccessorTester tester;
849 : tester.AssertMemoryErrorIsDetected(
850 : reinterpret_cast<FARPROC>(fn.function),
851 : src_ + kAllocSize,
852 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
853 :
854 E : ASSERT_TRUE(tester.memory_error_detected());
855 E : }
856 E : }
857 :
858 : void TestMemoryInterceptors::TestOverrunAccessIgnoreFlags(
859 E : const InterceptFunction* fns, size_t num_fns) {
860 E : for (size_t i = 0; i < num_fns; ++i) {
861 E : const InterceptFunction& fn = fns[i];
862 :
863 E : MemoryAccessorTester tester(MemoryAccessorTester::IGNORE_FLAGS);
864 : tester.AssertMemoryErrorIsDetected(
865 : reinterpret_cast<FARPROC>(fn.function),
866 : src_ + kAllocSize,
867 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
868 :
869 E : ASSERT_TRUE(tester.memory_error_detected());
870 E : }
871 E : }
872 :
873 : void TestMemoryInterceptors::TestUnderrunAccess(
874 E : const InterceptFunction* fns, size_t num_fns) {
875 E : for (size_t i = 0; i < num_fns; ++i) {
876 E : const InterceptFunction& fn = fns[i];
877 :
878 : // TODO(someone): the 32 byte access checker does not fire on 32 byte
879 : // underrun. I guess the checkers test a single shadow byte at most
880 : // whereas it'd be more correct for access checkers to test as many
881 : // shadow bytes as is appropriate for the range of memory they touch.
882 E : MemoryAccessorTester tester;
883 : tester.AssertMemoryErrorIsDetected(
884 : reinterpret_cast<FARPROC>(fn.function),
885 : src_ - 8,
886 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_UNDERFLOW);
887 :
888 E : ASSERT_TRUE(tester.memory_error_detected());
889 E : }
890 E : }
891 :
892 : void TestMemoryInterceptors::TestUnderrunAccessIgnoreFlags(
893 E : const InterceptFunction* fns, size_t num_fns) {
894 E : for (size_t i = 0; i < num_fns; ++i) {
895 E : const InterceptFunction& fn = fns[i];
896 :
897 : // TODO(someone): the 32 byte access checker does not fire on 32 byte
898 : // underrun. I guess the checkers test a single shadow byte at most
899 : // whereas it'd be more correct for access checkers to test as many
900 : // shadow bytes as is appropriate for the range of memory they touch.
901 E : MemoryAccessorTester tester(MemoryAccessorTester::IGNORE_FLAGS);
902 : tester.AssertMemoryErrorIsDetected(
903 : reinterpret_cast<FARPROC>(fn.function),
904 : src_ - 8,
905 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_UNDERFLOW);
906 :
907 E : ASSERT_TRUE(tester.memory_error_detected());
908 E : }
909 E : }
910 :
911 : void TestMemoryInterceptors::TestStringValidAccess(
912 E : const StringInterceptFunction* fns, size_t num_fns) {
913 E : for (size_t i = 0; i < num_fns; ++i) {
914 E : const StringInterceptFunction& fn = fns[i];
915 :
916 E : MemoryAccessorTester tester;
917 : tester.CheckSpecialAccessAndCompareContexts(
918 : reinterpret_cast<FARPROC>(fn.function),
919 : MemoryAccessorTester::DIRECTION_FORWARD,
920 E : dst_, src_, kAllocSize / fn.size);
921 E : ASSERT_FALSE(tester.memory_error_detected());
922 :
923 : tester.CheckSpecialAccessAndCompareContexts(
924 : reinterpret_cast<FARPROC>(fn.function),
925 : MemoryAccessorTester::DIRECTION_BACKWARD,
926 : dst_ + kAllocSize - fn.size, src_ + kAllocSize - fn.size,
927 E : kAllocSize / fn.size);
928 :
929 E : ASSERT_FALSE(tester.memory_error_detected());
930 E : }
931 E : }
932 :
933 : void TestMemoryInterceptors::TestStringOverrunAccess(
934 E : const StringInterceptFunction* fns, size_t num_fns) {
935 E : for (size_t i = 0; i < num_fns; ++i) {
936 E : const StringInterceptFunction& fn = fns[i];
937 :
938 E : MemoryAccessorTester tester;
939 E : size_t oob_len = 0;
940 E : byte* oob_dst = NULL;
941 E : byte* oob_src = NULL;
942 :
943 : // Half the string function intercepts are for rep-prefixed instructions,
944 : // which count on "ecx", and the other half is for non-prefixed
945 : // instructions that always perform a single access.
946 : // Compute appropriate pointers for both variants, forwards.
947 E : if (fn.uses_counter) {
948 E : oob_len = kAllocSize / fn.size;
949 E : oob_dst = dst_ + fn.size;
950 E : oob_src = src_ + fn.size;
951 E : } else {
952 E : oob_len = 1;
953 E : oob_dst = dst_ + kAllocSize;
954 E : oob_src = src_ + kAllocSize;
955 : }
956 :
957 E : ASSERT_NE(agent::asan::ASAN_UNKNOWN_ACCESS, fn.dst_access_mode);
958 : // Overflow on dst forwards.
959 : tester.ExpectSpecialMemoryErrorIsDetected(
960 : reinterpret_cast<FARPROC>(fn.function),
961 : MemoryAccessorTester::DIRECTION_FORWARD, true,
962 : oob_dst, src_, oob_len,
963 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
964 :
965 E : if (fn.src_access_mode != agent::asan::ASAN_UNKNOWN_ACCESS) {
966 : // Overflow on src forwards.
967 : tester.ExpectSpecialMemoryErrorIsDetected(
968 : reinterpret_cast<FARPROC>(fn.function),
969 : MemoryAccessorTester::DIRECTION_FORWARD, true,
970 : dst_, oob_src, oob_len,
971 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
972 : }
973 :
974 : // Compute appropriate pointers for both variants, backwards.
975 E : if (fn.uses_counter) {
976 E : oob_len = kAllocSize / fn.size;
977 E : } else {
978 E : oob_len = 1;
979 : }
980 :
981 E : oob_dst = dst_ + kAllocSize;
982 E : oob_src = src_ + kAllocSize;
983 :
984 E : ASSERT_NE(agent::asan::ASAN_UNKNOWN_ACCESS, fn.dst_access_mode);
985 : // Overflow on dst backwards.
986 : tester.ExpectSpecialMemoryErrorIsDetected(
987 : reinterpret_cast<FARPROC>(fn.function),
988 : MemoryAccessorTester::DIRECTION_BACKWARD, true,
989 : oob_dst, src_ + kAllocSize - fn.size, oob_len,
990 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
991 :
992 E : if (fn.src_access_mode != agent::asan::ASAN_UNKNOWN_ACCESS) {
993 : // Overflow on src backwards.
994 : tester.ExpectSpecialMemoryErrorIsDetected(
995 : reinterpret_cast<FARPROC>(fn.function),
996 : MemoryAccessorTester::DIRECTION_BACKWARD, true,
997 : dst_ + kAllocSize - fn.size, oob_dst, oob_len,
998 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
999 : }
1000 E : }
1001 E : }
1002 :
1003 E : bool IsAccessible(void* address) {
1004 E : return testing::TestAccess(address, false);
1005 E : }
1006 :
1007 E : bool IsNotAccessible(void* address) {
1008 E : return testing::TestAccess(address, true);
1009 E : }
1010 :
1011 : DebugShadow::Metadata::Metadata()
1012 : : address(nullptr), size(0),
1013 : marker(agent::asan::kHeapAddressableMarker) {
1014 : }
1015 :
1016 : DebugShadow::Metadata::Metadata(
1017 : const void* address, size_t size, ShadowMarker marker)
1018 : : address(address), size(size), marker(marker) {
1019 : stack_capture.InitFromStack();
1020 : }
1021 :
1022 : DebugShadow::Metadata::Metadata(const Metadata& rhs)
1023 : : address(rhs.address), size(rhs.size), marker(rhs.marker) {
1024 : if (rhs.stack_capture.num_frames() > 0) {
1025 : stack_capture.InitFromExistingStack(rhs.stack_capture);
1026 : }
1027 : }
1028 :
1029 : DebugShadow::Metadata& DebugShadow::Metadata::operator=(const Metadata& rhs) {
1030 : address = rhs.address;
1031 : size = rhs.size;
1032 : marker = rhs.marker;
1033 : if (rhs.stack_capture.num_frames() > 0) {
1034 : stack_capture.InitFromExistingStack(rhs.stack_capture);
1035 : }
1036 : return *this;
1037 : }
1038 :
1039 : void DebugShadow::SetShadowMemory(
1040 : const void* address, size_t length, ShadowMarker marker) {
1041 : ClearIntersection(address, length);
1042 : if (marker != agent::asan::kHeapAddressableMarker) {
1043 : Range range(reinterpret_cast<uintptr_t>(address), length);
1044 : Metadata data(address, length, marker);
1045 :
1046 : ShadowAddressSpace::RangeMapIter it;
1047 : CHECK(shadow_address_space_.Insert(range, data, &it));
1048 :
1049 : // If this is memory being returned to a reserved pool, then potentially
1050 : // merge with neighboring such ranges. This keeps the address space as
1051 : // human legible as possible.
1052 : if (marker == agent::asan::kAsanReservedMarker) {
1053 : auto it1 = it;
1054 : auto it2 = it;
1055 : bool merge = false;
1056 : Metadata data = it->second;
1057 :
1058 : // Check to see if there's a range to the left, and if it needs to be
1059 : // merged.
1060 : if (it != shadow_address_space_.begin()) {
1061 : it1--;
1062 : if (it1->first.end() == it->first.start() &&
1063 : it1->second.marker == it->second.marker) {
1064 : merge = true;
1065 : if (it1->second.size >= data.size)
1066 : data = it1->second;
1067 : } else {
1068 : ++it1;
1069 : }
1070 : }
1071 :
1072 : // Check to see if there's a range to the right, and if it needs to be
1073 : // merged.
1074 : ++it2;
1075 : if (it2 != shadow_address_space_.end()) {
1076 : if (it->first.end() == it2->first.start() &&
1077 : it->second.marker == it2->second.marker) {
1078 : merge = true;
1079 : if (it2->second.size > data.size)
1080 : data = it2->second;
1081 : } else {
1082 : --it2;
1083 : }
1084 : } else {
1085 : --it2;
1086 : }
1087 :
1088 : if (merge) {
1089 : Range range(it1->first.start(),
1090 : it2->first.end() - it1->first.start());
1091 : CHECK(shadow_address_space_.SubsumeInsert(range, data));
1092 : }
1093 : }
1094 : }
1095 : }
1096 :
1097 : void DebugShadow::GetPointerAndSizeImpl(
1098 : void const** self, size_t* size) const {
1099 : DCHECK_NE(static_cast<void**>(nullptr), self);
1100 : DCHECK_NE(static_cast<size_t*>(nullptr), size);
1101 : *self = this;
1102 : *size = sizeof(*this);
1103 : }
1104 :
1105 : void DebugShadow::ClearIntersection(const void* addr, size_t size) {
1106 : uintptr_t start = reinterpret_cast<uintptr_t>(addr);
1107 :
1108 : auto range = Range(reinterpret_cast<uintptr_t>(addr), size);
1109 : ShadowAddressSpace::RangeMapIterPair iter_pair =
1110 : shadow_address_space_.FindIntersecting(range);
1111 :
1112 : bool reinsert_head_range = false;
1113 : Range head_range;
1114 : Metadata head_data;
1115 :
1116 : bool reinsert_tail_range = false;
1117 : Range tail_range;
1118 : Metadata tail_data;
1119 :
1120 : // If the range is non-empty then remember the portion of the head and tail
1121 : // ranges to be reinserted, if any.
1122 : if (iter_pair.first != iter_pair.second) {
1123 : auto it = iter_pair.first;
1124 : if (it->first.start() < start) {
1125 : reinsert_head_range = true;
1126 : head_range = Range(
1127 : it->first.start(),
1128 : start - it->first.start());
1129 : head_data = it->second;
1130 : }
1131 :
1132 : it = iter_pair.second;
1133 : --it;
1134 : if (start + size < it->first.end()) {
1135 : reinsert_tail_range = true;
1136 : tail_range = Range(
1137 : range.end(),
1138 : it->first.end() - range.end());
1139 : tail_data = it->second;
1140 : }
1141 : }
1142 :
1143 : // Delete the entire range.
1144 : shadow_address_space_.Remove(iter_pair);
1145 : if (reinsert_head_range)
1146 : CHECK(shadow_address_space_.Insert(head_range, head_data));
1147 : if (reinsert_tail_range)
1148 : CHECK(shadow_address_space_.Insert(tail_range, tail_data));
1149 : }
1150 :
1151 : } // namespace testing
|