1 //=-- asan_str_test.cpp ---------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of AddressSanitizer, an address sanity checker.
10 //
11 //===----------------------------------------------------------------------===//
12 #include "asan_test_utils.h"
13
14 #if defined(__APPLE__)
15 #include <AvailabilityMacros.h> // For MAC_OS_X_VERSION_*
16 #endif
17
18 // Used for string functions tests
19 static char global_string[] = "global";
20 static size_t global_string_length = 6;
21
22 const char kStackReadUnderflow[] =
23 #if !GTEST_USES_SIMPLE_RE
24 ASAN_PCRE_DOTALL
25 "READ.*"
26 #endif
27 "underflows this variable";
28 const char kStackReadOverflow[] =
29 #if !GTEST_USES_SIMPLE_RE
30 ASAN_PCRE_DOTALL
31 "READ.*"
32 #endif
33 "overflows this variable";
34
35 namespace {
36 enum class OOBKind {
37 Heap,
38 Stack,
39 Global,
40 };
41
LeftOOBReadMessage(OOBKind oob_kind,int oob_distance)42 std::string LeftOOBReadMessage(OOBKind oob_kind, int oob_distance) {
43 return oob_kind == OOBKind::Stack ? kStackReadUnderflow
44 : ::LeftOOBReadMessage(oob_distance);
45 }
46
RightOOBReadMessage(OOBKind oob_kind,int oob_distance)47 std::string RightOOBReadMessage(OOBKind oob_kind, int oob_distance) {
48 return oob_kind == OOBKind::Stack ? kStackReadOverflow
49 : ::RightOOBReadMessage(oob_distance);
50 }
51 } // namespace
52
53 // Input to a test is a zero-terminated string str with given length
54 // Accesses to the bytes to the left and to the right of str
55 // are presumed to produce OOB errors
StrLenOOBTestTemplate(char * str,size_t length,OOBKind oob_kind)56 void StrLenOOBTestTemplate(char *str, size_t length, OOBKind oob_kind) {
57 // Normal strlen calls
58 EXPECT_EQ(strlen(str), length);
59 if (length > 0) {
60 EXPECT_EQ(length - 1, strlen(str + 1));
61 EXPECT_EQ(0U, strlen(str + length));
62 }
63 // Arg of strlen is not malloced, OOB access
64 if (oob_kind != OOBKind::Global) {
65 // We don't insert RedZones to the left of global variables
66 EXPECT_DEATH(Ident(strlen(str - 1)), LeftOOBReadMessage(oob_kind, 1));
67 EXPECT_DEATH(Ident(strlen(str - 5)), LeftOOBReadMessage(oob_kind, 5));
68 }
69 EXPECT_DEATH(Ident(strlen(str + length + 1)),
70 RightOOBReadMessage(oob_kind, 0));
71 // Overwrite terminator
72 str[length] = 'a';
73 // String is not zero-terminated, strlen will lead to OOB access
74 EXPECT_DEATH(Ident(strlen(str)), RightOOBReadMessage(oob_kind, 0));
75 EXPECT_DEATH(Ident(strlen(str + length)), RightOOBReadMessage(oob_kind, 0));
76 // Restore terminator
77 str[length] = 0;
78 }
TEST(AddressSanitizer,StrLenOOBTest)79 TEST(AddressSanitizer, StrLenOOBTest) {
80 // Check heap-allocated string
81 size_t length = Ident(10);
82 char *heap_string = Ident((char*)malloc(length + 1));
83 char stack_string[10 + 1];
84 break_optimization(&stack_string);
85 for (size_t i = 0; i < length; i++) {
86 heap_string[i] = 'a';
87 stack_string[i] = 'b';
88 }
89 heap_string[length] = 0;
90 stack_string[length] = 0;
91 StrLenOOBTestTemplate(heap_string, length, OOBKind::Heap);
92 StrLenOOBTestTemplate(stack_string, length, OOBKind::Stack);
93 StrLenOOBTestTemplate(global_string, global_string_length, OOBKind::Global);
94 free(heap_string);
95 }
96
97 // 32-bit android libc++-based NDK toolchain links wcslen statically, disabling
98 // the interceptor.
99 #if !defined(__ANDROID__) || defined(__LP64__)
TEST(AddressSanitizer,WcsLenTest)100 TEST(AddressSanitizer, WcsLenTest) {
101 EXPECT_EQ(0U, wcslen(Ident(L"")));
102 size_t hello_len = 13;
103 size_t hello_size = (hello_len + 1) * sizeof(wchar_t);
104 EXPECT_EQ(hello_len, wcslen(Ident(L"Hello, World!")));
105 wchar_t *heap_string = Ident((wchar_t*)malloc(hello_size));
106 memcpy(heap_string, L"Hello, World!", hello_size);
107 EXPECT_EQ(hello_len, Ident(wcslen(heap_string)));
108 EXPECT_DEATH(Ident(wcslen(heap_string + 14)), RightOOBReadMessage(0));
109 free(heap_string);
110 }
111 #endif
112
113 #if SANITIZER_TEST_HAS_STRNLEN
TEST(AddressSanitizer,StrNLenOOBTest)114 TEST(AddressSanitizer, StrNLenOOBTest) {
115 size_t size = Ident(123);
116 char *str = MallocAndMemsetString(size);
117 // Normal strnlen calls.
118 Ident(strnlen(str - 1, 0));
119 Ident(strnlen(str, size));
120 Ident(strnlen(str + size - 1, 1));
121 str[size - 1] = '\0';
122 Ident(strnlen(str, 2 * size));
123 // Argument points to not allocated memory.
124 EXPECT_DEATH(Ident(strnlen(str - 1, 1)), LeftOOBReadMessage(1));
125 EXPECT_DEATH(Ident(strnlen(str + size, 1)), RightOOBReadMessage(0));
126 // Overwrite the terminating '\0' and hit unallocated memory.
127 str[size - 1] = 'z';
128 EXPECT_DEATH(Ident(strnlen(str, size + 1)), RightOOBReadMessage(0));
129 free(str);
130 }
131 #endif // SANITIZER_TEST_HAS_STRNLEN
132
133 // This test fails with the WinASan dynamic runtime because we fail to intercept
134 // strdup.
135 #if defined(_MSC_VER) && defined(_DLL)
136 #define MAYBE_StrDupOOBTest DISABLED_StrDupOOBTest
137 #else
138 #define MAYBE_StrDupOOBTest StrDupOOBTest
139 #endif
140
TEST(AddressSanitizer,MAYBE_StrDupOOBTest)141 TEST(AddressSanitizer, MAYBE_StrDupOOBTest) {
142 size_t size = Ident(42);
143 char *str = MallocAndMemsetString(size);
144 char *new_str;
145 // Normal strdup calls.
146 str[size - 1] = '\0';
147 new_str = strdup(str);
148 free(new_str);
149 new_str = strdup(str + size - 1);
150 free(new_str);
151 // Argument points to not allocated memory.
152 EXPECT_DEATH(Ident(strdup(str - 1)), LeftOOBReadMessage(1));
153 EXPECT_DEATH(Ident(strdup(str + size)), RightOOBReadMessage(0));
154 // Overwrite the terminating '\0' and hit unallocated memory.
155 str[size - 1] = 'z';
156 EXPECT_DEATH(Ident(strdup(str)), RightOOBReadMessage(0));
157 free(str);
158 }
159
160 #if SANITIZER_TEST_HAS_STRNDUP
TEST(AddressSanitizer,MAYBE_StrNDupOOBTest)161 TEST(AddressSanitizer, MAYBE_StrNDupOOBTest) {
162 size_t size = Ident(42);
163 char *str = MallocAndMemsetString(size);
164 char *new_str;
165 // Normal strndup calls.
166 str[size - 1] = '\0';
167 new_str = strndup(str, size - 13);
168 free(new_str);
169 new_str = strndup(str + size - 1, 13);
170 free(new_str);
171 // Argument points to not allocated memory.
172 EXPECT_DEATH(Ident(strndup(str - 1, 13)), LeftOOBReadMessage(1));
173 EXPECT_DEATH(Ident(strndup(str + size, 13)), RightOOBReadMessage(0));
174 // Overwrite the terminating '\0' and hit unallocated memory.
175 str[size - 1] = 'z';
176 EXPECT_DEATH(Ident(strndup(str, size + 13)), RightOOBReadMessage(0));
177 // Check handling of non 0 terminated strings.
178 Ident(new_str = strndup(str + size - 1, 0));
179 free(new_str);
180 Ident(new_str = strndup(str + size - 1, 1));
181 free(new_str);
182 EXPECT_DEATH(Ident(strndup(str + size - 1, 2)), RightOOBReadMessage(0));
183 free(str);
184 }
185 #endif // SANITIZER_TEST_HAS_STRNDUP
186
TEST(AddressSanitizer,StrCpyOOBTest)187 TEST(AddressSanitizer, StrCpyOOBTest) {
188 size_t to_size = Ident(30);
189 size_t from_size = Ident(6); // less than to_size
190 char *to = Ident((char*)malloc(to_size));
191 char *from = Ident((char*)malloc(from_size));
192 // Normal strcpy calls.
193 strcpy(from, "hello");
194 strcpy(to, from);
195 strcpy(to + to_size - from_size, from);
196 // Length of "from" is too small.
197 EXPECT_DEATH(Ident(strcpy(from, "hello2")), RightOOBWriteMessage(0));
198 // "to" or "from" points to not allocated memory.
199 EXPECT_DEATH(Ident(strcpy(to - 1, from)), LeftOOBWriteMessage(1));
200 EXPECT_DEATH(Ident(strcpy(to, from - 1)), LeftOOBReadMessage(1));
201 EXPECT_DEATH(Ident(strcpy(to, from + from_size)), RightOOBReadMessage(0));
202 EXPECT_DEATH(Ident(strcpy(to + to_size, from)), RightOOBWriteMessage(0));
203 // Overwrite the terminating '\0' character and hit unallocated memory.
204 from[from_size - 1] = '!';
205 EXPECT_DEATH(Ident(strcpy(to, from)), RightOOBReadMessage(0));
206 free(to);
207 free(from);
208 }
209
TEST(AddressSanitizer,StrNCpyOOBTest)210 TEST(AddressSanitizer, StrNCpyOOBTest) {
211 size_t to_size = Ident(20);
212 size_t from_size = Ident(6); // less than to_size
213 char *to = Ident((char*)malloc(to_size));
214 // From is a zero-terminated string "hello\0" of length 6
215 char *from = Ident((char*)malloc(from_size));
216 strcpy(from, "hello");
217 // copy 0 bytes
218 strncpy(to, from, 0);
219 strncpy(to - 1, from - 1, 0);
220 // normal strncpy calls
221 strncpy(to, from, from_size);
222 strncpy(to, from, to_size);
223 strncpy(to, from + from_size - 1, to_size);
224 strncpy(to + to_size - 1, from, 1);
225 // One of {to, from} points to not allocated memory
226 EXPECT_DEATH(Ident(strncpy(to, from - 1, from_size)),
227 LeftOOBReadMessage(1));
228 EXPECT_DEATH(Ident(strncpy(to - 1, from, from_size)),
229 LeftOOBWriteMessage(1));
230 EXPECT_DEATH(Ident(strncpy(to, from + from_size, 1)),
231 RightOOBReadMessage(0));
232 EXPECT_DEATH(Ident(strncpy(to + to_size, from, 1)),
233 RightOOBWriteMessage(0));
234 // Length of "to" is too small
235 EXPECT_DEATH(Ident(strncpy(to + to_size - from_size + 1, from, from_size)),
236 RightOOBWriteMessage(0));
237 EXPECT_DEATH(Ident(strncpy(to + 1, from, to_size)),
238 RightOOBWriteMessage(0));
239 // Overwrite terminator in from
240 from[from_size - 1] = '!';
241 // normal strncpy call
242 strncpy(to, from, from_size);
243 // Length of "from" is too small
244 EXPECT_DEATH(Ident(strncpy(to, from, to_size)),
245 RightOOBReadMessage(0));
246 free(to);
247 free(from);
248 }
249
250 // Users may have different definitions of "strchr" and "index", so provide
251 // function pointer typedefs and overload RunStrChrTest implementation.
252 // We can't use macro for RunStrChrTest body here, as this macro would
253 // confuse EXPECT_DEATH gtest macro.
254 typedef char*(*PointerToStrChr1)(const char*, int);
255 typedef char*(*PointerToStrChr2)(char*, int);
256
257 template<typename StrChrFn>
RunStrChrTestImpl(StrChrFn * StrChr)258 static void RunStrChrTestImpl(StrChrFn *StrChr) {
259 size_t size = Ident(100);
260 char *str = MallocAndMemsetString(size);
261 str[10] = 'q';
262 str[11] = '\0';
263 EXPECT_EQ(str, StrChr(str, 'z'));
264 EXPECT_EQ(str + 10, StrChr(str, 'q'));
265 EXPECT_EQ(NULL, StrChr(str, 'a'));
266 // StrChr argument points to not allocated memory.
267 EXPECT_DEATH(Ident(StrChr(str - 1, 'z')), LeftOOBReadMessage(1));
268 EXPECT_DEATH(Ident(StrChr(str + size, 'z')), RightOOBReadMessage(0));
269 // Overwrite the terminator and hit not allocated memory.
270 str[11] = 'z';
271 EXPECT_DEATH(Ident(StrChr(str, 'a')), RightOOBReadMessage(0));
272 free(str);
273 }
274
275 // Prefer to use the standard signature if both are available.
RunStrChrTest(PointerToStrChr1 StrChr,...)276 UNUSED static void RunStrChrTest(PointerToStrChr1 StrChr, ...) {
277 RunStrChrTestImpl(StrChr);
278 }
RunStrChrTest(PointerToStrChr2 StrChr,int)279 UNUSED static void RunStrChrTest(PointerToStrChr2 StrChr, int) {
280 RunStrChrTestImpl(StrChr);
281 }
282
TEST(AddressSanitizer,StrChrAndIndexOOBTest)283 TEST(AddressSanitizer, StrChrAndIndexOOBTest) {
284 RunStrChrTest(&strchr, 0);
285 // No index() on Windows and on Android L.
286 #if !defined(_WIN32) && !defined(__ANDROID__)
287 RunStrChrTest(&index, 0);
288 #endif
289 }
290
TEST(AddressSanitizer,StrCmpAndFriendsLogicTest)291 TEST(AddressSanitizer, StrCmpAndFriendsLogicTest) {
292 // strcmp
293 EXPECT_EQ(0, strcmp("", ""));
294 EXPECT_EQ(0, strcmp("abcd", "abcd"));
295 EXPECT_GT(0, strcmp("ab", "ac"));
296 EXPECT_GT(0, strcmp("abc", "abcd"));
297 EXPECT_LT(0, strcmp("acc", "abc"));
298 EXPECT_LT(0, strcmp("abcd", "abc"));
299
300 // strncmp
301 EXPECT_EQ(0, strncmp("a", "b", 0));
302 EXPECT_EQ(0, strncmp("abcd", "abcd", 10));
303 EXPECT_EQ(0, strncmp("abcd", "abcef", 3));
304 EXPECT_GT(0, strncmp("abcde", "abcfa", 4));
305 EXPECT_GT(0, strncmp("a", "b", 5));
306 EXPECT_GT(0, strncmp("bc", "bcde", 4));
307 EXPECT_LT(0, strncmp("xyz", "xyy", 10));
308 EXPECT_LT(0, strncmp("baa", "aaa", 1));
309 EXPECT_LT(0, strncmp("zyx", "", 2));
310
311 #if !defined(_WIN32) // no str[n]casecmp on Windows.
312 // strcasecmp
313 EXPECT_EQ(0, strcasecmp("", ""));
314 EXPECT_EQ(0, strcasecmp("zzz", "zzz"));
315 EXPECT_EQ(0, strcasecmp("abCD", "ABcd"));
316 EXPECT_GT(0, strcasecmp("aB", "Ac"));
317 EXPECT_GT(0, strcasecmp("ABC", "ABCd"));
318 EXPECT_LT(0, strcasecmp("acc", "abc"));
319 EXPECT_LT(0, strcasecmp("ABCd", "abc"));
320
321 // strncasecmp
322 EXPECT_EQ(0, strncasecmp("a", "b", 0));
323 EXPECT_EQ(0, strncasecmp("abCD", "ABcd", 10));
324 EXPECT_EQ(0, strncasecmp("abCd", "ABcef", 3));
325 EXPECT_GT(0, strncasecmp("abcde", "ABCfa", 4));
326 EXPECT_GT(0, strncasecmp("a", "B", 5));
327 EXPECT_GT(0, strncasecmp("bc", "BCde", 4));
328 EXPECT_LT(0, strncasecmp("xyz", "xyy", 10));
329 EXPECT_LT(0, strncasecmp("Baa", "aaa", 1));
330 EXPECT_LT(0, strncasecmp("zyx", "", 2));
331 #endif
332
333 // memcmp
334 EXPECT_EQ(0, memcmp("a", "b", 0));
335 EXPECT_EQ(0, memcmp("ab\0c", "ab\0c", 4));
336 EXPECT_GT(0, memcmp("\0ab", "\0ac", 3));
337 EXPECT_GT(0, memcmp("abb\0", "abba", 4));
338 EXPECT_LT(0, memcmp("ab\0cd", "ab\0c\0", 5));
339 EXPECT_LT(0, memcmp("zza", "zyx", 3));
340 }
341
342 typedef int(*PointerToStrCmp)(const char*, const char*);
RunStrCmpTest(PointerToStrCmp StrCmp)343 void RunStrCmpTest(PointerToStrCmp StrCmp) {
344 size_t size = Ident(100);
345 int fill = 'o';
346 char *s1 = MallocAndMemsetString(size, fill);
347 char *s2 = MallocAndMemsetString(size, fill);
348 s1[size - 1] = '\0';
349 s2[size - 1] = '\0';
350 // Normal StrCmp calls
351 Ident(StrCmp(s1, s2));
352 Ident(StrCmp(s1, s2 + size - 1));
353 Ident(StrCmp(s1 + size - 1, s2 + size - 1));
354 // One of arguments points to not allocated memory.
355 EXPECT_DEATH(Ident(StrCmp)(s1 - 1, s2), LeftOOBReadMessage(1));
356 EXPECT_DEATH(Ident(StrCmp)(s1, s2 - 1), LeftOOBReadMessage(1));
357 EXPECT_DEATH(Ident(StrCmp)(s1 + size, s2), RightOOBReadMessage(0));
358 EXPECT_DEATH(Ident(StrCmp)(s1, s2 + size), RightOOBReadMessage(0));
359 // Hit unallocated memory and die.
360 s1[size - 1] = fill;
361 EXPECT_DEATH(Ident(StrCmp)(s1, s1), RightOOBReadMessage(0));
362 EXPECT_DEATH(Ident(StrCmp)(s1 + size - 1, s2), RightOOBReadMessage(0));
363 free(s1);
364 free(s2);
365 }
366
TEST(AddressSanitizer,StrCmpOOBTest)367 TEST(AddressSanitizer, StrCmpOOBTest) {
368 RunStrCmpTest(&strcmp);
369 }
370
371 #if !defined(_WIN32) // no str[n]casecmp on Windows.
TEST(AddressSanitizer,StrCaseCmpOOBTest)372 TEST(AddressSanitizer, StrCaseCmpOOBTest) {
373 RunStrCmpTest(&strcasecmp);
374 }
375 #endif
376
377 typedef int(*PointerToStrNCmp)(const char*, const char*, size_t);
RunStrNCmpTest(PointerToStrNCmp StrNCmp)378 void RunStrNCmpTest(PointerToStrNCmp StrNCmp) {
379 size_t size = Ident(100);
380 char *s1 = MallocAndMemsetString(size);
381 char *s2 = MallocAndMemsetString(size);
382 s1[size - 1] = '\0';
383 s2[size - 1] = '\0';
384 // Normal StrNCmp calls
385 Ident(StrNCmp(s1, s2, size + 2));
386 s1[size - 1] = 'z';
387 s2[size - 1] = 'x';
388 Ident(StrNCmp(s1 + size - 2, s2 + size - 2, size));
389 s2[size - 1] = 'z';
390 Ident(StrNCmp(s1 - 1, s2 - 1, 0));
391 Ident(StrNCmp(s1 + size - 1, s2 + size - 1, 1));
392 // One of arguments points to not allocated memory.
393 EXPECT_DEATH(Ident(StrNCmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1));
394 EXPECT_DEATH(Ident(StrNCmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1));
395 EXPECT_DEATH(Ident(StrNCmp)(s1 + size, s2, 1), RightOOBReadMessage(0));
396 EXPECT_DEATH(Ident(StrNCmp)(s1, s2 + size, 1), RightOOBReadMessage(0));
397 // Hit unallocated memory and die.
398 EXPECT_DEATH(Ident(StrNCmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0));
399 EXPECT_DEATH(Ident(StrNCmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0));
400 free(s1);
401 free(s2);
402 }
403
TEST(AddressSanitizer,StrNCmpOOBTest)404 TEST(AddressSanitizer, StrNCmpOOBTest) {
405 RunStrNCmpTest(&strncmp);
406 }
407
408 #if !defined(_WIN32) // no str[n]casecmp on Windows.
TEST(AddressSanitizer,StrNCaseCmpOOBTest)409 TEST(AddressSanitizer, StrNCaseCmpOOBTest) {
410 RunStrNCmpTest(&strncasecmp);
411 }
412 #endif
413
TEST(AddressSanitizer,StrCatOOBTest)414 TEST(AddressSanitizer, StrCatOOBTest) {
415 // strcat() reads strlen(to) bytes from |to| before concatenating.
416 size_t to_size = Ident(100);
417 char *to = MallocAndMemsetString(to_size);
418 to[0] = '\0';
419 size_t from_size = Ident(20);
420 char *from = MallocAndMemsetString(from_size);
421 from[from_size - 1] = '\0';
422 // Normal strcat calls.
423 strcat(to, from);
424 strcat(to, from);
425 strcat(to + from_size, from + from_size - 2);
426 // Passing an invalid pointer is an error even when concatenating an empty
427 // string.
428 EXPECT_DEATH(strcat(to - 1, from + from_size - 1), LeftOOBAccessMessage(1));
429 // One of arguments points to not allocated memory.
430 EXPECT_DEATH(strcat(to - 1, from), LeftOOBAccessMessage(1));
431 EXPECT_DEATH(strcat(to, from - 1), LeftOOBReadMessage(1));
432 EXPECT_DEATH(strcat(to, from + from_size), RightOOBReadMessage(0));
433
434 // "from" is not zero-terminated.
435 from[from_size - 1] = 'z';
436 EXPECT_DEATH(strcat(to, from), RightOOBReadMessage(0));
437 from[from_size - 1] = '\0';
438 // "to" is too short to fit "from".
439 memset(to, 'z', to_size);
440 to[to_size - from_size + 1] = '\0';
441 EXPECT_DEATH(strcat(to, from), RightOOBWriteMessage(0));
442 // length of "to" is just enough.
443 strcat(to, from + 1);
444
445 free(to);
446 free(from);
447 }
448
TEST(AddressSanitizer,StrNCatOOBTest)449 TEST(AddressSanitizer, StrNCatOOBTest) {
450 // strncat() reads strlen(to) bytes from |to| before concatenating.
451 size_t to_size = Ident(100);
452 char *to = MallocAndMemsetString(to_size);
453 to[0] = '\0';
454 size_t from_size = Ident(20);
455 char *from = MallocAndMemsetString(from_size);
456 // Normal strncat calls.
457 strncat(to, from, 0);
458 strncat(to, from, from_size);
459 from[from_size - 1] = '\0';
460 strncat(to, from, 2 * from_size);
461 strncat(to, from + from_size - 1, 10);
462 // One of arguments points to not allocated memory.
463 EXPECT_DEATH(strncat(to - 1, from, 2), LeftOOBAccessMessage(1));
464 EXPECT_DEATH(strncat(to, from - 1, 2), LeftOOBReadMessage(1));
465 EXPECT_DEATH(strncat(to, from + from_size, 2), RightOOBReadMessage(0));
466
467 memset(from, 'z', from_size);
468 memset(to, 'z', to_size);
469 to[0] = '\0';
470 // "from" is too short.
471 EXPECT_DEATH(strncat(to, from, from_size + 1), RightOOBReadMessage(0));
472 // "to" is too short to fit "from".
473 to[0] = 'z';
474 to[to_size - from_size + 1] = '\0';
475 EXPECT_DEATH(strncat(to, from, from_size - 1), RightOOBWriteMessage(0));
476 // "to" is just enough.
477 strncat(to, from, from_size - 2);
478
479 free(to);
480 free(from);
481 }
482
OverlapErrorMessage(const std::string & func)483 static std::string OverlapErrorMessage(const std::string &func) {
484 return func + "-param-overlap";
485 }
486
TEST(AddressSanitizer,StrArgsOverlapTest)487 TEST(AddressSanitizer, StrArgsOverlapTest) {
488 size_t size = Ident(100);
489 char *str = Ident((char*)malloc(size));
490
491 // Do not check memcpy() on OS X 10.7 and later, where it actually aliases
492 // memmove().
493 #if !defined(__APPLE__) || !defined(MAC_OS_X_VERSION_10_7) || \
494 (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7)
495 // Check "memcpy". Use Ident() to avoid inlining.
496 #if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
497 memset(str, 'z', size);
498 Ident(memcpy)(str + 1, str + 11, 10);
499 Ident(memcpy)(str, str, 0);
500 EXPECT_DEATH(Ident(memcpy)(str, str + 14, 15), OverlapErrorMessage("memcpy"));
501 EXPECT_DEATH(Ident(memcpy)(str + 14, str, 15), OverlapErrorMessage("memcpy"));
502 #endif
503 #endif
504
505 // We do not treat memcpy with to==from as a bug.
506 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
507 // EXPECT_DEATH(Ident(memcpy)(str + 20, str + 20, 1),
508 // OverlapErrorMessage("memcpy"));
509
510 // Check "strcpy".
511 memset(str, 'z', size);
512 str[9] = '\0';
513 strcpy(str + 10, str);
514 EXPECT_DEATH(strcpy(str + 9, str), OverlapErrorMessage("strcpy"));
515 EXPECT_DEATH(strcpy(str, str + 4), OverlapErrorMessage("strcpy"));
516 strcpy(str, str + 5);
517
518 // Check "strncpy".
519 memset(str, 'z', size);
520 strncpy(str, str + 10, 10);
521 EXPECT_DEATH(strncpy(str, str + 9, 10), OverlapErrorMessage("strncpy"));
522 EXPECT_DEATH(strncpy(str + 9, str, 10), OverlapErrorMessage("strncpy"));
523 str[10] = '\0';
524 strncpy(str + 11, str, 20);
525 EXPECT_DEATH(strncpy(str + 10, str, 20), OverlapErrorMessage("strncpy"));
526
527 // Check "strcat".
528 memset(str, 'z', size);
529 str[10] = '\0';
530 str[20] = '\0';
531 strcat(str, str + 10);
532 EXPECT_DEATH(strcat(str, str + 11), OverlapErrorMessage("strcat"));
533 str[10] = '\0';
534 strcat(str + 11, str);
535 EXPECT_DEATH(strcat(str, str + 9), OverlapErrorMessage("strcat"));
536 EXPECT_DEATH(strcat(str + 9, str), OverlapErrorMessage("strcat"));
537 EXPECT_DEATH(strcat(str + 10, str), OverlapErrorMessage("strcat"));
538
539 // Check "strncat".
540 memset(str, 'z', size);
541 str[10] = '\0';
542 strncat(str, str + 10, 10); // from is empty
543 EXPECT_DEATH(strncat(str, str + 11, 10), OverlapErrorMessage("strncat"));
544 str[10] = '\0';
545 str[20] = '\0';
546 strncat(str + 5, str, 5);
547 str[10] = '\0';
548 EXPECT_DEATH(strncat(str + 5, str, 6), OverlapErrorMessage("strncat"));
549 EXPECT_DEATH(strncat(str, str + 9, 10), OverlapErrorMessage("strncat"));
550
551 free(str);
552 }
553
554 typedef void(*PointerToCallAtoi)(const char*);
555
RunAtoiOOBTest(PointerToCallAtoi Atoi)556 void RunAtoiOOBTest(PointerToCallAtoi Atoi) {
557 char *array = MallocAndMemsetString(10, '1');
558 // Invalid pointer to the string.
559 EXPECT_DEATH(Atoi(array + 11), RightOOBReadMessage(1));
560 EXPECT_DEATH(Atoi(array - 1), LeftOOBReadMessage(1));
561 // Die if a buffer doesn't have terminating NULL.
562 EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0));
563 // Make last symbol a terminating NULL
564 array[9] = '\0';
565 Atoi(array);
566 // Sometimes we need to detect overflow if no digits are found.
567 memset(array, ' ', 10);
568 EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0));
569 array[9] = '-';
570 EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0));
571 EXPECT_DEATH(Atoi(array + 9), RightOOBReadMessage(0));
572 free(array);
573 }
574
575 #if !defined(_WIN32) // FIXME: Fix and enable on Windows.
CallAtoi(const char * nptr)576 void CallAtoi(const char *nptr) {
577 Ident(atoi(nptr));
578 }
CallAtol(const char * nptr)579 void CallAtol(const char *nptr) {
580 Ident(atol(nptr));
581 }
CallAtoll(const char * nptr)582 void CallAtoll(const char *nptr) {
583 Ident(atoll(nptr));
584 }
TEST(AddressSanitizer,AtoiAndFriendsOOBTest)585 TEST(AddressSanitizer, AtoiAndFriendsOOBTest) {
586 RunAtoiOOBTest(&CallAtoi);
587 RunAtoiOOBTest(&CallAtol);
588 RunAtoiOOBTest(&CallAtoll);
589 }
590 #endif
591
592 typedef void(*PointerToCallStrtol)(const char*, char**, int);
593
RunStrtolOOBTest(PointerToCallStrtol Strtol)594 void RunStrtolOOBTest(PointerToCallStrtol Strtol) {
595 char *array = MallocAndMemsetString(3);
596 array[0] = '1';
597 array[1] = '2';
598 array[2] = '3';
599 // Invalid pointer to the string.
600 EXPECT_DEATH(Strtol(array + 3, NULL, 0), RightOOBReadMessage(0));
601 EXPECT_DEATH(Strtol(array - 1, NULL, 0), LeftOOBReadMessage(1));
602 // Buffer overflow if there is no terminating null (depends on base).
603 EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));
604 array[2] = 'z';
605 EXPECT_DEATH(Strtol(array, NULL, 36), RightOOBReadMessage(0));
606 // Add terminating zero to get rid of overflow.
607 array[2] = '\0';
608 Strtol(array, NULL, 36);
609 // Sometimes we need to detect overflow if no digits are found.
610 array[0] = array[1] = array[2] = ' ';
611 EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));
612 array[2] = '+';
613 EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));
614 array[2] = '-';
615 EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));
616 free(array);
617 }
618
619 #if !defined(_WIN32) // FIXME: Fix and enable on Windows.
CallStrtol(const char * nptr,char ** endptr,int base)620 void CallStrtol(const char *nptr, char **endptr, int base) {
621 Ident(strtol(nptr, endptr, base));
622 }
CallStrtoll(const char * nptr,char ** endptr,int base)623 void CallStrtoll(const char *nptr, char **endptr, int base) {
624 Ident(strtoll(nptr, endptr, base));
625 }
TEST(AddressSanitizer,StrtollOOBTest)626 TEST(AddressSanitizer, StrtollOOBTest) {
627 RunStrtolOOBTest(&CallStrtoll);
628 }
TEST(AddressSanitizer,StrtolOOBTest)629 TEST(AddressSanitizer, StrtolOOBTest) {
630 RunStrtolOOBTest(&CallStrtol);
631 }
632 #endif
633