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