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