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