1 : // Copyright 2014 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 "syzygy/agent/asan/crt_interceptors.h"
16 :
17 : #include <windows.h>
18 :
19 : #include "base/bind.h"
20 : #include "gtest/gtest.h"
21 : #include "syzygy/agent/asan/unittest_util.h"
22 :
23 : namespace agent {
24 : namespace asan {
25 :
26 : namespace {
27 :
28 : using testing::ScopedAsanAlloc;
29 :
30 : typedef testing::TestAsanRtl CrtInterceptorsTest;
31 :
32 : // An arbitrary size for the buffer we allocate in the different unittests.
33 : const size_t kAllocSize = 13;
34 :
35 E : void AsanErrorCallback(AsanErrorInfo* error_info) {
36 : // Our tests should clean up after themselves and not leave any blocks
37 : // corrupt.
38 E : ASSERT_NE(CORRUPT_BLOCK, error_info->error_type);
39 :
40 : // Raise an exception to prevent the intercepted function from corrupting
41 : // the block. If this error is not handled then this will cause the unittest
42 : // to fail.
43 E : ::RaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED, 0, 0, 0);
44 i : }
45 :
46 : } // namespace
47 :
48 E : TEST_F(CrtInterceptorsTest, AsanCheckMemset) {
49 E : const size_t kAllocSize = 13;
50 E : ScopedAsanAlloc<uint8_t> mem(this, kAllocSize);
51 E : ASSERT_TRUE(mem.get() != NULL);
52 E : SetCallBackFunction(&AsanErrorCallback);
53 E : EXPECT_EQ(mem.get(), memsetFunction(mem.GetAs<void*>(), 0xAA, kAllocSize));
54 E : for (size_t i = 0; i < kAllocSize; ++i)
55 E : EXPECT_EQ(0xAA, mem[i]);
56 :
57 E : memsetFunctionFailing(mem.get() - 1, 0xBB, kAllocSize);
58 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
59 E : ResetLog();
60 :
61 E : memsetFunctionFailing(mem.get(), 0xCC, kAllocSize + 1);
62 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
63 E : ResetLog();
64 E : }
65 :
66 E : TEST_F(CrtInterceptorsTest, AsanCheckMemchr) {
67 E : const size_t kAllocSize = 13;
68 E : ScopedAsanAlloc<uint8_t> mem(this, kAllocSize);
69 E : ASSERT_TRUE(mem.get() != NULL);
70 E : ::memset(mem.get(), 0, kAllocSize);
71 E : mem[4] = 0xAA;
72 :
73 E : SetCallBackFunction(&AsanErrorCallback);
74 E : EXPECT_EQ(mem.get() + 4, memchrFunction(mem.get(), mem[4], kAllocSize));
75 E : EXPECT_EQ(NULL, memchrFunction(mem.get(), mem[4] + 1, kAllocSize));
76 :
77 E : memchrFunctionFailing(mem.get() - 1, mem[4], kAllocSize);
78 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
79 E : ResetLog();
80 :
81 E : memchrFunctionFailing(mem.get() + 1, mem[4], kAllocSize);
82 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
83 E : ResetLog();
84 E : }
85 :
86 E : TEST_F(CrtInterceptorsTest, AsanCheckMemmove) {
87 E : const uint8_t kAllocSize = 13;
88 E : ScopedAsanAlloc<uint8_t> mem_src(this, kAllocSize);
89 E : ASSERT_TRUE(mem_src.get() != NULL);
90 : // Fill the array with value going from 0 to kAllocSize;
91 E : for (uint8_t i = 0; i < kAllocSize; ++i)
92 E : mem_src[i] = i;
93 :
94 E : SetCallBackFunction(&AsanErrorCallback);
95 : // Shift all the value from one index to the right.
96 E : EXPECT_EQ(mem_src.get() + 1,
97 E : memmoveFunction(mem_src.get() + 1, mem_src.get(), kAllocSize - 1));
98 E : EXPECT_EQ(0, mem_src[0]);
99 E : for (uint8_t i = 1; i < kAllocSize; ++i)
100 E : EXPECT_EQ(i - 1, mem_src[i]);
101 :
102 : // Re-shift them to the left.
103 E : memmoveFunctionFailing(mem_src.get(), mem_src.get() + 1, kAllocSize);
104 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
105 E : ResetLog();
106 :
107 E : memmoveFunctionFailing(mem_src.get() - 1, mem_src.get(), kAllocSize);
108 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
109 E : ResetLog();
110 E : }
111 :
112 E : TEST_F(CrtInterceptorsTest, AsanCheckMemcpy) {
113 E : const uint8_t kAllocSize = 13;
114 E : ScopedAsanAlloc<uint8_t> mem_src(this, kAllocSize);
115 E : ASSERT_TRUE(mem_src.get() != NULL);
116 E : ScopedAsanAlloc<uint8_t> mem_dst(this, kAllocSize);
117 E : ASSERT_TRUE(mem_dst.get() != NULL);
118 : // Fill the array with value going from 0 to kAllocSize;
119 E : for (uint8_t i = 0; i < kAllocSize; ++i) {
120 E : mem_src[i] = i;
121 E : mem_dst[i] = ~i;
122 E : }
123 :
124 E : SetCallBackFunction(&AsanErrorCallback);
125 E : EXPECT_EQ(mem_dst.get(),
126 E : memcpyFunction(mem_dst.get(), mem_src.get(), kAllocSize));
127 E : for (size_t i = 0; i < kAllocSize; ++i)
128 E : EXPECT_EQ(mem_dst[i], mem_src[i]);
129 :
130 E : memcpyFunctionFailing(mem_dst.get(), mem_src.get(), kAllocSize + 1);
131 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
132 E : ResetLog();
133 :
134 E : memcpyFunctionFailing(mem_dst.get(), mem_src.get() - 1, kAllocSize);
135 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
136 E : ResetLog();
137 E : }
138 :
139 E : TEST_F(CrtInterceptorsTest, DISABLED_AsanCheckStrcspn) {
140 : // TODO(sebmarchand): Reactivate this unittest once the implementation of
141 : // this interceptor has been fixed.
142 i : const char* str_value = "abc1";
143 i : ScopedAsanAlloc<char> str(this, ::strlen(str_value) + 1, str_value);
144 i : ASSERT_TRUE(str.get() != NULL);
145 :
146 i : const char* str_value_2 = "abc";
147 i : ScopedAsanAlloc<char> str2(this, ::strlen(str_value_2) + 1, str_value_2);
148 i : ASSERT_TRUE(str2.get() != NULL);
149 :
150 : // This should contain at least one value present in |str| but none present
151 : // in |str2|.
152 i : const char* keys_value = "12";
153 i : EXPECT_NE(::strlen(str_value), ::strcspn(str_value, keys_value));
154 i : EXPECT_EQ(::strlen(str_value_2), ::strcspn(str_value_2, keys_value));
155 i : ScopedAsanAlloc<char> keys(this, ::strlen(keys_value) + 1, keys_value);
156 i : ASSERT_TRUE(keys.get() != NULL);
157 :
158 i : SetCallBackFunction(&AsanErrorCallback);
159 i : EXPECT_EQ(::strcspn(str.get(), keys.get()),
160 i : strcspnFunction(str.get(), keys.get()));
161 :
162 i : strcspnFunctionFailing(str.get() - 1, keys.get());
163 i : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
164 i : ResetLog();
165 :
166 : // The key set should be null terminated, otherwise an overflow should be
167 : // detected.
168 i : size_t keys_len = ::strlen(keys.get());
169 i : keys[keys_len] = 'a';
170 i : strcspnFunctionFailing(str.get(), keys.get());
171 i : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
172 i : keys[keys_len] = 0;
173 i : ResetLog();
174 :
175 : // The implementation allows a non null terminated input string if it contains
176 : // at least one of the keys, otherwise it'll overflow.
177 :
178 i : size_t str_len = ::strlen(str.get());
179 i : str[str_len] = 'a';
180 i : EXPECT_EQ(::strcspn(str.get(), keys.get()),
181 i : strcspnFunction(str.get(), keys.get()));
182 i : str[str_len] = 0;
183 i : ResetLog();
184 :
185 i : size_t str2_len = ::strlen(str2.get());
186 i : str2[str2_len] = 'a';
187 i : strcspnFunctionFailing(str2.get(), keys.get());
188 i : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
189 i : str2[str2_len] = 0;
190 i : ResetLog();
191 i : }
192 :
193 E : TEST_F(CrtInterceptorsTest, DISABLED_AsanStrcspnImpl) {
194 : // TODO(sebmarchand): Reactivate this unittest once the implementation of
195 : // this interceptor has been fixed.
196 i : EXPECT_EQ(5, asan_strcspn("abcde", "fgh"));
197 i : EXPECT_EQ(5, asan_strcspn("abcde", ""));
198 i : EXPECT_EQ(0, asan_strcspn("abcde", "abcde"));
199 i : EXPECT_EQ(0U, asan_strcspn("abcde", "edcba"));
200 i : EXPECT_EQ(3, asan_strcspn("abcde", "ed"));
201 i : EXPECT_EQ(2, asan_strcspn("abcde", "c"));
202 i : EXPECT_EQ(0U, asan_strcspn("", ""));
203 i : EXPECT_EQ(0U, asan_strcspn("", "abcde"));
204 i : }
205 :
206 E : TEST_F(CrtInterceptorsTest, AsanCheckStrlen) {
207 E : const char* str_value = "test_strlen";
208 E : ScopedAsanAlloc<char> str(this, ::strlen(str_value) + 1, str_value);
209 E : ASSERT_TRUE(str != NULL);
210 :
211 E : SetCallBackFunction(&AsanErrorCallback);
212 E : EXPECT_EQ(::strlen(str.get()), strlenFunction(str.get()));
213 :
214 E : strlenFunctionFailing(str.get() - 1);
215 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
216 E : ResetLog();
217 :
218 E : size_t str_len = ::strlen(str.get());
219 E : str[str_len] = 'a';
220 E : strlenFunctionFailing(str.get());
221 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
222 E : ResetLog();
223 E : }
224 :
225 E : TEST_F(CrtInterceptorsTest, AsanCheckStrnlen) {
226 E : const char str_value[] = "test_strnlen";
227 E : const size_t str_len = arraysize(str_value);
228 E : ScopedAsanAlloc<char> str(this, str_len, str_value);
229 E : ASSERT_TRUE(str != NULL);
230 :
231 E : SetCallBackFunction(&AsanErrorCallback);
232 E : EXPECT_EQ(::strnlen(str.get(), str_len), strnlenFunction(str.get(), str_len));
233 :
234 E : strnlenFunctionFailing(str.get() - 1, str_len);
235 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
236 E : ResetLog();
237 :
238 E : size_t n = ::strlen(str.get());
239 E : str[n] = 'a';
240 E : strnlenFunctionFailing(str.get(), str_len + 1);
241 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
242 E : ResetLog();
243 E : }
244 :
245 E : TEST_F(CrtInterceptorsTest, AsanCheckStrrchr) {
246 E : const char* str_value = "test_strrchr";
247 E : ScopedAsanAlloc<char> str(this, ::strlen(str_value) + 1, str_value);
248 E : ASSERT_TRUE(str != NULL);
249 :
250 E : SetCallBackFunction(&AsanErrorCallback);
251 E : EXPECT_EQ(::strrchr(str.get(), 'c'), strrchrFunction(str.get(), 'c'));
252 E : EXPECT_EQ(::strrchr(str.get(), 'z'), strrchrFunction(str.get(), 'z'));
253 :
254 E : strrchrFunctionFailing(str.get() - 1, 'c');
255 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
256 E : ResetLog();
257 :
258 E : size_t str_len = ::strlen(str.get());
259 E : str[str_len] = 'a';
260 E : strrchrFunctionFailing(str.get(), 'c');
261 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
262 E : ResetLog();
263 E : }
264 :
265 E : TEST_F(CrtInterceptorsTest, AsanCheckWcsnlen) {
266 E : const wchar_t str_value[] = L"test_wcsnlen";
267 E : const size_t str_len = arraysize(str_value);
268 E : ScopedAsanAlloc<wchar_t> str(this, str_len, str_value);
269 E : ASSERT_TRUE(str != NULL);
270 :
271 E : SetCallBackFunction(&AsanErrorCallback);
272 E : EXPECT_EQ(::wcsnlen(str.get(), str_len),
273 E : wcsnlenFunction(str.get(), str_len));
274 :
275 E : wcsnlenFunctionFailing(str.get() - 1, str_len);
276 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
277 E : ResetLog();
278 :
279 E : size_t n = ::wcslen(str.get());
280 E : str[n] = 'a';
281 E : wcsnlenFunctionFailing(str.get(), str_len + 1);
282 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
283 E : ResetLog();
284 E : }
285 :
286 E : TEST_F(CrtInterceptorsTest, AsanCheckWcsrchr) {
287 E : const wchar_t* wstr_value = L"test_wcsrchr";
288 E : ScopedAsanAlloc<wchar_t> wstr(this, ::wcslen(wstr_value) + 1);
289 E : ASSERT_TRUE(wstr != NULL);
290 E : wcscpy(wstr.get(), wstr_value);
291 :
292 E : SetCallBackFunction(&AsanErrorCallback);
293 E : EXPECT_EQ(::wcsrchr(wstr.get(), L'c'), wcsrchrFunction(wstr.get(), L'c'));
294 E : EXPECT_EQ(::wcsrchr(wstr.get(), 'z'), wcsrchrFunction(wstr.get(), 'z'));
295 :
296 E : wcsrchrFunctionFailing(wstr.get() - 1, L'c');
297 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
298 E : ResetLog();
299 :
300 E : size_t str_len = ::wcslen(wstr_value);
301 E : wstr[str_len] = L'a';
302 E : wcsrchrFunctionFailing(wstr.get(), L'c');
303 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
304 E : ResetLog();
305 E : }
306 :
307 E : TEST_F(CrtInterceptorsTest, AsanCheckWcschr) {
308 E : const wchar_t* wstr_value = L"test_wcschr";
309 E : ScopedAsanAlloc<wchar_t> wstr(this, ::wcslen(wstr_value) + 1);
310 E : ASSERT_TRUE(wstr != NULL);
311 E : wcscpy(wstr.get(), wstr_value);
312 :
313 E : SetCallBackFunction(&AsanErrorCallback);
314 E : EXPECT_EQ(::wcschr(wstr.get(), L'c'), wcschrFunction(wstr.get(), L'c'));
315 E : EXPECT_EQ(::wcschr(wstr.get(), 'z'), wcschrFunction(wstr.get(), 'z'));
316 :
317 E : wcschrFunctionFailing(wstr.get() - 1, L'c');
318 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
319 E : ResetLog();
320 :
321 E : size_t str_len = ::wcslen(wstr_value);
322 E : wstr[str_len] = L'a';
323 E : wcschrFunctionFailing(wstr.get(), L'z');
324 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
325 E : ResetLog();
326 E : }
327 :
328 E : TEST_F(CrtInterceptorsTest, DISABLED_AsanCheckStrcmp) {
329 : // TODO(sebmarchand): Reactivate this unittest once the implementation of
330 : // this interceptor has been fixed.
331 i : const char* str_value = "test_strcmp";
332 i : ScopedAsanAlloc<char> str(this, ::strlen(str_value) + 1, str_value);
333 i : ASSERT_TRUE(str.get() != NULL);
334 :
335 i : const char* keys_value = "strcmp";
336 i : ScopedAsanAlloc<char> keys(this, ::strlen(keys_value) + 1, keys_value);
337 i : ASSERT_TRUE(keys.get() != NULL);
338 :
339 i : SetCallBackFunction(&AsanErrorCallback);
340 i : EXPECT_EQ(::strcmp(str.get(), keys.get()),
341 i : strcmpFunction(str.get(), keys.get()));
342 :
343 i : strcmpFunctionFailing(str.get() - 1, keys.get());
344 i : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
345 i : ResetLog();
346 :
347 i : size_t keys_len = ::strlen(keys.get());
348 i : keys[keys_len] = 'a';
349 i : strcmpFunctionFailing(str.get(), keys.get());
350 i : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
351 i : keys[keys_len] = 0;
352 i : ResetLog();
353 i : }
354 :
355 E : TEST_F(CrtInterceptorsTest, DISABLED_AsanCheckStrpbrk) {
356 : // TODO(sebmarchand): Reactivate this unittest once the implementation of
357 : // this interceptor has been fixed.
358 i : const char* str_value = "abc1";
359 i : ScopedAsanAlloc<char> str(this, ::strlen(str_value) + 1, str_value);
360 i : ASSERT_TRUE(str.get() != NULL);
361 :
362 i : const char* str_value_2 = "abc";
363 i : ScopedAsanAlloc<char> str2(this, ::strlen(str_value_2) + 1, str_value_2);
364 i : ASSERT_TRUE(str2.get() != NULL);
365 :
366 : // This should contain at least one value present in |str| but none present
367 : // in |str2|.
368 i : const char* keys_value = "12";
369 i : EXPECT_NE(::strlen(str_value), ::strcspn(str_value, keys_value));
370 i : EXPECT_EQ(::strlen(str_value_2), ::strcspn(str_value_2, keys_value));
371 i : ScopedAsanAlloc<char> keys(this, ::strlen(keys_value) + 1, keys_value);
372 i : ASSERT_TRUE(keys.get() != NULL);
373 :
374 i : SetCallBackFunction(&AsanErrorCallback);
375 i : EXPECT_EQ(::strpbrk(str.get(), keys.get()),
376 i : strpbrkFunction(str.get(), keys.get()));
377 :
378 i : strpbrkFunctionFailing(str.get() - 1, keys.get());
379 i : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
380 i : ResetLog();
381 :
382 i : size_t keys_len = ::strlen(keys.get());
383 i : keys[keys_len] = 'a';
384 i : strpbrkFunctionFailing(str.get(), keys.get());
385 i : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
386 i : keys[keys_len] = 0;
387 i : ResetLog();
388 :
389 : // The implementation allows a non null terminated input string if it contains
390 : // at least one of the keys, otherwise it'll overflow.
391 :
392 i : size_t str_len = ::strlen(str.get());
393 i : str[str_len] = 'a';
394 i : EXPECT_EQ(::strpbrk(str.get(), keys.get()),
395 i : strpbrkFunction(str.get(), keys.get()));
396 i : str[str_len] = 0;
397 i : ResetLog();
398 :
399 i : size_t str2_len = ::strlen(str2.get());
400 i : str2[str2_len] = 'a';
401 i : strpbrkFunctionFailing(str2.get(), keys.get());
402 i : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
403 i : str2[str2_len] = 0;
404 i : ResetLog();
405 i : }
406 :
407 E : TEST_F(CrtInterceptorsTest, DISABLED_AsanStrpbrkImpl) {
408 : // TODO(sebmarchand): Reactivate this unittest once the implementation of
409 : // this interceptor has been fixed.
410 i : const char* abcde = "abcde";
411 i : const char* empty_string = "";
412 i : EXPECT_EQ(strpbrk(abcde, abcde), asan_strpbrk(abcde, abcde));
413 i : EXPECT_EQ(strpbrk(abcde, "fgh"), asan_strpbrk(abcde, "fgh"));
414 i : EXPECT_EQ(strpbrk(abcde, ""), asan_strpbrk(abcde, ""));
415 i : EXPECT_EQ(strpbrk(abcde, "edcba"), asan_strpbrk(abcde, "edcba"));
416 i : EXPECT_EQ(strpbrk(abcde, "ed"), asan_strpbrk(abcde, "ed"));
417 i : EXPECT_EQ(strpbrk(abcde, "c"), asan_strpbrk(abcde, "c"));
418 i : EXPECT_EQ(strpbrk(empty_string, ""), asan_strpbrk(empty_string, ""));
419 i : EXPECT_EQ(strpbrk(empty_string, abcde), asan_strpbrk(empty_string, abcde));
420 i : }
421 :
422 E : TEST_F(CrtInterceptorsTest, DISABLED_AsanCheckStrstr) {
423 : // TODO(sebmarchand): Reactivate this unittest once the implementation of
424 : // this interceptor has been fixed.
425 i : const char* str_value = "test_strstr";
426 i : ScopedAsanAlloc<char> str(this, ::strlen(str_value) + 1, str_value);
427 i : ASSERT_TRUE(str != NULL);
428 :
429 i : const char* keys_value = "strstr";
430 i : ScopedAsanAlloc<char> keys(this, ::strlen(keys_value) + 1, keys_value);
431 i : ASSERT_TRUE(keys.get() != NULL);
432 :
433 i : SetCallBackFunction(&AsanErrorCallback);
434 i : EXPECT_EQ(::strstr(str.get(), keys.get()),
435 i : strstrFunction(str.get(), keys.get()));
436 :
437 i : strstrFunctionFailing(str.get() - 1, keys.get());
438 i : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
439 i : ResetLog();
440 :
441 i : size_t keys_len = ::strlen(keys.get());
442 i : keys[keys_len] = 'a';
443 i : strstrFunctionFailing(str.get(), keys.get());
444 i : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
445 i : keys[keys_len] = 0;
446 i : ResetLog();
447 i : }
448 :
449 E : TEST_F(CrtInterceptorsTest, AsanCheckWcsstr) {
450 E : const wchar_t* str_value = L"test_wcsstr";
451 E : ScopedAsanAlloc<wchar_t> str(this, ::wcslen(str_value) + 1, str_value);
452 E : ASSERT_TRUE(str != NULL);
453 :
454 E : const wchar_t* keys_value = L"wcsstr";
455 E : ScopedAsanAlloc<wchar_t> keys(this, ::wcslen(keys_value) + 1, keys_value);
456 E : ASSERT_TRUE(keys.get() != NULL);
457 :
458 E : EXPECT_EQ(::wcsstr(str.get(), keys.get()),
459 E : wcsstrFunction(str.get(), keys.get()));
460 :
461 E : EXPECT_EQ(NULL, wcsstrFunction(str.get(), L"abcd"));
462 :
463 E : SetCallBackFunction(&AsanErrorCallback);
464 E : keys[::wcslen(keys_value)] = L'a';
465 E : wcsstrFunctionFailing(str.get(), keys.get());
466 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
467 E : keys[::wcslen(keys_value)] = 0;
468 :
469 E : ResetLog();
470 E : }
471 :
472 E : TEST_F(CrtInterceptorsTest, DISABLED_AsanCheckStrspn) {
473 : // TODO(sebmarchand): Reactivate this unittest once the implementation of
474 : // this interceptor has been fixed.
475 i : const char* str_value = "123_abc";
476 i : ScopedAsanAlloc<char> str(this, ::strlen(str_value) + 1, str_value);
477 i : ASSERT_TRUE(str.get() != NULL);
478 :
479 i : const char* keys_value = "123";
480 i : EXPECT_EQ(::strlen(keys_value), ::strspn(str_value, keys_value));
481 i : ScopedAsanAlloc<char> keys(this, ::strlen(keys_value) + 1, keys_value);
482 i : ASSERT_TRUE(keys.get() != NULL);
483 :
484 : // The second test string should only contains values present in the keys.
485 i : const char* str_value_2 = "12321";
486 i : ScopedAsanAlloc<char> str2(this, ::strlen(str_value_2) + 1, str_value_2);
487 i : EXPECT_EQ(::strlen(str_value_2), ::strspn(str_value_2, keys_value));
488 i : ASSERT_TRUE(str2.get() != NULL);
489 :
490 i : SetCallBackFunction(&AsanErrorCallback);
491 i : EXPECT_EQ(::strspn(str.get(), keys.get()),
492 i : strspnFunction(str.get(), keys.get()));
493 :
494 i : strspnFunctionFailing(str.get() - 1, keys.get());
495 i : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
496 i : ResetLog();
497 :
498 i : size_t keys_len = ::strlen(keys.get());
499 i : keys[keys_len] = 'a';
500 i : strspnFunctionFailing(str.get(), keys.get());
501 i : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
502 i : keys[keys_len] = 0;
503 i : ResetLog();
504 :
505 : // The implementation allows a non null terminated input string if it doesn't
506 : // start with a value contained in the keys, otherwise it'll overflow.
507 :
508 i : size_t str_len = ::strlen(str.get());
509 i : str[str_len] = 'a';
510 i : EXPECT_EQ(::strspn(str.get(), keys.get()),
511 i : strspnFunction(str.get(), keys.get()));
512 i : str[str_len] = 0;
513 i : ResetLog();
514 :
515 i : size_t str2_len = ::strlen(str2.get());
516 i : str2[str2_len] = keys[0];
517 i : strspnFunctionFailing(str2.get(), keys.get());
518 i : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
519 i : str2[str2_len] = 0;
520 i : ResetLog();
521 i : }
522 :
523 E : TEST_F(CrtInterceptorsTest, DISABLED_AsanStrspnImpl) {
524 : // TODO(sebmarchand): Reactivate this unittest once the implementation of
525 : // this interceptor has been fixed.
526 i : EXPECT_EQ(5, asan_strspn("abcde", "abcde"));
527 i : EXPECT_EQ(5, asan_strspn("abcde", "edcba"));
528 i : EXPECT_EQ(0U, asan_strspn("abcde", ""));
529 i : EXPECT_EQ(2, asan_strspn("abcde", "ab"));
530 i : EXPECT_EQ(4, asan_strspn("abccde", "abc"));
531 i : EXPECT_EQ(2, asan_strspn("abcde", "fghab"));
532 i : EXPECT_EQ(3, asan_strspn("abcde", "fagbhc"));
533 i : EXPECT_EQ(1, asan_strspn("abcde", "aaa"));
534 i : EXPECT_EQ(0U, asan_strspn("abcde", "fgh"));
535 i : EXPECT_EQ(0U, asan_strspn("", ""));
536 i : EXPECT_EQ(0U, asan_strspn("", "abcde"));
537 i : }
538 :
539 E : TEST_F(CrtInterceptorsTest, AsanCheckStrncpy) {
540 E : const char* str_value = "test_strncpy";
541 E : ScopedAsanAlloc<char> source(this, ::strlen(str_value) + 1, str_value);
542 E : ASSERT_TRUE(source != NULL);
543 :
544 E : const char* long_str_value = "test_strncpy_long_source";
545 E : ScopedAsanAlloc<char> long_source(this, ::strlen(long_str_value) + 1,
546 : long_str_value);
547 E : ASSERT_TRUE(long_source.get() != NULL);
548 :
549 E : ScopedAsanAlloc<char> destination(this, ::strlen(str_value) + 1);
550 E : ASSERT_TRUE(destination != NULL);
551 :
552 E : SetCallBackFunction(&AsanErrorCallback);
553 E : EXPECT_EQ(destination.get(),
554 : strncpyFunction(destination.get(),
555 : source.get(),
556 E : ::strlen(str_value)));
557 :
558 : // Test an underflow on the source.
559 E : strncpyFunctionFailing(destination.get(),
560 : source.get() - 1,
561 : ::strlen(str_value));
562 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
563 E : ResetLog();
564 :
565 : // Test an underflow on the destination.
566 E : strncpyFunctionFailing(destination.get() - 1,
567 : source.get(),
568 : ::strlen(str_value));
569 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
570 E : ResetLog();
571 :
572 : // Test an overflow on the destination.
573 E : std::vector<uint8_t> original_data(::strlen(long_str_value));
574 E : memcpy(&original_data[0], destination.get(), ::strlen(long_str_value));
575 E : strncpyFunctionFailing(destination.get(),
576 : long_source.get(),
577 : ::strlen(long_str_value));
578 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
579 E : ResetLog();
580 :
581 : // Another overflow on the destination.
582 E : strncpyFunctionFailing(destination.get(),
583 : source.get(),
584 : ::strlen(str_value) + 2);
585 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
586 E : ResetLog();
587 :
588 : // Test an overflow on the source.
589 E : size_t source_len = ::strlen(source.get());
590 E : source[source_len] = 'a';
591 E : strncpyFunctionFailing(destination.get(),
592 : source.get(),
593 : ::strlen(source.get()) + 1);
594 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
595 E : source[source_len] = 0;
596 E : ResetLog();
597 E : }
598 :
599 E : TEST_F(CrtInterceptorsTest, AsanCheckStrncat) {
600 E : const char* prefix_value = "test_";
601 E : const char* suffix_value = "strncat";
602 : char buffer[64];
603 :
604 E : ScopedAsanAlloc<char> mem(this,
605 : ::strlen(prefix_value) + ::strlen(suffix_value) + 1, prefix_value);
606 E : ASSERT_TRUE(mem != NULL);
607 E : ::strcpy(buffer, prefix_value);
608 :
609 E : ScopedAsanAlloc<char> suffix(this, ::strlen(suffix_value) + 1, suffix_value);
610 E : ASSERT_TRUE(mem.get() != NULL);
611 :
612 E : SetCallBackFunction(&AsanErrorCallback);
613 E : EXPECT_EQ(mem.get(),
614 E : strncatFunction(mem.get(), suffix.get(), ::strlen(suffix_value)));
615 E : EXPECT_STRCASEEQ(
616 E : ::strncat(buffer, suffix.get(), ::strlen(suffix_value)), mem.get());
617 :
618 : // Test an underflow on the suffix.
619 E : ::strcpy(mem.get(), prefix_value);
620 E : ::strcpy(buffer, prefix_value);
621 E : strncatFunctionFailing(mem.get(), suffix.get() - 1, ::strlen(suffix_value));
622 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
623 E : ResetLog();
624 :
625 : // Test an underflow on the destination.
626 E : ::strcpy(mem.get(), prefix_value);
627 E : ::strcpy(buffer, prefix_value);
628 E : strncatFunctionFailing(mem.get() - 1, suffix.get(), ::strlen(suffix_value));
629 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
630 E : ResetLog();
631 :
632 : // Test an overflow on the suffix.
633 E : size_t suffix_len = ::strlen(suffix.get());
634 E : suffix[suffix_len] = 'a';
635 E : ::strcpy(mem.get(), prefix_value);
636 E : ::strcpy(buffer, prefix_value);
637 E : strncatFunctionFailing(mem.get(), suffix.get(), ::strlen(suffix.get()) + 1);
638 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
639 E : suffix[suffix_len] = 0;
640 E : ResetLog();
641 :
642 : // Test an overflow on the destination.
643 E : ::strcpy(mem.get(), prefix_value);
644 E : ::strcpy(buffer, prefix_value);
645 E : size_t prefix_len = ::strlen(prefix_value);
646 E : mem[prefix_len] = 'a';
647 E : buffer[prefix_len] = 'a';
648 E : strncatFunctionFailing(mem.get(), suffix.get(), ::strlen(suffix.get()));
649 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
650 E : mem[prefix_len] = 0;
651 E : buffer[prefix_len] = 0;
652 E : ResetLog();
653 E : }
654 :
655 : } // namespace asan
656 : } // namespace agent
|