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