1 : // Copyright 2012 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 : #include <windows.h>
16 :
17 : #include "base/bind.h"
18 : #include "base/file_util.h"
19 : #include "base/synchronization/waitable_event.h"
20 : #include "base/threading/thread.h"
21 : #include "base/win/scoped_handle.h"
22 : #include "gtest/gtest.h"
23 : #include "syzygy/agent/asan/asan_heap.h"
24 : #include "syzygy/agent/asan/asan_rtl_impl.h"
25 : #include "syzygy/agent/asan/asan_runtime.h"
26 : #include "syzygy/agent/asan/asan_shadow.h"
27 : #include "syzygy/agent/asan/unittest_util.h"
28 : #include "syzygy/core/unittest_util.h"
29 :
30 : namespace agent {
31 : namespace asan {
32 :
33 : namespace {
34 :
35 : // The access check function invoked by the below.
36 : FARPROC check_access_fn = NULL;
37 : // A flag used in asan callback to ensure that a memory error has been detected.
38 : bool memory_error_detected = false;
39 : // A pointer to a context to ensure that we're able to restore the context when
40 : // an asan error is found.
41 : CONTEXT* context_before_hook = NULL;
42 : // This will be used in the asan callback to ensure that we detect the right
43 : // error.
44 : HeapProxy::BadAccessKind expected_error_type = HeapProxy::UNKNOWN_BAD_ACCESS;
45 : // A flag to override the direction flag on special instruction checker.
46 : bool direction_flag_forward = true;
47 : // An arbitrary size for the buffer we allocate in the different unittests.
48 : const size_t kAllocSize = 13;
49 :
50 : // Shorthand for discussing all the asan runtime functions.
51 : #define ASAN_RTL_FUNCTIONS(F) \
52 : F(WINAPI, HANDLE, HeapCreate, \
53 : (DWORD options, SIZE_T initial_size, SIZE_T maximum_size)) \
54 : F(WINAPI, BOOL, HeapDestroy, \
55 : (HANDLE heap)) \
56 : F(WINAPI, LPVOID, HeapAlloc, \
57 : (HANDLE heap, DWORD flags, SIZE_T bytes)) \
58 : F(WINAPI, LPVOID, HeapReAlloc, \
59 : (HANDLE heap, DWORD flags, LPVOID mem, SIZE_T bytes)) \
60 : F(WINAPI, BOOL, HeapFree, \
61 : (HANDLE heap, DWORD flags, LPVOID mem)) \
62 : F(WINAPI, SIZE_T, HeapSize, \
63 : (HANDLE heap, DWORD flags, LPCVOID mem)) \
64 : F(WINAPI, BOOL, HeapValidate, \
65 : (HANDLE heap, DWORD flags, LPCVOID mem)) \
66 : F(WINAPI, SIZE_T, HeapCompact, \
67 : (HANDLE heap, DWORD flags)) \
68 : F(WINAPI, BOOL, HeapLock, (HANDLE heap)) \
69 : F(WINAPI, BOOL, HeapUnlock, (HANDLE heap)) \
70 : F(WINAPI, BOOL, HeapWalk, \
71 : (HANDLE heap, LPPROCESS_HEAP_ENTRY entry)) \
72 : F(WINAPI, BOOL, HeapSetInformation, \
73 : (HANDLE heap, HEAP_INFORMATION_CLASS info_class, \
74 : PVOID info, SIZE_T info_length)) \
75 : F(WINAPI, BOOL, HeapQueryInformation, \
76 : (HANDLE heap, HEAP_INFORMATION_CLASS info_class, \
77 : PVOID info, SIZE_T info_length, PSIZE_T return_length)) \
78 : F(WINAPI, void, SetCallBack, \
79 : (void (*callback)(AsanErrorInfo* error_info))) \
80 : F(_cdecl, void*, memcpy, \
81 : (void* destination, const void* source, size_t num)) \
82 : F(_cdecl, void*, memmove, \
83 : (void* destination, const void* source, size_t num)) \
84 : F(_cdecl, void*, memset, (void* ptr, int value, size_t num)) \
85 : F(_cdecl, const void*, memchr, (const void* ptr, int value, size_t num)) \
86 : F(_cdecl, size_t, strcspn, (const char* str1, const char* str2)) \
87 : F(_cdecl, size_t, strlen, (const char* str)) \
88 : F(_cdecl, const char*, strrchr, (const char* str, int character)) \
89 : F(_cdecl, int, strcmp, (const char* str1, const char* str2)) \
90 : F(_cdecl, const char*, strpbrk, (const char* str1, const char* str2)) \
91 : F(_cdecl, const char*, strstr, (const char* str1, const char* str2)) \
92 : F(_cdecl, size_t, strspn, (const char* str1, const char* str2)) \
93 : F(_cdecl, char*, strncpy, \
94 : (char* destination, const char* source, size_t num)) \
95 : F(_cdecl, char*, strncat, \
96 : (char* destination, const char* source, size_t num)) \
97 : F(_cdecl, void, PoisonMemoryRange, (const void* address, size_t size)) \
98 : F(_cdecl, void, UnpoisonMemoryRange, (const void* address, size_t size)) \
99 : F(_cdecl, void, GetAsanObjectSize, \
100 : (size_t user_object_size, size_t alignment)) \
101 : F(_cdecl, void, InitializeObject, \
102 : (void* asan_pointer, size_t user_object_size, size_t alignment)) \
103 : F(_cdecl, void, GetUserExtent, \
104 : (const void* asan_pointer, void** user_pointer, size_t* size)) \
105 : F(_cdecl, void, GetAsanExtent, \
106 : (const void* user_pointer, void** asan_pointer, size_t* size)) \
107 : F(_cdecl, void, QuarantineObject, (void* asan_pointer)) \
108 : F(_cdecl, void, DestroyObject, (void* asan_pointer)) \
109 : F(_cdecl, void, CloneObject, \
110 : (const void* src_asan_pointer, const void* dst_asan_pointer)) \
111 : F(WINAPI, BOOL, ReadFile, \
112 : (HANDLE file_handle, LPVOID buffer, DWORD bytes_to_read, \
113 : LPDWORD bytes_read, LPOVERLAPPED overlapped)) \
114 : F(WINAPI, BOOL, WriteFile, \
115 : (HANDLE file_handle, LPCVOID buffer, DWORD bytes_to_write, \
116 : LPDWORD bytes_written, LPOVERLAPPED overlapped)) \
117 : F(_cdecl, void, SetInterceptorCallback, (void (*callback)()))
118 :
119 : #define DECLARE_ASAN_FUNCTION_PTR(convention, ret, name, args) \
120 : typedef ret (convention* name##FunctionPtr)args;
121 :
122 : ASAN_RTL_FUNCTIONS(DECLARE_ASAN_FUNCTION_PTR)
123 :
124 : #undef DECLARE_ASAN_FUNCTION_PTR
125 :
126 : class AsanRtlTest : public testing::TestWithAsanLogger {
127 : public:
128 : AsanRtlTest() : asan_rtl_(NULL), heap_(NULL),
129 : memory_src_(NULL), memory_dst_(NULL),
130 E : memory_length_(0), memory_size_(0) {
131 E : }
132 :
133 E : void SetUp() OVERRIDE {
134 E : testing::TestWithAsanLogger::SetUp();
135 E : memory_error_detected = false;
136 :
137 : // Load the ASAN runtime library.
138 : base::FilePath asan_rtl_path =
139 E : testing::GetExeRelativePath(L"syzyasan_rtl.dll");
140 E : asan_rtl_ = ::LoadLibrary(asan_rtl_path.value().c_str());
141 E : ASSERT_TRUE(asan_rtl_ != NULL);
142 :
143 : // Load all the functions and assert that we find them.
144 : #define LOAD_ASAN_FUNCTION(convention, ret, name, args) \
145 : name##Function = reinterpret_cast<name##FunctionPtr>( \
146 : ::GetProcAddress(asan_rtl_, "asan_" #name)); \
147 : ASSERT_TRUE(name##Function != NULL);
148 :
149 E : ASAN_RTL_FUNCTIONS(LOAD_ASAN_FUNCTION)
150 :
151 : #undef LOAD_ASAN_FUNCTION
152 :
153 E : heap_ = HeapCreateFunction(0, 0, 0);
154 E : ASSERT_TRUE(heap_ != NULL);
155 E : }
156 :
157 E : void TearDown() OVERRIDE {
158 E : if (heap_ != NULL) {
159 E : HeapDestroyFunction(heap_);
160 E : heap_ = NULL;
161 : }
162 :
163 E : if (asan_rtl_ != NULL) {
164 E : ::FreeLibrary(asan_rtl_);
165 E : asan_rtl_ = NULL;
166 : }
167 :
168 E : testing::TestWithAsanLogger::TearDown();
169 E : }
170 :
171 E : HANDLE heap() { return heap_; }
172 :
173 : // Declare the function pointers.
174 : #define DECLARE_FUNCTION_PTR_VARIABLE(convention, ret, name, args) \
175 : static name##FunctionPtr AsanRtlTest::name##Function;
176 :
177 : ASAN_RTL_FUNCTIONS(DECLARE_FUNCTION_PTR_VARIABLE)
178 :
179 : #undef DECLARE_FUNCTION_PTR_VARIABLE
180 :
181 : protected:
182 : void AllocMemoryBuffers(int32 length, int32 element_size);
183 : void FreeMemoryBuffers();
184 :
185 : // The ASAN runtime module to test.
186 : HMODULE asan_rtl_;
187 :
188 : // Scratch heap handle valid from SetUp to TearDown.
189 : HANDLE heap_;
190 :
191 : // Memory buffers used to test special instructions.
192 : void* memory_src_;
193 : void* memory_dst_;
194 : int32 memory_length_;
195 : int32 memory_size_;
196 : };
197 :
198 : // A helper struct to be passed as a destructor of ASan scoped allocation.
199 : struct ASanDeleteHelper {
200 E : explicit ASanDeleteHelper(AsanRtlTest* asan_rtl)
201 : : asan_rtl_(asan_rtl) {
202 E : }
203 :
204 E : void operator()(void* ptr) {
205 E : asan_rtl_->HeapFreeFunction(asan_rtl_->heap(), 0, ptr);
206 E : }
207 : AsanRtlTest* asan_rtl_;
208 : };
209 :
210 : // A scoped_ptr specialization for the ASan allocations.
211 : template <typename T>
212 : class ScopedASanAlloc : public scoped_ptr<T, ASanDeleteHelper> {
213 : public:
214 : explicit ScopedASanAlloc(AsanRtlTest* asan_rtl)
215 : : scoped_ptr(NULL, ASanDeleteHelper(asan_rtl)) {
216 : }
217 :
218 E : ScopedASanAlloc(AsanRtlTest* asan_rtl, size_t size)
219 : : scoped_ptr(NULL, ASanDeleteHelper(asan_rtl)) {
220 E : Allocate(asan_rtl, size);
221 E : }
222 :
223 : template <typename T2>
224 E : T2* GetAs() {
225 E : return reinterpret_cast<T2*>(get());
226 E : }
227 :
228 E : void Allocate(AsanRtlTest* asan_rtl, size_t size) {
229 E : ASSERT_TRUE(asan_rtl != NULL);
230 : reset(reinterpret_cast<T*>(
231 E : asan_rtl->HeapAllocFunction(asan_rtl->heap(), 0, size * sizeof(T))));
232 E : memset(get(), 0, size * sizeof(T));
233 E : }
234 :
235 : T operator[](int i) const {
236 : CHECK(get() != NULL);
237 : return get()[i];
238 : }
239 :
240 E : T& operator[](int i) {
241 E : CHECK(get() != NULL);
242 E : return get()[i];
243 E : }
244 : };
245 :
246 : // Define the function pointers.
247 : #define DEFINE_FUNCTION_PTR_VARIABLE(convention, ret, name, args) \
248 : name##FunctionPtr AsanRtlTest::name##Function;
249 :
250 : ASAN_RTL_FUNCTIONS(DEFINE_FUNCTION_PTR_VARIABLE)
251 :
252 : #undef DEFINE_FUNCTION_PTR_VARIABLE
253 :
254 : #define RTL_CAPTURE_CONTEXT(context, expected_eip) { \
255 : /* Save caller save registers. */ \
256 : __asm push eax \
257 : __asm push ecx \
258 : __asm push edx \
259 : /* Call Capture context. */ \
260 : __asm push context \
261 : __asm call dword ptr[RtlCaptureContext] \
262 : /* Restore caller save registers. */ \
263 : __asm pop edx \
264 : __asm pop ecx \
265 : __asm pop eax \
266 : /* Restore registers which are stomped by RtlCaptureContext. */ \
267 : __asm push eax \
268 : __asm pushfd \
269 : __asm mov eax, context \
270 : __asm mov dword ptr[eax + CONTEXT.Ebp], ebp \
271 : __asm mov dword ptr[eax + CONTEXT.Esp], esp \
272 : /* NOTE: we need to add 8 bytes because EAX + EFLAGS are on the stack. */ \
273 : __asm add dword ptr[eax + CONTEXT.Esp], 8 \
274 : __asm mov dword ptr[eax + CONTEXT.Eip], offset expected_eip \
275 : __asm popfd \
276 : __asm pop eax \
277 : }
278 :
279 : // Check if the sections of 2 context are equals.
280 : // @param c1 The first context to check.
281 : // @param c2 The second context to check.
282 : // @param flags The sections to compare.
283 E : void ExpectEqualContexts(const CONTEXT& c1, const CONTEXT& c2, DWORD flags) {
284 E : if ((flags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS) {
285 E : EXPECT_EQ(c1.SegGs, c2.SegGs);
286 E : EXPECT_EQ(c1.SegFs, c2.SegFs);
287 E : EXPECT_EQ(c1.SegEs, c2.SegEs);
288 E : EXPECT_EQ(c1.SegDs, c2.SegDs);
289 : }
290 :
291 E : if ((flags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
292 E : EXPECT_EQ(c1.Edi, c2.Edi);
293 E : EXPECT_EQ(c1.Esi, c2.Esi);
294 E : EXPECT_EQ(c1.Ebx, c2.Ebx);
295 E : EXPECT_EQ(c1.Edx, c2.Edx);
296 E : EXPECT_EQ(c1.Ecx, c2.Ecx);
297 E : EXPECT_EQ(c1.Eax, c2.Eax);
298 : }
299 :
300 E : if ((flags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
301 E : EXPECT_EQ(c1.Ebp, c2.Ebp);
302 E : EXPECT_EQ(c1.Eip, c2.Eip);
303 E : EXPECT_EQ(c1.SegCs, c2.SegCs);
304 E : EXPECT_EQ(c1.EFlags, c2.EFlags);
305 E : EXPECT_EQ(c1.Esp, c2.Esp);
306 E : EXPECT_EQ(c1.SegSs, c2.SegSs);
307 : }
308 E : }
309 :
310 : void CheckAccessAndCaptureContexts(
311 i : CONTEXT* before, CONTEXT* after, void* location) {
312 : __asm {
313 i : pushad
314 i : pushfd
315 :
316 : // Avoid undefined behavior by forcing values.
317 i : mov eax, 0x01234567
318 i : mov ebx, 0x70123456
319 i : mov ecx, 0x12345678
320 i : mov edx, 0x56701234
321 i : mov esi, 0xCCAACCAA
322 i : mov edi, 0xAACCAACC
323 :
324 i : RTL_CAPTURE_CONTEXT(before, check_access_expected_eip)
325 :
326 : // Push EDX as we're required to do by the custom calling convention.
327 i : push edx
328 : // Ptr is the pointer to check.
329 i : mov edx, location
330 : // Call through.
331 i : call dword ptr[check_access_fn + 0]
332 : check_access_expected_eip:
333 :
334 i : RTL_CAPTURE_CONTEXT(after, check_access_expected_eip)
335 :
336 i : popfd
337 i : popad
338 : }
339 i : }
340 :
341 E : void CheckAccessAndCompareContexts(void* ptr) {
342 E : CONTEXT before = {};
343 E : CONTEXT after = {};
344 :
345 E : context_before_hook = &before;
346 E : CheckAccessAndCaptureContexts(&before, &after, ptr);
347 :
348 E : ExpectEqualContexts(before, after, CONTEXT_FULL);
349 :
350 E : context_before_hook = NULL;
351 E : }
352 :
353 : void CheckSpecialAccess(CONTEXT* before, CONTEXT* after,
354 i : void* dst, void* src, int len) {
355 : __asm {
356 i : pushad
357 i : pushfd
358 :
359 : // Override the direction flag.
360 i : cld
361 i : cmp direction_flag_forward, 0
362 i : jne skip_reverse_direction
363 i : std
364 : skip_reverse_direction:
365 :
366 : // Avoid undefined behavior by forcing values.
367 i : mov eax, 0x01234567
368 i : mov ebx, 0x70123456
369 i : mov edx, 0x56701234
370 :
371 : // Setup registers used by the special instruction.
372 i : mov ecx, len
373 i : mov esi, src
374 i : mov edi, dst
375 :
376 i : RTL_CAPTURE_CONTEXT(before, special_access_expected_eip)
377 :
378 : // Call through.
379 i : call dword ptr[check_access_fn + 0]
380 : special_access_expected_eip:
381 :
382 i : RTL_CAPTURE_CONTEXT(after, special_access_expected_eip)
383 :
384 i : popfd
385 i : popad
386 : }
387 i : }
388 :
389 E : void CheckSpecialAccessAndCompareContexts(void* dst, void* src, int len) {
390 E : CONTEXT before = {};
391 E : CONTEXT after = {};
392 :
393 E : context_before_hook = &before;
394 :
395 E : CheckSpecialAccess(&before, &after, dst, src, len);
396 :
397 E : ExpectEqualContexts(before, after, CONTEXT_FULL);
398 :
399 E : context_before_hook = NULL;
400 E : }
401 :
402 E : void AsanErrorCallback(AsanErrorInfo* error_info) {
403 : // TODO(sebmarchand): Stash the error info in a fixture-static variable and
404 : // assert on specific conditions after the fact.
405 E : EXPECT_TRUE(context_before_hook != NULL);
406 E : EXPECT_NE(HeapProxy::UNKNOWN_BAD_ACCESS, error_info->error_type);
407 :
408 E : EXPECT_EQ(expected_error_type, error_info->error_type);
409 E : if (error_info->error_type >= HeapProxy::USE_AFTER_FREE) {
410 : // We should at least have the stack trace of the allocation of this block.
411 E : EXPECT_GT(error_info->alloc_stack_size, 0U);
412 E : EXPECT_NE(0U, error_info->alloc_tid);
413 E : if (error_info->error_type == HeapProxy::USE_AFTER_FREE) {
414 E : EXPECT_GT(error_info->free_stack_size, 0U);
415 E : EXPECT_NE(0U, error_info->free_tid);
416 E : } else {
417 E : EXPECT_EQ(error_info->free_stack_size, 0U);
418 E : EXPECT_EQ(0U, error_info->free_tid);
419 : }
420 : }
421 :
422 E : if (error_info->error_type == HeapProxy::HEAP_BUFFER_OVERFLOW) {
423 E : EXPECT_TRUE(strstr(error_info->shadow_info, "beyond") != NULL);
424 E : } else if (error_info->error_type == HeapProxy::HEAP_BUFFER_UNDERFLOW) {
425 E : EXPECT_TRUE(strstr(error_info->shadow_info, "before") != NULL);
426 : }
427 :
428 E : memory_error_detected = true;
429 : ExpectEqualContexts(*context_before_hook,
430 : error_info->context,
431 E : CONTEXT_INTEGER | CONTEXT_CONTROL);
432 E : }
433 :
434 E : void AsanErrorCallbackWithoutComparingContext(AsanErrorInfo* error_info) {
435 E : memory_error_detected = true;
436 E : }
437 :
438 : void AssertMemoryErrorIsDetected(void* ptr,
439 E : HeapProxy::BadAccessKind bad_access_type) {
440 E : expected_error_type = bad_access_type;
441 E : memory_error_detected = false;
442 E : CheckAccessAndCompareContexts(ptr);
443 E : ASSERT_TRUE(memory_error_detected);
444 E : }
445 :
446 : void ExpectSpecialMemoryErrorIsDetected(bool expected,
447 : void* dst, void* src, int32 length,
448 E : HeapProxy::BadAccessKind bad_access_type) {
449 E : DCHECK(dst != NULL);
450 E : DCHECK(src != NULL);
451 E : ASSERT_TRUE(check_access_fn != NULL);
452 E : expected_error_type = bad_access_type;
453 :
454 : // Setup the callback to detect invalid accesses.
455 E : memory_error_detected = false;
456 :
457 : // Perform memory accesses inside the range.
458 : ASSERT_NO_FATAL_FAILURE(
459 E : CheckSpecialAccessAndCompareContexts(dst, src, length));
460 :
461 E : EXPECT_EQ(expected, memory_error_detected);
462 E : }
463 :
464 : } // namespace
465 :
466 E : TEST_F(AsanRtlTest, AsanCheckGoodAccess) {
467 : check_access_fn =
468 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
469 E : ASSERT_TRUE(check_access_fn != NULL);
470 :
471 : // Run through access checking an allocation that's larger than our
472 : // block size (8), but not a multiple thereof to exercise all paths
473 : // in the access check function (save for the failure path).
474 E : ScopedASanAlloc<uint8> mem(this, kAllocSize);
475 E : ASSERT_TRUE(mem.get() != NULL);
476 :
477 E : for (size_t i = 0; i < kAllocSize; ++i) {
478 E : ASSERT_NO_FATAL_FAILURE(CheckAccessAndCompareContexts(mem.get() + i));
479 E : }
480 E : }
481 :
482 E : TEST_F(AsanRtlTest, AsanCheckHeapBufferOverflow) {
483 : check_access_fn =
484 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
485 E : ASSERT_TRUE(check_access_fn != NULL);
486 :
487 E : ScopedASanAlloc<uint8> mem(this, kAllocSize);
488 E : ASSERT_TRUE(mem.get() != NULL);
489 :
490 E : SetCallBackFunction(&AsanErrorCallback);
491 : AssertMemoryErrorIsDetected(mem.get() + kAllocSize,
492 E : HeapProxy::HEAP_BUFFER_OVERFLOW);
493 E : EXPECT_TRUE(LogContains("previously allocated here"));
494 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
495 E : }
496 :
497 E : TEST_F(AsanRtlTest, AsanCheckHeapBufferUnderflow) {
498 : check_access_fn =
499 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
500 E : ASSERT_TRUE(check_access_fn != NULL);
501 :
502 E : const size_t kAllocSize = 13;
503 E : ScopedASanAlloc<uint8> mem(this, kAllocSize);
504 E : ASSERT_TRUE(mem.get() != NULL);
505 :
506 E : SetCallBackFunction(&AsanErrorCallback);
507 E : AssertMemoryErrorIsDetected(mem.get() - 1, HeapProxy::HEAP_BUFFER_UNDERFLOW);
508 E : EXPECT_TRUE(LogContains("previously allocated here"));
509 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
510 E : }
511 :
512 E : TEST_F(AsanRtlTest, AsanCheckUseAfterFree) {
513 : check_access_fn =
514 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
515 E : ASSERT_TRUE(check_access_fn != NULL);
516 :
517 E : const size_t kAllocSize = 13;
518 E : ScopedASanAlloc<uint8> mem(this, kAllocSize);
519 E : ASSERT_TRUE(mem.get() != NULL);
520 :
521 E : SetCallBackFunction(&AsanErrorCallback);
522 E : uint8* mem_ptr = mem.get();
523 E : mem.reset(NULL);
524 E : AssertMemoryErrorIsDetected(mem_ptr, HeapProxy::USE_AFTER_FREE);
525 E : EXPECT_TRUE(LogContains("previously allocated here"));
526 E : EXPECT_TRUE(LogContains("freed here"));
527 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapUseAfterFree));
528 E : }
529 :
530 E : TEST_F(AsanRtlTest, AsanCheckDoubleFree) {
531 : check_access_fn =
532 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
533 E : ASSERT_TRUE(check_access_fn != NULL);
534 :
535 E : const size_t kAllocSize = 13;
536 E : uint8* mem_ptr = NULL;
537 : {
538 E : ScopedASanAlloc<uint8> mem(this, kAllocSize);
539 E : ASSERT_TRUE(mem.get() != NULL);
540 E : mem_ptr = mem.get();
541 E : }
542 :
543 E : CONTEXT context_before_error = {};
544 E : context_before_hook = &context_before_error;
545 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
546 E : EXPECT_FALSE(HeapFreeFunction(heap_, 0, mem_ptr));
547 E : EXPECT_TRUE(memory_error_detected);
548 E : EXPECT_TRUE(LogContains(HeapProxy::kAttemptingDoubleFree));
549 E : EXPECT_TRUE(LogContains("previously allocated here"));
550 E : EXPECT_TRUE(LogContains("freed here"));
551 E : }
552 :
553 E : TEST_F(AsanRtlTest, AsanCheckWildAccess) {
554 : check_access_fn =
555 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
556 E : ASSERT_TRUE(check_access_fn != NULL);
557 :
558 E : SetCallBackFunction(&AsanErrorCallback);
559 : AssertMemoryErrorIsDetected(reinterpret_cast<void*>(0x80000000),
560 E : HeapProxy::WILD_ACCESS);
561 E : EXPECT_TRUE(LogContains(HeapProxy::kWildAccess));
562 E : }
563 :
564 E : TEST_F(AsanRtlTest, AsanCheckInvalidAccess) {
565 : check_access_fn =
566 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
567 E : ASSERT_TRUE(check_access_fn != NULL);
568 :
569 E : SetCallBackFunction(&AsanErrorCallback);
570 : AssertMemoryErrorIsDetected(reinterpret_cast<void*>(0x00000000),
571 E : HeapProxy::INVALID_ADDRESS);
572 E : EXPECT_TRUE(LogContains(HeapProxy::kInvalidAddress));
573 E : }
574 :
575 E : void AsanRtlTest::AllocMemoryBuffers(int32 length, int32 element_size) {
576 E : DCHECK(memory_src_ == NULL);
577 E : DCHECK(memory_dst_ == NULL);
578 E : DCHECK_EQ(0, memory_length_);
579 E : DCHECK_EQ(0, memory_size_);
580 :
581 : // Keep track of memory size.
582 E : memory_length_ = length;
583 E : memory_size_ = length * element_size;
584 :
585 : // Allocate memory space.
586 E : memory_src_ = HeapAllocFunction(heap_, 0, memory_size_);
587 E : ASSERT_TRUE(memory_src_ != NULL);
588 E : memory_dst_ = HeapAllocFunction(heap_, 0, memory_size_);
589 E : ASSERT_TRUE(memory_dst_ != NULL);
590 :
591 : // Initialize memory.
592 E : memset(memory_src_, 0, memory_size_);
593 E : memset(memory_dst_, 0, memory_size_);
594 E : }
595 :
596 E : void AsanRtlTest::FreeMemoryBuffers() {
597 E : DCHECK(memory_src_ != NULL);
598 E : DCHECK(memory_dst_ != NULL);
599 :
600 E : ASSERT_TRUE(HeapFreeFunction(heap_, 0, memory_src_));
601 E : ASSERT_TRUE(HeapFreeFunction(heap_, 0, memory_dst_));
602 :
603 E : memory_length_ = 0;
604 E : memory_size_ = 0;
605 E : memory_src_ = NULL;
606 E : memory_dst_ = NULL;
607 E : }
608 :
609 E : TEST_F(AsanRtlTest, AsanSingleSpecial1byteInstructionCheckGoodAccess) {
610 : static const char* function_names[] = {
611 : "asan_check_1_byte_movs_access",
612 : "asan_check_1_byte_cmps_access",
613 : "asan_check_1_byte_stos_access"
614 : };
615 :
616 : // Setup the callback to detect invalid accesses.
617 E : SetCallBackFunction(&AsanErrorCallback);
618 :
619 : // Allocate memory space.
620 E : AllocMemoryBuffers(kAllocSize, sizeof(uint8));
621 E : uint8* src = reinterpret_cast<uint8*>(memory_src_);
622 E : uint8* dst = reinterpret_cast<uint8*>(memory_dst_);
623 :
624 : // Validate memory accesses.
625 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
626 : check_access_fn =
627 E : ::GetProcAddress(asan_rtl_, function_names[function]);
628 E : ASSERT_TRUE(check_access_fn != NULL);
629 :
630 E : for (int32 i = 0; i < memory_length_; ++i)
631 : ExpectSpecialMemoryErrorIsDetected(false, &dst[i], &src[i], 0xDEADDEAD,
632 E : HeapProxy::UNKNOWN_BAD_ACCESS);
633 E : }
634 :
635 E : FreeMemoryBuffers();
636 E : }
637 :
638 E : TEST_F(AsanRtlTest, AsanSingleSpecial2byteInstructionCheckGoodAccess) {
639 : static const char* function_names[] = {
640 : "asan_check_2_byte_movs_access",
641 : "asan_check_2_byte_cmps_access",
642 : "asan_check_2_byte_stos_access"
643 : };
644 :
645 : // Setup the callback to detect invalid accesses.
646 E : SetCallBackFunction(&AsanErrorCallback);
647 :
648 : // Allocate memory space.
649 E : AllocMemoryBuffers(kAllocSize, sizeof(uint16));
650 E : uint16* src = reinterpret_cast<uint16*>(memory_src_);
651 E : uint16* dst = reinterpret_cast<uint16*>(memory_dst_);
652 :
653 : // Validate memory accesses.
654 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
655 : check_access_fn =
656 E : ::GetProcAddress(asan_rtl_, function_names[function]);
657 E : ASSERT_TRUE(check_access_fn != NULL);
658 :
659 E : for (int32 i = 0; i < memory_length_; ++i)
660 : ExpectSpecialMemoryErrorIsDetected(false, &dst[i], &src[i], 0xDEADDEAD,
661 E : HeapProxy::UNKNOWN_BAD_ACCESS);
662 E : }
663 :
664 E : FreeMemoryBuffers();
665 E : }
666 :
667 E : TEST_F(AsanRtlTest, AsanSingleSpecial4byteInstructionCheckGoodAccess) {
668 : static const char* function_names[] = {
669 : "asan_check_4_byte_movs_access",
670 : "asan_check_4_byte_cmps_access",
671 : "asan_check_4_byte_stos_access"
672 : };
673 :
674 : // Setup the callback to detect invalid accesses.
675 E : SetCallBackFunction(&AsanErrorCallback);
676 :
677 : // Allocate memory space.
678 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
679 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
680 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
681 :
682 : // Validate memory accesses.
683 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
684 : check_access_fn =
685 E : ::GetProcAddress(asan_rtl_, function_names[function]);
686 E : ASSERT_TRUE(check_access_fn != NULL);
687 :
688 E : for (int32 i = 0; i < memory_length_; ++i)
689 : ExpectSpecialMemoryErrorIsDetected(false, &dst[i], &src[i], 0xDEADDEAD,
690 E : HeapProxy::UNKNOWN_BAD_ACCESS);
691 E : }
692 :
693 E : FreeMemoryBuffers();
694 E : }
695 :
696 E : TEST_F(AsanRtlTest, AsanSingleSpecialInstructionCheckBadAccess) {
697 : static const char* function_names[] = {
698 : "asan_check_1_byte_movs_access",
699 : "asan_check_1_byte_cmps_access",
700 : "asan_check_2_byte_movs_access",
701 : "asan_check_2_byte_cmps_access",
702 : "asan_check_4_byte_movs_access",
703 : "asan_check_4_byte_cmps_access"
704 : };
705 :
706 : // Setup the callback to detect invalid accesses.
707 E : SetCallBackFunction(&AsanErrorCallback);
708 :
709 : // Allocate memory space.
710 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
711 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
712 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
713 :
714 : // Validate memory accesses.
715 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
716 : check_access_fn =
717 E : ::GetProcAddress(asan_rtl_, function_names[function]);
718 E : ASSERT_TRUE(check_access_fn != NULL);
719 :
720 : ExpectSpecialMemoryErrorIsDetected(true, &dst[0], &src[-1], 0xDEADDEAD,
721 E : HeapProxy::HEAP_BUFFER_UNDERFLOW);
722 : ExpectSpecialMemoryErrorIsDetected(true, &dst[-1], &src[0], 0xDEADDEAD,
723 E : HeapProxy::HEAP_BUFFER_UNDERFLOW);
724 :
725 : ExpectSpecialMemoryErrorIsDetected(true, &dst[0], &src[memory_length_],
726 E : 0xDEADDEAD, HeapProxy::HEAP_BUFFER_OVERFLOW);
727 : ExpectSpecialMemoryErrorIsDetected(true, &dst[memory_length_], &src[0],
728 E : 0xDEADDEAD, HeapProxy::HEAP_BUFFER_OVERFLOW);
729 E : }
730 :
731 E : FreeMemoryBuffers();
732 E : }
733 :
734 E : TEST_F(AsanRtlTest, AsanSingleStoInstructionCheckBadAccess) {
735 : static const char* function_names[] = {
736 : "asan_check_1_byte_stos_access",
737 : "asan_check_2_byte_stos_access",
738 : "asan_check_4_byte_stos_access"
739 : };
740 :
741 : // Setup the callback to detect invalid accesses.
742 E : SetCallBackFunction(&AsanErrorCallback);
743 :
744 : // Allocate memory space.
745 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
746 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
747 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
748 :
749 : // Validate memory accesses.
750 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
751 : check_access_fn =
752 E : ::GetProcAddress(asan_rtl_, function_names[function]);
753 E : ASSERT_TRUE(check_access_fn != NULL);
754 :
755 : ExpectSpecialMemoryErrorIsDetected(false, &dst[0], &src[-1], 0xDEAD,
756 E : HeapProxy::HEAP_BUFFER_UNDERFLOW);
757 : ExpectSpecialMemoryErrorIsDetected(true, &dst[-1], &src[0], 0xDEAD,
758 E : HeapProxy::HEAP_BUFFER_UNDERFLOW);
759 :
760 : ExpectSpecialMemoryErrorIsDetected(false, &dst[0], &src[memory_length_],
761 E : 0xDEADDEAD, HeapProxy::HEAP_BUFFER_OVERFLOW);
762 : ExpectSpecialMemoryErrorIsDetected(true, &dst[memory_length_], &src[0],
763 E : 0xDEADDEAD, HeapProxy::HEAP_BUFFER_OVERFLOW);
764 E : }
765 :
766 E : FreeMemoryBuffers();
767 E : }
768 :
769 E : TEST_F(AsanRtlTest, AsanPrefixedSpecialInstructionCheckGoodAccess) {
770 : static const char* function_names[] = {
771 : "asan_check_repz_4_byte_movs_access",
772 : "asan_check_repz_4_byte_cmps_access",
773 : "asan_check_repz_4_byte_stos_access"
774 : };
775 :
776 : // Setup the callback to detect invalid accesses.
777 E : SetCallBackFunction(&AsanErrorCallback);
778 :
779 : // Allocate memory space.
780 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
781 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
782 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
783 :
784 : // Validate memory accesses.
785 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
786 : check_access_fn =
787 E : ::GetProcAddress(asan_rtl_, function_names[function]);
788 E : ASSERT_TRUE(check_access_fn != NULL);
789 :
790 : ExpectSpecialMemoryErrorIsDetected(false, &dst[0], &src[0], memory_length_,
791 E : HeapProxy::UNKNOWN_BAD_ACCESS);
792 E : }
793 :
794 E : FreeMemoryBuffers();
795 E : }
796 :
797 E : TEST_F(AsanRtlTest, AsanPrefixedSpecialInstructionCheckBadAccess) {
798 : static const char* function_names[] = {
799 : "asan_check_repz_4_byte_movs_access",
800 : "asan_check_repz_4_byte_cmps_access",
801 : "asan_check_repz_4_byte_stos_access"
802 : };
803 :
804 : // Setup the callback to detect invalid accesses.
805 E : SetCallBackFunction(&AsanErrorCallback);
806 :
807 : // Allocate memory space.
808 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
809 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
810 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
811 :
812 : // Validate memory accesses.
813 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
814 : check_access_fn =
815 E : ::GetProcAddress(asan_rtl_, function_names[function]);
816 E : ASSERT_TRUE(check_access_fn != NULL);
817 :
818 : ExpectSpecialMemoryErrorIsDetected(true, &dst[0], &src[0],
819 E : memory_length_ + 1, HeapProxy::HEAP_BUFFER_OVERFLOW);
820 : ExpectSpecialMemoryErrorIsDetected(true, &dst[-1], &src[-1],
821 E : memory_length_, HeapProxy::HEAP_BUFFER_UNDERFLOW);
822 : ExpectSpecialMemoryErrorIsDetected(true, &dst[-1], &src[0],
823 E : memory_length_, HeapProxy::HEAP_BUFFER_UNDERFLOW);
824 E : }
825 :
826 E : FreeMemoryBuffers();
827 E : }
828 :
829 E : TEST_F(AsanRtlTest, AsanDirectionSpecialInstructionCheckGoodAccess) {
830 : static const char* function_names[] = {
831 : "asan_check_repz_4_byte_movs_access",
832 : "asan_check_repz_4_byte_cmps_access",
833 : "asan_check_repz_4_byte_stos_access"
834 : };
835 :
836 : // Setup the callback to detect invalid accesses.
837 E : SetCallBackFunction(&AsanErrorCallback);
838 :
839 : // Force direction flag to backward.
840 E : direction_flag_forward = false;
841 :
842 : // Allocate memory space.
843 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
844 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
845 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
846 :
847 : // Validate memory accesses.
848 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
849 : check_access_fn =
850 E : ::GetProcAddress(asan_rtl_, function_names[function]);
851 E : ASSERT_TRUE(check_access_fn != NULL);
852 :
853 : ExpectSpecialMemoryErrorIsDetected(false, &dst[memory_length_ - 1],
854 : &src[memory_length_ - 1], memory_length_,
855 E : HeapProxy::UNKNOWN_BAD_ACCESS);
856 E : }
857 :
858 : // Reset direction flag to forward.
859 E : direction_flag_forward = true;
860 :
861 E : FreeMemoryBuffers();
862 E : }
863 :
864 E : TEST_F(AsanRtlTest, AsanSpecialInstructionCheckZeroAccess) {
865 : static const char* function_names[] = {
866 : "asan_check_repz_1_byte_movs_access",
867 : "asan_check_repz_1_byte_cmps_access",
868 : "asan_check_repz_1_byte_stos_access",
869 : "asan_check_repz_2_byte_movs_access",
870 : "asan_check_repz_2_byte_cmps_access",
871 : "asan_check_repz_2_byte_stos_access",
872 : "asan_check_repz_4_byte_movs_access",
873 : "asan_check_repz_4_byte_cmps_access",
874 : "asan_check_repz_4_byte_stos_access"
875 : };
876 :
877 : // Setup the callback to detect invalid accesses.
878 E : SetCallBackFunction(&AsanErrorCallback);
879 :
880 : // Allocate memory space.
881 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
882 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
883 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
884 :
885 : // Validate memory accesses.
886 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
887 : check_access_fn =
888 E : ::GetProcAddress(asan_rtl_, function_names[function]);
889 E : ASSERT_TRUE(check_access_fn != NULL);
890 :
891 : // A prefixed instruction with a count of zero do not have side effects.
892 : ExpectSpecialMemoryErrorIsDetected(false, &dst[-1], &src[-1], 0,
893 E : HeapProxy::UNKNOWN_BAD_ACCESS);
894 E : }
895 :
896 E : FreeMemoryBuffers();
897 E : }
898 :
899 E : TEST_F(AsanRtlTest, AsanSpecialInstructionCheckShortcutAccess) {
900 : static const char* function_names[] = {
901 : "asan_check_repz_1_byte_cmps_access",
902 : "asan_check_repz_2_byte_cmps_access",
903 : "asan_check_repz_4_byte_cmps_access",
904 : };
905 :
906 : // Setup the callback to detect invalid accesses.
907 E : SetCallBackFunction(&AsanErrorCallback);
908 :
909 : // Allocate memory space.
910 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
911 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
912 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
913 :
914 E : src[1] = 0x12345667;
915 :
916 : // Validate memory accesses.
917 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
918 : check_access_fn =
919 E : ::GetProcAddress(asan_rtl_, function_names[function]);
920 E : ASSERT_TRUE(check_access_fn != NULL);
921 :
922 : // Compare instruction stop their execution when values differ.
923 : ExpectSpecialMemoryErrorIsDetected(false, &dst[0], &src[0],
924 E : memory_length_ + 1, HeapProxy::UNKNOWN_BAD_ACCESS);
925 E : }
926 :
927 E : FreeMemoryBuffers();
928 E : }
929 :
930 E : TEST_F(AsanRtlTest, AsanCheckMemset) {
931 E : const size_t kAllocSize = 13;
932 E : ScopedASanAlloc<uint8> mem(this, kAllocSize);
933 E : ASSERT_TRUE(mem.get() != NULL);
934 E : memory_error_detected = false;
935 :
936 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
937 E : EXPECT_EQ(mem.get(), memsetFunction(mem.GetAs<void*>(), 0xAA, kAllocSize));
938 E : EXPECT_FALSE(memory_error_detected);
939 E : for (size_t i = 0; i < kAllocSize; ++i)
940 E : EXPECT_EQ(0xAA, mem[i]);
941 :
942 : // mem[-1] points to the block header, we need to make sure that it doesn't
943 : // contain the value we're looking for.
944 E : uint8 last_block_header_byte = mem[-1];
945 E : mem[-1] = 0;
946 E : EXPECT_EQ(mem.get() - 1, memsetFunction(mem.get() - 1, 0xBB, kAllocSize));
947 E : EXPECT_TRUE(memory_error_detected);
948 E : for (size_t i = 0; i < kAllocSize; ++i)
949 E : EXPECT_EQ(0xBB, mem[i - 1]);
950 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
951 E : mem[-1] = last_block_header_byte;
952 E : ResetLog();
953 :
954 E : memory_error_detected = false;
955 E : EXPECT_EQ(mem.get(), memsetFunction(mem.get(), 0xCC, kAllocSize + 1));
956 E : for (size_t i = 0; i < kAllocSize + 1; ++i)
957 E : EXPECT_EQ(0xCC, mem[i]);
958 E : EXPECT_TRUE(memory_error_detected);
959 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
960 E : ResetLog();
961 :
962 E : }
963 :
964 E : TEST_F(AsanRtlTest, AsanCheckMemchr) {
965 E : const size_t kAllocSize = 13;
966 E : ScopedASanAlloc<uint8> mem(this, kAllocSize);
967 E : ASSERT_TRUE(mem.get() != NULL);
968 E : memset(mem.get(), 0, kAllocSize);
969 E : mem[4] = 0xAA;
970 E : memory_error_detected = false;
971 :
972 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
973 E : EXPECT_EQ(mem.get() + 4, memchrFunction(mem.get(), mem[4], kAllocSize));
974 E : EXPECT_EQ(NULL, memchrFunction(mem.get(), mem[4] + 1, kAllocSize));
975 E : EXPECT_FALSE(memory_error_detected);
976 :
977 : // mem[-1] points to the block header, we need to make sure that it doesn't
978 : // contain the value we're looking for.
979 E : uint8 last_block_header_byte = mem[-1];
980 E : mem[-1] = 0;
981 E : EXPECT_EQ(mem.get() + 4, memchrFunction(mem.get() - 1, mem[4], kAllocSize));
982 E : EXPECT_TRUE(memory_error_detected);
983 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
984 E : mem[-1] = last_block_header_byte;
985 E : ResetLog();
986 :
987 E : memory_error_detected = false;
988 E : EXPECT_EQ(mem.get() + 4, memchrFunction(mem.get() + 1, mem[4], kAllocSize));
989 E : EXPECT_TRUE(memory_error_detected);
990 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
991 E : ResetLog();
992 :
993 E : }
994 :
995 E : TEST_F(AsanRtlTest, AsanCheckMemmove) {
996 E : const size_t kAllocSize = 13;
997 E : ScopedASanAlloc<uint8> mem_src(this, kAllocSize);
998 E : ASSERT_TRUE(mem_src.get() != NULL);
999 E : memory_error_detected = false;
1000 : // Fill the array with value going from 0 to kAllocSize;
1001 E : for (size_t i = 0; i < kAllocSize; ++i)
1002 E : mem_src[i] = i;
1003 :
1004 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1005 : // Shift all the value from one index to the right.
1006 : EXPECT_EQ(mem_src.get() + 1,
1007 E : memmoveFunction(mem_src.get() + 1, mem_src.get(), kAllocSize - 1));
1008 E : EXPECT_FALSE(memory_error_detected);
1009 E : EXPECT_EQ(0, mem_src[0]);
1010 E : for (size_t i = 1; i < kAllocSize; ++i)
1011 E : EXPECT_EQ(i - 1, mem_src[i]);
1012 :
1013 : // Re-shift them to the left.
1014 : EXPECT_EQ(mem_src.get(),
1015 E : memmoveFunction(mem_src.get(), mem_src.get() + 1, kAllocSize));
1016 E : EXPECT_TRUE(memory_error_detected);
1017 E : for (size_t i = 0; i < kAllocSize - 1; ++i)
1018 E : EXPECT_EQ(i, mem_src[i]);
1019 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1020 E : ResetLog();
1021 :
1022 E : memory_error_detected = false;
1023 : // Shift them to the left one more time.
1024 :
1025 : // mem_src[-1] points to the block header, we need to make sure that it
1026 : // doesn't contain the value we're looking for.
1027 E : uint8 last_block_header_byte = mem_src[-1];
1028 E : mem_src[-1] = 0;
1029 : EXPECT_EQ(mem_src.get() - 1,
1030 E : memmoveFunction(mem_src.get() - 1, mem_src.get(), kAllocSize));
1031 E : EXPECT_TRUE(memory_error_detected);
1032 E : for (int i = -1; i < static_cast<int>(kAllocSize) - 2; ++i)
1033 E : EXPECT_EQ(i + 1, mem_src[i]);
1034 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1035 E : mem_src[-1] = last_block_header_byte;
1036 E : ResetLog();
1037 E : }
1038 :
1039 E : TEST_F(AsanRtlTest, AsanCheckMemcpy) {
1040 E : const size_t kAllocSize = 13;
1041 E : ScopedASanAlloc<uint8> mem_src(this, kAllocSize);
1042 E : ASSERT_TRUE(mem_src.get() != NULL);
1043 E : ScopedASanAlloc<uint8> mem_dst(this, kAllocSize);
1044 E : ASSERT_TRUE(mem_dst.get() != NULL);
1045 E : memory_error_detected = false;
1046 : // Fill the array with value going from 0 to kAllocSize;
1047 E : for (size_t i = 0; i < kAllocSize; ++i) {
1048 E : mem_src[i] = i;
1049 E : mem_dst[i] = ~i;
1050 E : }
1051 :
1052 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1053 : EXPECT_EQ(mem_dst.get(),
1054 E : memcpyFunction(mem_dst.get(), mem_src.get(), kAllocSize));
1055 E : EXPECT_FALSE(memory_error_detected);
1056 E : for (size_t i = 0; i < kAllocSize; ++i)
1057 E : EXPECT_EQ(mem_dst[i], mem_src[i]);
1058 :
1059 : EXPECT_EQ(mem_dst.get(),
1060 E : memcpyFunction(mem_dst.get(), mem_src.get(), kAllocSize + 1));
1061 E : EXPECT_TRUE(memory_error_detected);
1062 E : for (size_t i = 0; i < kAllocSize + 1; ++i)
1063 E : EXPECT_EQ(mem_dst[i], mem_src[i]);
1064 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1065 E : ResetLog();
1066 :
1067 E : memory_error_detected = false;
1068 E : uint8 last_block_header_byte = mem_dst[-1];
1069 E : mem_dst[-1] = 0;
1070 : EXPECT_EQ(mem_dst.get(),
1071 E : memcpyFunction(mem_dst.get(), mem_src.get() - 1, kAllocSize));
1072 E : EXPECT_TRUE(memory_error_detected);
1073 E : for (int i = -1; i < static_cast<int>(kAllocSize) - 1; ++i)
1074 E : EXPECT_EQ(mem_dst[i + 1], mem_src[i]);
1075 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1076 E : mem_dst[-1] = last_block_header_byte;
1077 E : ResetLog();
1078 E : }
1079 :
1080 E : TEST_F(AsanRtlTest, AsanCheckStrcspn) {
1081 E : const char* str_value = "abc1";
1082 E : ScopedASanAlloc<char> str(this, strlen(str_value) + 1);
1083 E : ASSERT_TRUE(str.get() != NULL);
1084 E : strcpy(str.get(), str_value);
1085 :
1086 E : const char* keys_value = "12";
1087 E : ScopedASanAlloc<char> keys(this, strlen(keys_value) + 1);
1088 E : ASSERT_TRUE(keys.get() != NULL);
1089 E : strcpy(keys.get(), keys_value);
1090 :
1091 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1092 E : memory_error_detected = false;
1093 :
1094 : EXPECT_EQ(strcspn(str.get(), keys.get()),
1095 E : strcspnFunction(str.get(), keys.get()));
1096 E : EXPECT_FALSE(memory_error_detected);
1097 :
1098 : // str[-1] points to the block header, we need to make sure that it doesn't
1099 : // contain the value \0.
1100 E : uint8 last_block_header_byte = str[-1];
1101 E : str[-1] = 'a';
1102 : EXPECT_EQ(strcspn(str.get() - 1, keys.get()),
1103 E : strcspnFunction(str.get() - 1, keys.get()));
1104 E : EXPECT_TRUE(memory_error_detected);
1105 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1106 E : str[-1] = last_block_header_byte;
1107 E : ResetLog();
1108 :
1109 E : memory_error_detected = false;
1110 E : size_t keys_len = strlen(keys.get());
1111 E : keys[keys_len] = 'a';
1112 E : keys[keys_len + 1] = 0;
1113 : EXPECT_EQ(strcspn(str.get(), keys.get()),
1114 E : strcspnFunction(str.get(), keys.get()));
1115 E : EXPECT_TRUE(memory_error_detected);
1116 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1117 E : ResetLog();
1118 E : }
1119 :
1120 E : TEST_F(AsanRtlTest, AsanCheckStrlen) {
1121 E : const char* str_value = "test_strlen";
1122 E : ScopedASanAlloc<char> str(this, strlen(str_value) + 1);
1123 E : ASSERT_TRUE(str != NULL);
1124 E : strcpy(str.get(), str_value);
1125 :
1126 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1127 E : memory_error_detected = false;
1128 :
1129 E : EXPECT_EQ(strlen(str.get()), strlenFunction(str.get()));
1130 E : EXPECT_FALSE(memory_error_detected);
1131 :
1132 : // str[-1] points to the block header, we need to make sure that it doesn't
1133 : // contain the value \0.
1134 E : uint8 last_block_header_byte = str[-1];
1135 E : str[-1] = 'a';
1136 E : EXPECT_EQ(strlen(str.get() - 1), strlenFunction(str.get() - 1));
1137 E : EXPECT_TRUE(memory_error_detected);
1138 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1139 E : str[-1] = last_block_header_byte;
1140 E : ResetLog();
1141 :
1142 E : memory_error_detected = false;
1143 E : size_t str_len = strlen(str.get());
1144 E : str[str_len] = 'a';
1145 E : str[str_len + 1] = 0;
1146 E : EXPECT_EQ(strlen(str.get()), strlenFunction(str.get()));
1147 E : EXPECT_TRUE(memory_error_detected);
1148 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1149 E : ResetLog();
1150 E : }
1151 :
1152 E : TEST_F(AsanRtlTest, AsanCheckStrrchr) {
1153 E : const char* str_value = "test_strrchr";
1154 E : ScopedASanAlloc<char> str(this, strlen(str_value) + 1);
1155 E : ASSERT_TRUE(str != NULL);
1156 E : strcpy(str.get(), str_value);
1157 :
1158 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1159 E : memory_error_detected = false;
1160 :
1161 E : EXPECT_EQ(strrchr(str.get(), 'c'), strrchrFunction(str.get(), 'c'));
1162 E : EXPECT_FALSE(memory_error_detected);
1163 E : EXPECT_EQ(strrchr(str.get(), 'z'), strrchrFunction(str.get(), 'z'));
1164 E : EXPECT_FALSE(memory_error_detected);
1165 :
1166 : // str[-1] points to the block header, we need to make sure that it doesn't
1167 : // contain the value \0.
1168 E : uint8 last_block_header_byte = str[-1];
1169 E : str[-1] = 'a';
1170 E : EXPECT_EQ(strrchr(str.get() - 1, 'c'), strrchrFunction(str.get() - 1, 'c'));
1171 E : EXPECT_TRUE(memory_error_detected);
1172 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1173 E : str[-1] = last_block_header_byte;
1174 E : ResetLog();
1175 :
1176 E : memory_error_detected = false;
1177 E : size_t str_len = strlen(str.get());
1178 E : str[str_len] = 'a';
1179 E : str[str_len + 1] = 0;
1180 E : EXPECT_EQ(strrchr(str.get(), 'c'), strrchrFunction(str.get(), 'c'));
1181 E : EXPECT_TRUE(memory_error_detected);
1182 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1183 E : ResetLog();
1184 E : }
1185 :
1186 E : TEST_F(AsanRtlTest, AsanCheckStrcmp) {
1187 E : const char* str_value = "test_strcmp";
1188 E : ScopedASanAlloc<char> str(this, strlen(str_value) + 1);
1189 E : ASSERT_TRUE(str.get() != NULL);
1190 E : strcpy(str.get(), str_value);
1191 :
1192 E : const char* keys_value = "strcmp";
1193 E : ScopedASanAlloc<char> keys(this, strlen(keys_value) + 1);
1194 E : ASSERT_TRUE(keys != NULL);
1195 E : strcpy(keys.get(), keys_value);
1196 :
1197 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1198 E : memory_error_detected = false;
1199 :
1200 : EXPECT_EQ(strcmp(str.get(), keys.get()),
1201 E : strcmpFunction(str.get(), keys.get()));
1202 E : EXPECT_FALSE(memory_error_detected);
1203 :
1204 : // str[-1] points to the block header, we need to make sure that it doesn't
1205 : // contain the value \0.
1206 E : uint8 last_block_header_byte = str[-1];
1207 E : str[-1] = 'a';
1208 : EXPECT_EQ(strcmp(str.get() - 1, keys.get()),
1209 E : strcmpFunction(str.get() - 1, keys.get()));
1210 E : EXPECT_TRUE(memory_error_detected);
1211 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1212 E : str[-1] = last_block_header_byte;
1213 E : ResetLog();
1214 :
1215 E : memory_error_detected = false;
1216 E : size_t keys_len = strlen(keys.get());
1217 E : keys[keys_len] = 'a';
1218 E : keys[keys_len + 1] = 0;
1219 : EXPECT_EQ(strcmp(str.get(), keys.get()),
1220 E : strcmpFunction(str.get(), keys.get()));
1221 E : EXPECT_TRUE(memory_error_detected);
1222 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1223 E : ResetLog();
1224 E : }
1225 :
1226 E : TEST_F(AsanRtlTest, AsanCheckStrpbrk) {
1227 E : const char* str_value = "test_strpbrk";
1228 E : ScopedASanAlloc<char> str(this, strlen(str_value) + 1);
1229 E : ASSERT_TRUE(str != NULL);
1230 E : strcpy(str.get(), str_value);
1231 :
1232 E : const char* keys_value = "strpbrk";
1233 E : ScopedASanAlloc<char> keys(this, strlen(keys_value) + 1);
1234 E : ASSERT_TRUE(keys != NULL);
1235 E : strcpy(keys.get(), keys_value);
1236 :
1237 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1238 E : memory_error_detected = false;
1239 :
1240 : EXPECT_EQ(strpbrk(str.get(), keys.get()),
1241 E : strpbrkFunction(str.get(), keys.get()));
1242 E : EXPECT_FALSE(memory_error_detected);
1243 :
1244 : // str[-1] points to the block header, we need to make sure that it doesn't
1245 : // contain the value \0.
1246 E : uint8 last_block_header_byte = str[-1];
1247 E : str[-1] = 'a';
1248 : EXPECT_EQ(strpbrk(str.get() - 1, keys.get()),
1249 E : strpbrkFunction(str.get() - 1, keys.get()));
1250 E : EXPECT_TRUE(memory_error_detected);
1251 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1252 E : str[-1] = last_block_header_byte;
1253 E : ResetLog();
1254 :
1255 E : memory_error_detected = false;
1256 E : size_t keys_len = strlen(keys.get());
1257 E : keys[keys_len] = 'a';
1258 E : keys[keys_len + 1] = 0;
1259 : EXPECT_EQ(strpbrk(str.get(), keys.get()),
1260 E : strpbrkFunction(str.get(), keys.get()));
1261 E : EXPECT_TRUE(memory_error_detected);
1262 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1263 E : ResetLog();
1264 E : }
1265 :
1266 E : TEST_F(AsanRtlTest, AsanCheckStrstr) {
1267 E : const char* str_value = "test_strstr";
1268 E : ScopedASanAlloc<char> str(this, strlen(str_value) + 1);
1269 E : ASSERT_TRUE(str != NULL);
1270 E : strcpy(str.get(), str_value);
1271 :
1272 E : const char* keys_value = "strstr";
1273 E : ScopedASanAlloc<char> keys(this, strlen(keys_value) + 1);
1274 E : ASSERT_TRUE(keys != NULL);
1275 E : strcpy(keys.get(), keys_value);
1276 :
1277 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1278 E : memory_error_detected = false;
1279 :
1280 : EXPECT_EQ(strstr(str.get(), keys.get()),
1281 E : strstrFunction(str.get(), keys.get()));
1282 E : EXPECT_FALSE(memory_error_detected);
1283 :
1284 : // str[-1] points to the block header, we need to make sure that it doesn't
1285 : // contain the value \0.
1286 E : uint8 last_block_header_byte = str[-1];
1287 E : str[-1] = 'a';
1288 : EXPECT_EQ(strstr(str.get() - 1, keys.get()),
1289 E : strstrFunction(str.get() - 1, keys.get()));
1290 E : EXPECT_TRUE(memory_error_detected);
1291 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1292 E : str[-1] = last_block_header_byte;
1293 E : ResetLog();
1294 :
1295 E : memory_error_detected = false;
1296 E : size_t keys_len = strlen(keys.get());
1297 E : keys[keys_len] = 'a';
1298 E : keys[keys_len + 1] = 0;
1299 : EXPECT_EQ(strstr(str.get(), keys.get()),
1300 E : strstrFunction(str.get(), keys.get()));
1301 E : EXPECT_TRUE(memory_error_detected);
1302 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1303 E : ResetLog();
1304 E : }
1305 :
1306 E : TEST_F(AsanRtlTest, AsanCheckStrspn) {
1307 E : const char* str_value = "test_strspn";
1308 E : ScopedASanAlloc<char> str(this, strlen(str_value) + 1);
1309 E : ASSERT_TRUE(str != NULL);
1310 E : strcpy(str.get(), str_value);
1311 :
1312 E : const char* keys_value = "strspn";
1313 E : ScopedASanAlloc<char> keys(this, strlen(keys_value) + 1);
1314 E : ASSERT_TRUE(keys != NULL);
1315 E : strcpy(keys.get(), keys_value);
1316 :
1317 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1318 E : memory_error_detected = false;
1319 :
1320 : EXPECT_EQ(strspn(str.get(), keys.get()),
1321 E : strspnFunction(str.get(), keys.get()));
1322 E : EXPECT_FALSE(memory_error_detected);
1323 :
1324 : // str[-1] points to the block header, we need to make sure that it doesn't
1325 : // contain the value \0.
1326 E : uint8 last_block_header_byte = str[-1];
1327 E : str[-1] = 'a';
1328 : EXPECT_EQ(strspn(str.get() - 1, keys.get()),
1329 E : strspnFunction(str.get() - 1, keys.get()));
1330 E : EXPECT_TRUE(memory_error_detected);
1331 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1332 E : str[-1] = last_block_header_byte;
1333 E : ResetLog();
1334 :
1335 E : memory_error_detected = false;
1336 E : size_t keys_len = strlen(keys.get());
1337 E : keys[keys_len] = 'a';
1338 E : keys[keys_len + 1] = 0;
1339 : EXPECT_EQ(strspn(str.get(), keys.get()),
1340 E : strspnFunction(str.get(), keys.get()));
1341 E : EXPECT_TRUE(memory_error_detected);
1342 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1343 E : ResetLog();
1344 E : }
1345 :
1346 E : TEST_F(AsanRtlTest, AsanCheckStrncpy) {
1347 E : const char* str_value = "test_strncpy";
1348 E : ScopedASanAlloc<char> source(this, strlen(str_value) + 1);
1349 E : ASSERT_TRUE(source != NULL);
1350 E : strcpy(source.get(), str_value);
1351 :
1352 E : const char* long_str_value = "test_strncpy_long_source";
1353 E : ScopedASanAlloc<char> long_source(this, strlen(long_str_value) + 1);
1354 E : ASSERT_TRUE(long_source.get() != NULL);
1355 E : strcpy(long_source.get(), long_str_value);
1356 :
1357 E : ScopedASanAlloc<char> destination(this, strlen(str_value) + 1);
1358 E : ASSERT_TRUE(destination != NULL);
1359 :
1360 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1361 E : memory_error_detected = false;
1362 :
1363 : EXPECT_EQ(destination.get(),
1364 : strncpyFunction(destination.get(),
1365 : source.get(),
1366 E : strlen(str_value)));
1367 E : EXPECT_FALSE(memory_error_detected);
1368 :
1369 : // Test an underflow on the source.
1370 E : uint8 last_block_header_byte = source[-1];
1371 E : source[-1] = 'a';
1372 : EXPECT_EQ(destination.get(),
1373 : strncpyFunction(destination.get(),
1374 : source.get() - 1,
1375 E : strlen(str_value)));
1376 E : EXPECT_TRUE(memory_error_detected);
1377 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1378 E : source[-1] = last_block_header_byte;
1379 E : ResetLog();
1380 :
1381 : // Test an underflow on the destination.
1382 E : memory_error_detected = false;
1383 E : last_block_header_byte = destination[-1];
1384 E : destination[-1] = 'a';
1385 : EXPECT_EQ(destination.get() - 1,
1386 : strncpyFunction(destination.get() - 1,
1387 : source.get(),
1388 E : strlen(str_value)));
1389 E : EXPECT_TRUE(memory_error_detected);
1390 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1391 E : destination[-1] = last_block_header_byte;
1392 E : ResetLog();
1393 :
1394 : // Test an overflow on the destination.
1395 E : memory_error_detected = false;
1396 : EXPECT_EQ(destination.get(),
1397 : strncpyFunction(destination.get(),
1398 : long_source.get(),
1399 E : strlen(long_str_value)));
1400 E : EXPECT_TRUE(memory_error_detected);
1401 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1402 E : ResetLog();
1403 :
1404 : // Another overflow on the destination.
1405 E : memory_error_detected = false;
1406 : EXPECT_EQ(destination,
1407 : strncpyFunction(destination.get(),
1408 : source.get(),
1409 E : strlen(str_value) + 2));
1410 E : EXPECT_TRUE(memory_error_detected);
1411 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1412 E : ResetLog();
1413 :
1414 : // Test an overflow on the source.
1415 E : size_t source_len = strlen(source.get());
1416 E : source[source_len] = 'a';
1417 E : source[source_len + 1] = 0;
1418 E : memory_error_detected = false;
1419 : EXPECT_EQ(destination.get(), strncpyFunction(destination.get(),
1420 : source.get(),
1421 E : strlen(source.get()) + 1));
1422 E : EXPECT_TRUE(memory_error_detected);
1423 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1424 E : ResetLog();
1425 :
1426 E : memory_error_detected = false;
1427 : EXPECT_EQ(destination.get(), strncpyFunction(destination.get(),
1428 : source.get(),
1429 E : strlen(source.get())));
1430 E : EXPECT_FALSE(memory_error_detected);
1431 E : ResetLog();
1432 E : }
1433 :
1434 E : TEST_F(AsanRtlTest, AsanCheckStrncat) {
1435 E : const char* prefix_value = "test_";
1436 E : const char* suffix_value = "strncat";
1437 : char buffer[64];
1438 :
1439 : ScopedASanAlloc<char> mem(this,
1440 E : strlen(prefix_value) + strlen(suffix_value) + 1);
1441 E : ASSERT_TRUE(mem != NULL);
1442 E : strcpy(mem.get(), prefix_value);
1443 E : strcpy(buffer, prefix_value);
1444 :
1445 E : ScopedASanAlloc<char> suffix(this, strlen(suffix_value) + 1);
1446 E : ASSERT_TRUE(mem.get() != NULL);
1447 E : strcpy(suffix.get(), suffix_value);
1448 :
1449 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1450 E : memory_error_detected = false;
1451 :
1452 : EXPECT_EQ(mem.get(),
1453 E : strncatFunction(mem.get(), suffix.get(), strlen(suffix_value)));
1454 E : EXPECT_FALSE(memory_error_detected);
1455 : EXPECT_STRCASEEQ(
1456 E : strncat(buffer, suffix.get(), strlen(suffix_value)), mem.get());
1457 :
1458 : // Test an underflow on the suffix.
1459 E : uint8 last_block_header_byte = suffix[-1];
1460 E : suffix[-1] = 'a';
1461 E : strcpy(mem.get(), prefix_value);
1462 E : strcpy(buffer, prefix_value);
1463 : EXPECT_EQ(mem.get(),
1464 E : strncatFunction(mem.get(), suffix.get() - 1, strlen(suffix_value)));
1465 E : EXPECT_TRUE(memory_error_detected);
1466 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1467 : EXPECT_STRCASEEQ(
1468 E : strncat(buffer, suffix.get() - 1, strlen(suffix_value)), mem.get());
1469 E : suffix[-1] = last_block_header_byte;
1470 E : ResetLog();
1471 :
1472 : // Test an underflow on the destination.
1473 E : memory_error_detected = false;
1474 E : last_block_header_byte = mem[-1];
1475 E : mem[-1] = 'a';
1476 E : strcpy(mem.get(), prefix_value);
1477 E : strcpy(buffer, prefix_value);
1478 : EXPECT_EQ(mem.get() - 1,
1479 E : strncatFunction(mem.get() - 1, suffix.get(), strlen(suffix_value)));
1480 E : EXPECT_TRUE(memory_error_detected);
1481 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
1482 : EXPECT_STRCASEEQ(
1483 E : strncat(buffer, suffix.get(), strlen(suffix_value)), mem.get());
1484 E : mem[-1] = last_block_header_byte;
1485 E : ResetLog();
1486 :
1487 : // Test an overflow on the suffix.
1488 E : size_t suffix_len = strlen(suffix.get());
1489 E : suffix[suffix_len] = 'a';
1490 E : suffix[suffix_len + 1] = 0;
1491 E : memory_error_detected = false;
1492 E : strcpy(mem.get(), prefix_value);
1493 E : strcpy(buffer, prefix_value);
1494 : EXPECT_EQ(mem.get(),
1495 E : strncatFunction(mem.get(), suffix.get(), strlen(suffix.get()) + 1));
1496 E : EXPECT_TRUE(memory_error_detected);
1497 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1498 : EXPECT_STRCASEEQ(
1499 E : strncat(buffer, suffix.get(), strlen(suffix.get())), mem.get());
1500 E : ResetLog();
1501 E : suffix[suffix_len] = 0;
1502 :
1503 : // Test an overflow on the destination.
1504 E : memory_error_detected = false;
1505 E : strcpy(mem.get(), prefix_value);
1506 E : strcpy(buffer, prefix_value);
1507 E : size_t prefix_len = strlen(prefix_value);
1508 E : mem[prefix_len] = 'a';
1509 E : mem[prefix_len + 1] = 0;
1510 E : buffer[prefix_len] = 'a';
1511 E : buffer[prefix_len + 1] = 0;
1512 : EXPECT_EQ(mem.get(),
1513 E : strncatFunction(mem.get(), suffix.get(), strlen(suffix.get())));
1514 E : EXPECT_TRUE(memory_error_detected);
1515 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1516 : EXPECT_STRCASEEQ(
1517 E : strncat(buffer, suffix.get(), strlen(suffix.get())), mem.get());
1518 E : ResetLog();
1519 E : }
1520 :
1521 : namespace {
1522 :
1523 : // Helps to test the asan_ReadFile function.
1524 : class AsanRtlReadFileTest : public AsanRtlTest {
1525 : public:
1526 : typedef AsanRtlTest Super;
1527 :
1528 E : AsanRtlReadFileTest() : temp_file_handle_(INVALID_HANDLE_VALUE) {
1529 E : }
1530 :
1531 E : void SetUp() OVERRIDE {
1532 E : Super::SetUp();
1533 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1534 E : ASSERT_NO_FATAL_FAILURE(CreateTempFile());
1535 E : }
1536 :
1537 E : void CreateTempFile() {
1538 E : ASSERT_EQ(kTestStringLength,
1539 : file_util::WriteFile(temp_file_.path(),
1540 : kTestString,
1541 : kTestStringLength));
1542 :
1543 : temp_file_handle_.Set(::CreateFile(temp_file_.path().value().c_str(),
1544 E : GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
1545 :
1546 E : ASSERT_NE(INVALID_HANDLE_VALUE, temp_file_handle_.Get());
1547 E : }
1548 :
1549 : static const char kTestString[];
1550 : static const size_t kTestStringLength;
1551 :
1552 : protected:
1553 : testing::ScopedTempFile temp_file_;
1554 :
1555 : base::win::ScopedHandle temp_file_handle_;
1556 : };
1557 :
1558 : const char AsanRtlReadFileTest::kTestString[] = "Test of asan_ReadFile";
1559 : const size_t AsanRtlReadFileTest::kTestStringLength =
1560 : sizeof(AsanRtlReadFileTest::kTestString);
1561 :
1562 : } // namespace
1563 :
1564 E : TEST_F(AsanRtlReadFileTest, AsanReadFile) {
1565 : // Test that the function works correctly with valid parameters. In this case
1566 : // we don't pass an OVERLAPPED structure to the function.
1567 E : DWORD bytes_read = 0;
1568 E : ScopedASanAlloc<char> alloc(this, kTestStringLength);
1569 : EXPECT_TRUE(ReadFileFunction(temp_file_handle_.Get(),
1570 : alloc.get(),
1571 : kTestStringLength,
1572 : &bytes_read,
1573 E : NULL));
1574 E : EXPECT_EQ(kTestStringLength, bytes_read);
1575 E : EXPECT_STREQ(kTestString, alloc.get());
1576 E : EXPECT_FALSE(memory_error_detected);
1577 E : }
1578 :
1579 E : TEST_F(AsanRtlReadFileTest, AsanReadFileWithOverlapped) {
1580 E : ScopedASanAlloc<char> alloc(this, kTestStringLength);
1581 : // Test that the function works correctly with valid parameters. Here we pass
1582 : // an OVERLAPPED structure to the function, which indicates that we want to do
1583 : // the read from a given offset.
1584 E : OVERLAPPED overlapped = {};
1585 : // Start the read from the middle of the test string.
1586 E : const size_t kOffset = kTestStringLength / 2;
1587 E : overlapped.Offset = kOffset;
1588 E : DWORD bytes_read = 0;
1589 : EXPECT_TRUE(ReadFileFunction(temp_file_handle_.Get(),
1590 : alloc.get(),
1591 : kTestStringLength,
1592 : &bytes_read,
1593 E : &overlapped));
1594 E : EXPECT_EQ(kTestStringLength - kOffset, bytes_read);
1595 E : EXPECT_STREQ(kTestString + kOffset, alloc.get());
1596 E : EXPECT_FALSE(memory_error_detected);
1597 E : }
1598 :
1599 E : TEST_F(AsanRtlReadFileTest, AsanReadFileOverflow) {
1600 : // Test that the function works correctly with valid parameters. In this case
1601 : // we don't pass an OVERLAPPED structure to the function.
1602 E : DWORD bytes_read = 0;
1603 E : ScopedASanAlloc<char> alloc(this, kTestStringLength);
1604 : EXPECT_TRUE(ReadFileFunction(temp_file_handle_.Get(),
1605 : alloc.get(),
1606 : kTestStringLength + 1,
1607 : &bytes_read,
1608 E : NULL));
1609 E : EXPECT_EQ(kTestStringLength, bytes_read);
1610 E : EXPECT_EQ(0U, ::strncmp(kTestString, alloc.get(), bytes_read));
1611 E : EXPECT_TRUE(memory_error_detected);
1612 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1613 E : }
1614 :
1615 E : TEST_F(AsanRtlReadFileTest, AsanReadFileUAFOnOverlapped) {
1616 E : ScopedASanAlloc<char> alloc(this, kTestStringLength);
1617 : // Test an use-after-free on the overlapped structure.
1618 E : ScopedASanAlloc<OVERLAPPED> overlapped(this, sizeof(OVERLAPPED));
1619 : // Start the read from the middle of the test string.
1620 E : const size_t kOffset = kTestStringLength / 2;
1621 E : overlapped->Offset = kOffset;
1622 E : DWORD bytes_read = 0;
1623 E : OVERLAPPED* overlapped_ptr = overlapped.get();
1624 E : overlapped.reset(NULL);
1625 : EXPECT_TRUE(ReadFileFunction(temp_file_handle_.Get(),
1626 : alloc.get(),
1627 : kTestStringLength,
1628 : &bytes_read,
1629 E : overlapped_ptr));
1630 E : EXPECT_EQ(kTestStringLength - kOffset, bytes_read);
1631 E : EXPECT_STREQ(kTestString + kOffset, alloc.get());
1632 E : EXPECT_TRUE(memory_error_detected);
1633 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapUseAfterFree));
1634 E : }
1635 :
1636 E : TEST_F(AsanRtlReadFileTest, AsanReadFileUseAfterFree) {
1637 : // Test if an use-after-free on the destination buffer is correctly detected.
1638 E : DWORD bytes_read = 0;
1639 E : ScopedASanAlloc<char> alloc(this, kTestStringLength);
1640 E : char* alloc_ptr = alloc.get();
1641 E : alloc.reset(NULL);
1642 : EXPECT_TRUE(ReadFileFunction(temp_file_handle_.Get(),
1643 : alloc_ptr,
1644 : kTestStringLength + 1,
1645 : &bytes_read,
1646 E : NULL));
1647 E : EXPECT_EQ(kTestStringLength, bytes_read);
1648 E : EXPECT_STREQ(kTestString, alloc_ptr);
1649 E : EXPECT_TRUE(memory_error_detected);
1650 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapUseAfterFree));
1651 E : }
1652 :
1653 : namespace {
1654 :
1655 : typedef ScopedASanAlloc<char>* AsanReadFileCallbackData;
1656 : AsanReadFileCallbackData readfile_callback_data = NULL;
1657 :
1658 E : void AsanReadFileCallback() {
1659 E : ASSERT_TRUE(readfile_callback_data != NULL);
1660 E : readfile_callback_data->reset(NULL);
1661 E : }
1662 :
1663 : } // namespace
1664 :
1665 E : TEST_F(AsanRtlReadFileTest, AsanReadFileUAFAfterInternalCall) {
1666 : // This test makes sure that use-after-free errors on the input buffer given
1667 : // to the ReadFile function are correctly detected.
1668 E : ScopedASanAlloc<char> alloc(this, kTestStringLength);
1669 E : memset(alloc.get(), 0, kTestStringLength);
1670 E : char* alloc_ptr = alloc.get();
1671 E : readfile_callback_data = &alloc;
1672 :
1673 : // Set the callback that we want to use once the internal call to ReadFile
1674 : // returns.
1675 E : SetInterceptorCallbackFunction(&AsanReadFileCallback);
1676 :
1677 : // Read from the file using the interceptor, this will call the ReadFile
1678 : // callback once the internal call to ReadFile returns, and result in freeing
1679 : // the buffer.
1680 E : DWORD bytes_read = 0;
1681 : EXPECT_TRUE(ReadFileFunction(temp_file_handle_.Get(),
1682 : alloc.get(),
1683 : kTestStringLength,
1684 : &bytes_read,
1685 E : NULL));
1686 :
1687 E : EXPECT_EQ(kTestStringLength, bytes_read);
1688 E : EXPECT_STREQ(kTestString, alloc_ptr);
1689 E : EXPECT_TRUE(memory_error_detected);
1690 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapUseAfterFree));
1691 :
1692 E : SetInterceptorCallbackFunction(NULL);
1693 E : }
1694 :
1695 : namespace {
1696 :
1697 : // Helps to test the asan_WriteFile function.
1698 : class AsanRtlWriteFileTest : public AsanRtlTest {
1699 : public:
1700 : typedef AsanRtlTest Super;
1701 :
1702 E : AsanRtlWriteFileTest()
1703 : : temp_file_handle_(INVALID_HANDLE_VALUE) {
1704 E : }
1705 :
1706 E : void SetUp() OVERRIDE {
1707 E : Super::SetUp();
1708 :
1709 : temp_file_handle_.Set(::CreateFile(temp_file_.path().value().c_str(),
1710 : GENERIC_READ | GENERIC_WRITE,
1711 : 0,
1712 : NULL,
1713 : OPEN_EXISTING,
1714 : FILE_ATTRIBUTE_NORMAL,
1715 E : NULL));
1716 E : ASSERT_NE(INVALID_HANDLE_VALUE, temp_file_handle_.Get());
1717 E : SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
1718 E : }
1719 :
1720 E : bool ReadFileContent(std::string* pipe_content, size_t kOffset) {
1721 E : EXPECT_TRUE(pipe_content != NULL);
1722 E : const size_t kMaxContentLength = 64;
1723 E : pipe_content->clear();
1724 E : pipe_content->resize(kMaxContentLength);
1725 E : DWORD bytes_read = 0;
1726 E : ::SetFilePointer(temp_file_handle_.Get(), kOffset, 0, FILE_BEGIN);
1727 : if (::ReadFile(temp_file_handle_.Get(),
1728 : &(*pipe_content)[0],
1729 : kMaxContentLength,
1730 : &bytes_read,
1731 E : NULL) == FALSE) {
1732 i : return false;
1733 : }
1734 : // Ensures that the buffer is big enough to store the pipe content.
1735 E : EXPECT_TRUE(bytes_read < kMaxContentLength);
1736 :
1737 E : return true;
1738 E : }
1739 :
1740 : static const char kTestString[];
1741 : static const size_t kTestStringLength;
1742 :
1743 : protected:
1744 : testing::ScopedTempFile temp_file_;
1745 :
1746 : base::win::ScopedHandle temp_file_handle_;
1747 : };
1748 :
1749 : const char AsanRtlWriteFileTest::kTestString[] = "Test of asan_WriteFile";
1750 : const size_t AsanRtlWriteFileTest::kTestStringLength =
1751 : sizeof(AsanRtlWriteFileTest::kTestString);
1752 :
1753 : } // namespace
1754 :
1755 E : TEST_F(AsanRtlWriteFileTest, AsanWriteFile) {
1756 : // Test that the function works correctly with valid parameters. In this case
1757 : // we don't pass an OVERLAPPED structure to the function.
1758 E : DWORD bytes_written = 0;
1759 E : ScopedASanAlloc<char> alloc(this, kTestStringLength);
1760 : EXPECT_TRUE(WriteFileFunction(temp_file_handle_.Get(),
1761 : kTestString,
1762 : kTestStringLength,
1763 : &bytes_written,
1764 E : NULL));
1765 E : EXPECT_EQ(kTestStringLength, bytes_written);
1766 E : EXPECT_FALSE(memory_error_detected);
1767 E : std::string file_content;
1768 E : EXPECT_TRUE(ReadFileContent(&file_content, 0));
1769 E : EXPECT_STREQ(kTestString, file_content.c_str());
1770 E : }
1771 :
1772 E : TEST_F(AsanRtlWriteFileTest, AsanWriteFileWithOverlapped) {
1773 E : ScopedASanAlloc<char> alloc(this, kTestStringLength);
1774 : // Test that the function works correctly with valid parameters. Here we pass
1775 : // an OVERLAPPED structure to the function, which indicates that we want to do
1776 : // the write after a given offset.
1777 E : OVERLAPPED overlapped = {};
1778 : // Start the write from the middle of the test string.
1779 E : const size_t kOffset = kTestStringLength / 2;
1780 E : overlapped.Offset = kOffset;
1781 E : DWORD bytes_written = 0;
1782 : EXPECT_TRUE(WriteFileFunction(temp_file_handle_.Get(),
1783 : kTestString + kOffset,
1784 : kTestStringLength - kOffset,
1785 : &bytes_written,
1786 E : &overlapped));
1787 E : EXPECT_EQ(kTestStringLength - kOffset, bytes_written);
1788 E : EXPECT_FALSE(memory_error_detected);
1789 E : std::string file_content;
1790 E : EXPECT_TRUE(ReadFileContent(&file_content, kOffset));
1791 E : EXPECT_STREQ(kTestString + kOffset, file_content.c_str());
1792 E : }
1793 :
1794 E : TEST_F(AsanRtlWriteFileTest, AsanWriteFileOverflow) {
1795 : // Test that the function works correctly with valid parameters. In this case
1796 : // we don't pass an OVERLAPPED structure to the function.
1797 E : DWORD bytes_written = 0;
1798 E : ScopedASanAlloc<char> alloc(this, kTestStringLength);
1799 E : strcpy(alloc.get(), kTestString);
1800 : EXPECT_TRUE(WriteFileFunction(temp_file_handle_.Get(),
1801 : alloc.get(),
1802 : kTestStringLength + 1,
1803 : &bytes_written,
1804 E : NULL));
1805 E : EXPECT_EQ(kTestStringLength + 1, bytes_written);
1806 E : EXPECT_TRUE(memory_error_detected);
1807 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
1808 E : std::string file_content;
1809 E : EXPECT_TRUE(ReadFileContent(&file_content, 0));
1810 E : EXPECT_STREQ(kTestString, file_content.c_str());
1811 E : }
1812 :
1813 E : TEST_F(AsanRtlWriteFileTest, AsanWriteFileUAFOnOverlapped) {
1814 : // Test an use-after-free on the overlapped structure.
1815 E : ScopedASanAlloc<OVERLAPPED> overlapped(this, sizeof(OVERLAPPED));
1816 : // Start the write from the middle of the test string.
1817 E : const size_t kOffset = kTestStringLength / 2;
1818 E : overlapped->Offset = kOffset;
1819 E : DWORD bytes_written = 0;
1820 E : OVERLAPPED* overlapped_ptr = overlapped.get();
1821 E : overlapped.reset(NULL);
1822 : EXPECT_TRUE(WriteFileFunction(temp_file_handle_.Get(),
1823 : kTestString + kOffset,
1824 : kTestStringLength - kOffset,
1825 : &bytes_written,
1826 E : overlapped_ptr));
1827 E : EXPECT_EQ(kTestStringLength - kOffset, bytes_written);
1828 E : EXPECT_TRUE(memory_error_detected);
1829 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapUseAfterFree));
1830 E : std::string file_content;
1831 E : EXPECT_TRUE(ReadFileContent(&file_content, kOffset));
1832 E : EXPECT_STREQ(kTestString + kOffset, file_content.c_str());
1833 E : }
1834 :
1835 E : TEST_F(AsanRtlWriteFileTest, AsanWriteFileUseAfterFree) {
1836 : // Test if an use-after-free on the destination buffer is correctly detected.
1837 E : DWORD bytes_written = 0;
1838 E : ScopedASanAlloc<char> alloc(this, kTestStringLength);
1839 E : strcpy(alloc.get(), kTestString);
1840 E : char* alloc_ptr = alloc.get();
1841 E : alloc.reset(NULL);
1842 : EXPECT_TRUE(WriteFileFunction(temp_file_handle_.Get(),
1843 : alloc_ptr,
1844 : kTestStringLength,
1845 : &bytes_written,
1846 E : NULL));
1847 E : EXPECT_EQ(kTestStringLength, bytes_written);
1848 E : EXPECT_TRUE(memory_error_detected);
1849 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapUseAfterFree));
1850 E : std::string file_content;
1851 E : EXPECT_TRUE(ReadFileContent(&file_content, 0));
1852 E : EXPECT_STREQ(kTestString, file_content.c_str());
1853 E : }
1854 :
1855 : namespace {
1856 :
1857 : typedef ScopedASanAlloc<char>* AsanWriteFileCallbackData;
1858 : AsanWriteFileCallbackData writefile_callback_data = NULL;
1859 :
1860 E : void AsanWriteFileCallback() {
1861 E : ASSERT_TRUE(writefile_callback_data != NULL);
1862 E : writefile_callback_data->reset(NULL);
1863 E : }
1864 :
1865 : } // namespace
1866 :
1867 E : TEST_F(AsanRtlWriteFileTest, AsanWriteFileUAFAfterInternalCall) {
1868 : // This test makes sure that use-after-free errors on the input buffer given
1869 : // to the WriteFile function are correctly detected.
1870 E : ScopedASanAlloc<char> alloc(this, kTestStringLength);
1871 E : strcpy(alloc.get(), kTestString);
1872 :
1873 E : writefile_callback_data = &alloc;
1874 :
1875 : // Set the callback that we want to use once the internal call to WriteFile
1876 : // returns.
1877 E : SetInterceptorCallbackFunction(&AsanWriteFileCallback);
1878 :
1879 : // Write to the file using the interceptor, this will call the WriteFile
1880 : // callback once the internal call to WriteFile returns, and result in freeing
1881 : // the buffer.
1882 E : DWORD bytes_written = 0;
1883 : EXPECT_TRUE(WriteFileFunction(temp_file_handle_.Get(),
1884 : alloc.get(),
1885 : kTestStringLength,
1886 : &bytes_written,
1887 E : NULL));
1888 :
1889 E : EXPECT_EQ(kTestStringLength, bytes_written);
1890 :
1891 E : EXPECT_TRUE(memory_error_detected);
1892 E : EXPECT_TRUE(LogContains(HeapProxy::kHeapUseAfterFree));
1893 :
1894 E : std::string file_content;
1895 E : EXPECT_TRUE(ReadFileContent(&file_content, 0));
1896 E : EXPECT_STREQ(kTestString, file_content.c_str());
1897 :
1898 E : SetInterceptorCallbackFunction(NULL);
1899 E : }
1900 :
1901 : } // namespace asan
1902 : } // namespace agent
|