18fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany//=-- asan_str_test.cc ----------------------------------------------------===//
28fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany//
38fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany//                     The LLVM Compiler Infrastructure
48fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany//
58fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// This file is distributed under the University of Illinois Open Source
68fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// License. See LICENSE.TXT for details.
78fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany//
88fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany//===----------------------------------------------------------------------===//
98fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany//
108fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker.
118fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany//
128fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany//===----------------------------------------------------------------------===//
138fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany#include "asan_test_utils.h"
148fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
15b812253202f2db9d60a543b22226064d1ed20279Alexander Potapenko#if defined(__APPLE__)
16b812253202f2db9d60a543b22226064d1ed20279Alexander Potapenko#include <AvailabilityMacros.h>  // For MAC_OS_X_VERSION_*
17b812253202f2db9d60a543b22226064d1ed20279Alexander Potapenko#endif
18d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko
198fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// Used for string functions tests
208fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanystatic char global_string[] = "global";
218fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanystatic size_t global_string_length = 6;
228fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
23c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarconst char kStackReadUnderflow[] =
24c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if !GTEST_USES_SIMPLE_RE
25c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    ASAN_PCRE_DOTALL
26c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    "READ.*"
27c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
28c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    "underflows this variable";
29c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarconst char kStackReadOverflow[] =
30c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if !GTEST_USES_SIMPLE_RE
31c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    ASAN_PCRE_DOTALL
32c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    "READ.*"
33c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
34c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    "overflows this variable";
35c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
36c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarnamespace {
37c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarenum class OOBKind {
38c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  Heap,
39c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  Stack,
40c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  Global,
41c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar};
42c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
43c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstring LeftOOBReadMessage(OOBKind oob_kind, int oob_distance) {
44c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return oob_kind == OOBKind::Stack ? kStackReadUnderflow
45c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                                    : ::LeftOOBReadMessage(oob_distance);
46c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
47c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
48c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstring RightOOBReadMessage(OOBKind oob_kind, int oob_distance) {
49c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return oob_kind == OOBKind::Stack ? kStackReadOverflow
50c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                                    : ::RightOOBReadMessage(oob_distance);
51c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
52c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}  // namespace
53c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
548fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// Input to a test is a zero-terminated string str with given length
558fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// Accesses to the bytes to the left and to the right of str
568fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// are presumed to produce OOB errors
57c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid StrLenOOBTestTemplate(char *str, size_t length, OOBKind oob_kind) {
588fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Normal strlen calls
598fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(strlen(str), length);
608fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  if (length > 0) {
618fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany    EXPECT_EQ(length - 1, strlen(str + 1));
628fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany    EXPECT_EQ(0U, strlen(str + length));
638fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  }
648fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Arg of strlen is not malloced, OOB access
65c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (oob_kind != OOBKind::Global) {
668fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany    // We don't insert RedZones to the left of global variables
67c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    EXPECT_DEATH(Ident(strlen(str - 1)), LeftOOBReadMessage(oob_kind, 1));
68c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    EXPECT_DEATH(Ident(strlen(str - 5)), LeftOOBReadMessage(oob_kind, 5));
698fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  }
70c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  EXPECT_DEATH(Ident(strlen(str + length + 1)),
71c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar               RightOOBReadMessage(oob_kind, 0));
728fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Overwrite terminator
738fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[length] = 'a';
748fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // String is not zero-terminated, strlen will lead to OOB access
75c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  EXPECT_DEATH(Ident(strlen(str)), RightOOBReadMessage(oob_kind, 0));
76c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  EXPECT_DEATH(Ident(strlen(str + length)), RightOOBReadMessage(oob_kind, 0));
778fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Restore terminator
788fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[length] = 0;
798fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
808fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrLenOOBTest) {
818fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Check heap-allocated string
828fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t length = Ident(10);
838fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *heap_string = Ident((char*)malloc(length + 1));
848fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char stack_string[10 + 1];
858fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  break_optimization(&stack_string);
868fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  for (size_t i = 0; i < length; i++) {
878fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany    heap_string[i] = 'a';
888fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany    stack_string[i] = 'b';
898fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  }
908fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  heap_string[length] = 0;
918fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  stack_string[length] = 0;
92c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  StrLenOOBTestTemplate(heap_string, length, OOBKind::Heap);
93c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  StrLenOOBTestTemplate(stack_string, length, OOBKind::Stack);
94c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  StrLenOOBTestTemplate(global_string, global_string_length, OOBKind::Global);
958fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(heap_string);
968fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
978fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
98b99228de65b408b0acd9618b92774fb8add7e482Reid KlecknerTEST(AddressSanitizer, WcsLenTest) {
99e9e4f04e8320d35ab19dfb8688a7bdd3e5ae7cbbAlexey Samsonov  EXPECT_EQ(0U, wcslen(Ident(L"")));
100b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  size_t hello_len = 13;
101b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  size_t hello_size = (hello_len + 1) * sizeof(wchar_t);
102b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  EXPECT_EQ(hello_len, wcslen(Ident(L"Hello, World!")));
103b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  wchar_t *heap_string = Ident((wchar_t*)malloc(hello_size));
104b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  memcpy(heap_string, L"Hello, World!", hello_size);
105b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  EXPECT_EQ(hello_len, Ident(wcslen(heap_string)));
106b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner  EXPECT_DEATH(Ident(wcslen(heap_string + 14)), RightOOBReadMessage(0));
1071a249181dcdf217d368fbf4c1f09d8af7e617cb0Alexey Samsonov  free(heap_string);
108b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner}
109b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner
1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_TEST_HAS_STRNLEN
1118fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrNLenOOBTest) {
1128fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t size = Ident(123);
1138fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *str = MallocAndMemsetString(size);
1148fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Normal strnlen calls.
1158fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(strnlen(str - 1, 0));
1168fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(strnlen(str, size));
1178fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(strnlen(str + size - 1, 1));
1188fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[size - 1] = '\0';
1198fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(strnlen(str, 2 * size));
1208fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Argument points to not allocated memory.
1218fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strnlen(str - 1, 1)), LeftOOBReadMessage(1));
1228fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strnlen(str + size, 1)), RightOOBReadMessage(0));
1238fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Overwrite the terminating '\0' and hit unallocated memory.
1248fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[size - 1] = 'z';
1258fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strnlen(str, size + 1)), RightOOBReadMessage(0));
1268fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(str);
1278fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_TEST_HAS_STRNLEN
1298fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
1308fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrDupOOBTest) {
1318fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t size = Ident(42);
1328fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *str = MallocAndMemsetString(size);
1338fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *new_str;
1348fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Normal strdup calls.
1358fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[size - 1] = '\0';
1368fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  new_str = strdup(str);
1378fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(new_str);
1388fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  new_str = strdup(str + size - 1);
1398fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(new_str);
1408fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Argument points to not allocated memory.
1418fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strdup(str - 1)), LeftOOBReadMessage(1));
1428fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strdup(str + size)), RightOOBReadMessage(0));
1438fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Overwrite the terminating '\0' and hit unallocated memory.
1448fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[size - 1] = 'z';
1458fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strdup(str)), RightOOBReadMessage(0));
1468fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(str);
1478fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
1488fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
1498fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrCpyOOBTest) {
1508fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t to_size = Ident(30);
1518fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t from_size = Ident(6);  // less than to_size
1528fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *to = Ident((char*)malloc(to_size));
1538fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *from = Ident((char*)malloc(from_size));
1548fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Normal strcpy calls.
1558fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strcpy(from, "hello");
1568fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strcpy(to, from);
1578fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strcpy(to + to_size - from_size, from);
1588fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Length of "from" is too small.
1598fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strcpy(from, "hello2")), RightOOBWriteMessage(0));
1608fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // "to" or "from" points to not allocated memory.
1618fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strcpy(to - 1, from)), LeftOOBWriteMessage(1));
1628fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strcpy(to, from - 1)), LeftOOBReadMessage(1));
1638fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strcpy(to, from + from_size)), RightOOBReadMessage(0));
1648fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strcpy(to + to_size, from)), RightOOBWriteMessage(0));
1658fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Overwrite the terminating '\0' character and hit unallocated memory.
1668fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  from[from_size - 1] = '!';
1678fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strcpy(to, from)), RightOOBReadMessage(0));
1688fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(to);
1698fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(from);
1708fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
1718fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
1728fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrNCpyOOBTest) {
1738fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t to_size = Ident(20);
1748fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t from_size = Ident(6);  // less than to_size
1758fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *to = Ident((char*)malloc(to_size));
1768fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // From is a zero-terminated string "hello\0" of length 6
1778fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *from = Ident((char*)malloc(from_size));
1788fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strcpy(from, "hello");
1798fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // copy 0 bytes
1808fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncpy(to, from, 0);
1818fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncpy(to - 1, from - 1, 0);
1828fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // normal strncpy calls
1838fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncpy(to, from, from_size);
1848fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncpy(to, from, to_size);
1858fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncpy(to, from + from_size - 1, to_size);
1868fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncpy(to + to_size - 1, from, 1);
1878fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // One of {to, from} points to not allocated memory
1888fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strncpy(to, from - 1, from_size)),
1898fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany               LeftOOBReadMessage(1));
1908fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strncpy(to - 1, from, from_size)),
1918fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany               LeftOOBWriteMessage(1));
1928fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strncpy(to, from + from_size, 1)),
1938fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany               RightOOBReadMessage(0));
1948fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strncpy(to + to_size, from, 1)),
1958fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany               RightOOBWriteMessage(0));
1968fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Length of "to" is too small
1978fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strncpy(to + to_size - from_size + 1, from, from_size)),
1988fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany               RightOOBWriteMessage(0));
1998fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strncpy(to + 1, from, to_size)),
2008fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany               RightOOBWriteMessage(0));
2018fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Overwrite terminator in from
2028fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  from[from_size - 1] = '!';
2038fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // normal strncpy call
2048fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncpy(to, from, from_size);
2058fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Length of "from" is too small
2068fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(strncpy(to, from, to_size)),
2078fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany               RightOOBReadMessage(0));
2088fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(to);
2098fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(from);
2108fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
2118fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
2128fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// Users may have different definitions of "strchr" and "index", so provide
2138fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// function pointer typedefs and overload RunStrChrTest implementation.
2148fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// We can't use macro for RunStrChrTest body here, as this macro would
2158fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// confuse EXPECT_DEATH gtest macro.
2168fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanytypedef char*(*PointerToStrChr1)(const char*, int);
2178fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanytypedef char*(*PointerToStrChr2)(char*, int);
2188fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
219c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainartemplate<typename StrChrFn>
220c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstatic void RunStrChrTestImpl(StrChrFn *StrChr) {
2218fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t size = Ident(100);
2228fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *str = MallocAndMemsetString(size);
2238fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[10] = 'q';
2248fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[11] = '\0';
2258fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(str, StrChr(str, 'z'));
2268fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(str + 10, StrChr(str, 'q'));
2278fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(NULL, StrChr(str, 'a'));
2288fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // StrChr argument points to not allocated memory.
2298fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrChr(str - 1, 'z')), LeftOOBReadMessage(1));
2308fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrChr(str + size, 'z')), RightOOBReadMessage(0));
2318fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Overwrite the terminator and hit not allocated memory.
2328fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[11] = 'z';
2338fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrChr(str, 'a')), RightOOBReadMessage(0));
2348fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(str);
2358fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
236c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
237c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Prefer to use the standard signature if both are available.
238c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga NainarUNUSED static void RunStrChrTest(PointerToStrChr1 StrChr, ...) {
239c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  RunStrChrTestImpl(StrChr);
240c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
241c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga NainarUNUSED static void RunStrChrTest(PointerToStrChr2 StrChr, int) {
242c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  RunStrChrTestImpl(StrChr);
2438fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
2448fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
2458fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrChrAndIndexOOBTest) {
246c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  RunStrChrTest(&strchr, 0);
2476d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// No index() on Windows and on Android L.
2486d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !defined(_WIN32) && !defined(__ANDROID__)
249c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  RunStrChrTest(&index, 0);
2502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
2518fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
2528fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
2538fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrCmpAndFriendsLogicTest) {
2548fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // strcmp
2558fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, strcmp("", ""));
2568fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, strcmp("abcd", "abcd"));
2578fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_GT(0, strcmp("ab", "ac"));
2588fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_GT(0, strcmp("abc", "abcd"));
2598fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_LT(0, strcmp("acc", "abc"));
2608fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_LT(0, strcmp("abcd", "abc"));
2618fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
2628fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // strncmp
2638fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, strncmp("a", "b", 0));
2648fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, strncmp("abcd", "abcd", 10));
2658fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, strncmp("abcd", "abcef", 3));
2668fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_GT(0, strncmp("abcde", "abcfa", 4));
2678fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_GT(0, strncmp("a", "b", 5));
2688fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_GT(0, strncmp("bc", "bcde", 4));
2698fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_LT(0, strncmp("xyz", "xyy", 10));
2708fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_LT(0, strncmp("baa", "aaa", 1));
2718fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_LT(0, strncmp("zyx", "", 2));
2728fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
2732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !defined(_WIN32)  // no str[n]casecmp on Windows.
2748fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // strcasecmp
2758fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, strcasecmp("", ""));
2768fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, strcasecmp("zzz", "zzz"));
2778fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, strcasecmp("abCD", "ABcd"));
2788fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_GT(0, strcasecmp("aB", "Ac"));
2798fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_GT(0, strcasecmp("ABC", "ABCd"));
2808fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_LT(0, strcasecmp("acc", "abc"));
2818fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_LT(0, strcasecmp("ABCd", "abc"));
2828fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
2838fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // strncasecmp
2848fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, strncasecmp("a", "b", 0));
2858fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, strncasecmp("abCD", "ABcd", 10));
2868fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, strncasecmp("abCd", "ABcef", 3));
2878fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_GT(0, strncasecmp("abcde", "ABCfa", 4));
2888fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_GT(0, strncasecmp("a", "B", 5));
2898fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_GT(0, strncasecmp("bc", "BCde", 4));
2908fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_LT(0, strncasecmp("xyz", "xyy", 10));
2918fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_LT(0, strncasecmp("Baa", "aaa", 1));
2928fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_LT(0, strncasecmp("zyx", "", 2));
2932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
2948fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
2958fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // memcmp
2968fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, memcmp("a", "b", 0));
2978fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_EQ(0, memcmp("ab\0c", "ab\0c", 4));
2988fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_GT(0, memcmp("\0ab", "\0ac", 3));
2998fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_GT(0, memcmp("abb\0", "abba", 4));
3008fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_LT(0, memcmp("ab\0cd", "ab\0c\0", 5));
3018fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_LT(0, memcmp("zza", "zyx", 3));
3028fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
3038fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
3048fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanytypedef int(*PointerToStrCmp)(const char*, const char*);
3058fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanyvoid RunStrCmpTest(PointerToStrCmp StrCmp) {
3068fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t size = Ident(100);
3078fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  int fill = 'o';
3088fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *s1 = MallocAndMemsetString(size, fill);
3098fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *s2 = MallocAndMemsetString(size, fill);
3108fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  s1[size - 1] = '\0';
3118fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  s2[size - 1] = '\0';
3128fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Normal StrCmp calls
3138fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(StrCmp(s1, s2));
3148fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(StrCmp(s1, s2 + size - 1));
3158fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(StrCmp(s1 + size - 1, s2 + size - 1));
3168fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // One of arguments points to not allocated memory.
3178fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrCmp)(s1 - 1, s2), LeftOOBReadMessage(1));
3188fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrCmp)(s1, s2 - 1), LeftOOBReadMessage(1));
3198fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrCmp)(s1 + size, s2), RightOOBReadMessage(0));
3208fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrCmp)(s1, s2 + size), RightOOBReadMessage(0));
3218fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Hit unallocated memory and die.
3228fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  s1[size - 1] = fill;
3238fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrCmp)(s1, s1), RightOOBReadMessage(0));
3248fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrCmp)(s1 + size - 1, s2), RightOOBReadMessage(0));
3258fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(s1);
3268fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(s2);
3278fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
3288fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
3298fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrCmpOOBTest) {
3308fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  RunStrCmpTest(&strcmp);
3318fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
3328fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
3332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !defined(_WIN32)  // no str[n]casecmp on Windows.
3348fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrCaseCmpOOBTest) {
3358fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  RunStrCmpTest(&strcasecmp);
3368fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
3372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
3388fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
3398fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanytypedef int(*PointerToStrNCmp)(const char*, const char*, size_t);
3408fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanyvoid RunStrNCmpTest(PointerToStrNCmp StrNCmp) {
3418fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t size = Ident(100);
3428fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *s1 = MallocAndMemsetString(size);
3438fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *s2 = MallocAndMemsetString(size);
3448fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  s1[size - 1] = '\0';
3458fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  s2[size - 1] = '\0';
3468fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Normal StrNCmp calls
3478fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(StrNCmp(s1, s2, size + 2));
3488fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  s1[size - 1] = 'z';
3498fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  s2[size - 1] = 'x';
3508fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(StrNCmp(s1 + size - 2, s2 + size - 2, size));
3518fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  s2[size - 1] = 'z';
3528fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(StrNCmp(s1 - 1, s2 - 1, 0));
3538fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(StrNCmp(s1 + size - 1, s2 + size - 1, 1));
3548fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // One of arguments points to not allocated memory.
3558fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrNCmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1));
3568fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrNCmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1));
3578fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrNCmp)(s1 + size, s2, 1), RightOOBReadMessage(0));
3588fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrNCmp)(s1, s2 + size, 1), RightOOBReadMessage(0));
3598fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Hit unallocated memory and die.
3608fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrNCmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0));
3618fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(StrNCmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0));
3628fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(s1);
3638fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(s2);
3648fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
3658fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
3668fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrNCmpOOBTest) {
3678fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  RunStrNCmpTest(&strncmp);
3688fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
3698fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
3702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !defined(_WIN32)  // no str[n]casecmp on Windows.
3718fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrNCaseCmpOOBTest) {
3728fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  RunStrNCmpTest(&strncasecmp);
3738fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
3742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
3752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
3768fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrCatOOBTest) {
3778fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // strcat() reads strlen(to) bytes from |to| before concatenating.
3788fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t to_size = Ident(100);
3798fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *to = MallocAndMemsetString(to_size);
3808fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  to[0] = '\0';
3818fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t from_size = Ident(20);
3828fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *from = MallocAndMemsetString(from_size);
3838fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  from[from_size - 1] = '\0';
3848fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Normal strcat calls.
3858fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strcat(to, from);
3868fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strcat(to, from);
3878fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strcat(to + from_size, from + from_size - 2);
3888fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Passing an invalid pointer is an error even when concatenating an empty
3898fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // string.
3908fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strcat(to - 1, from + from_size - 1), LeftOOBAccessMessage(1));
3918fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // One of arguments points to not allocated memory.
3928fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strcat(to - 1, from), LeftOOBAccessMessage(1));
3938fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strcat(to, from - 1), LeftOOBReadMessage(1));
3948fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strcat(to, from + from_size), RightOOBReadMessage(0));
3958fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
3968fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // "from" is not zero-terminated.
3978fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  from[from_size - 1] = 'z';
3988fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strcat(to, from), RightOOBReadMessage(0));
3998fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  from[from_size - 1] = '\0';
4008fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // "to" is too short to fit "from".
401259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  memset(to, 'z', to_size);
4028fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  to[to_size - from_size + 1] = '\0';
4038fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strcat(to, from), RightOOBWriteMessage(0));
4048fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // length of "to" is just enough.
4058fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strcat(to, from + 1);
4068fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
4078fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(to);
4088fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(from);
4098fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
4108fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
4118fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrNCatOOBTest) {
4128fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // strncat() reads strlen(to) bytes from |to| before concatenating.
4138fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t to_size = Ident(100);
4148fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *to = MallocAndMemsetString(to_size);
4158fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  to[0] = '\0';
4168fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t from_size = Ident(20);
4178fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *from = MallocAndMemsetString(from_size);
4188fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Normal strncat calls.
4198fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncat(to, from, 0);
4208fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncat(to, from, from_size);
4218fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  from[from_size - 1] = '\0';
4228fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncat(to, from, 2 * from_size);
4238fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Catenating empty string with an invalid string is still an error.
4248fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strncat(to - 1, from, 0), LeftOOBAccessMessage(1));
4258fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncat(to, from + from_size - 1, 10);
4268fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // One of arguments points to not allocated memory.
4278fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strncat(to - 1, from, 2), LeftOOBAccessMessage(1));
4288fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strncat(to, from - 1, 2), LeftOOBReadMessage(1));
4298fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strncat(to, from + from_size, 2), RightOOBReadMessage(0));
4308fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
4318fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  memset(from, 'z', from_size);
4328fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  memset(to, 'z', to_size);
4338fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  to[0] = '\0';
4348fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // "from" is too short.
4358fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strncat(to, from, from_size + 1), RightOOBReadMessage(0));
4368fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // "to" is too short to fit "from".
4378fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  to[0] = 'z';
4388fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  to[to_size - from_size + 1] = '\0';
4398fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strncat(to, from, from_size - 1), RightOOBWriteMessage(0));
4408fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // "to" is just enough.
4418fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncat(to, from, from_size - 2);
4428fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
4438fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(to);
4448fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(from);
4458fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
4468fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
4478fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanystatic string OverlapErrorMessage(const string &func) {
4488fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  return func + "-param-overlap";
4498fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
4508fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
4518fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrArgsOverlapTest) {
4528fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  size_t size = Ident(100);
4538fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *str = Ident((char*)malloc(size));
4548fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
4558fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// Do not check memcpy() on OS X 10.7 and later, where it actually aliases
4568fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany// memmove().
4578fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany#if !defined(__APPLE__) || !defined(MAC_OS_X_VERSION_10_7) || \
4588fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany    (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7)
4598fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Check "memcpy". Use Ident() to avoid inlining.
4608fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  memset(str, 'z', size);
4618fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(memcpy)(str + 1, str + 11, 10);
4628fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Ident(memcpy)(str, str, 0);
4638fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(memcpy)(str, str + 14, 15), OverlapErrorMessage("memcpy"));
4648fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Ident(memcpy)(str + 14, str, 15), OverlapErrorMessage("memcpy"));
4658fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany#endif
4668fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
4678fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // We do not treat memcpy with to==from as a bug.
4688fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // See http://llvm.org/bugs/show_bug.cgi?id=11763.
4698fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // EXPECT_DEATH(Ident(memcpy)(str + 20, str + 20, 1),
4708fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  //              OverlapErrorMessage("memcpy"));
4718fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
4728fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Check "strcpy".
4738fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  memset(str, 'z', size);
4748fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[9] = '\0';
4758fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strcpy(str + 10, str);
4768fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strcpy(str + 9, str), OverlapErrorMessage("strcpy"));
4778fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strcpy(str, str + 4), OverlapErrorMessage("strcpy"));
4788fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strcpy(str, str + 5);
4798fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
4808fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Check "strncpy".
4818fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  memset(str, 'z', size);
4828fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncpy(str, str + 10, 10);
4838fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strncpy(str, str + 9, 10), OverlapErrorMessage("strncpy"));
4848fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strncpy(str + 9, str, 10), OverlapErrorMessage("strncpy"));
4858fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[10] = '\0';
4868fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncpy(str + 11, str, 20);
4878fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strncpy(str + 10, str, 20), OverlapErrorMessage("strncpy"));
4888fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
4898fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Check "strcat".
4908fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  memset(str, 'z', size);
4918fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[10] = '\0';
4928fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[20] = '\0';
4938fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strcat(str, str + 10);
4948fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strcat(str, str + 11), OverlapErrorMessage("strcat"));
4958fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[10] = '\0';
4968fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strcat(str + 11, str);
4978fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strcat(str, str + 9), OverlapErrorMessage("strcat"));
4988fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strcat(str + 9, str), OverlapErrorMessage("strcat"));
4998fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strcat(str + 10, str), OverlapErrorMessage("strcat"));
5008fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
5018fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Check "strncat".
5028fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  memset(str, 'z', size);
5038fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[10] = '\0';
5048fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncat(str, str + 10, 10);  // from is empty
5058fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strncat(str, str + 11, 10), OverlapErrorMessage("strncat"));
5068fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[10] = '\0';
5078fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[20] = '\0';
5088fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  strncat(str + 5, str, 5);
5098fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  str[10] = '\0';
5108fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strncat(str + 5, str, 6), OverlapErrorMessage("strncat"));
5118fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(strncat(str, str + 9, 10), OverlapErrorMessage("strncat"));
5128fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
5138fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(str);
5148fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
5158fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
5168fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanytypedef void(*PointerToCallAtoi)(const char*);
5178fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
5188fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanyvoid RunAtoiOOBTest(PointerToCallAtoi Atoi) {
5198fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *array = MallocAndMemsetString(10, '1');
5208fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Invalid pointer to the string.
5218fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Atoi(array + 11), RightOOBReadMessage(1));
5228fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Atoi(array - 1), LeftOOBReadMessage(1));
5238fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Die if a buffer doesn't have terminating NULL.
5248fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0));
525259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  // Make last symbol a terminating NULL
5268fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  array[9] = '\0';
5278fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Atoi(array);
5288fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Sometimes we need to detect overflow if no digits are found.
5298fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  memset(array, ' ', 10);
5308fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0));
5318fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  array[9] = '-';
5328fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0));
5338fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Atoi(array + 9), RightOOBReadMessage(0));
5348fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(array);
5358fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
5368fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
5372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !defined(_WIN32)  // FIXME: Fix and enable on Windows.
5386d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid CallAtoi(const char *nptr) {
5396d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  Ident(atoi(nptr));
5406d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}
5416d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid CallAtol(const char *nptr) {
5426d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  Ident(atol(nptr));
5436d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}
5446d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid CallAtoll(const char *nptr) {
5456d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  Ident(atoll(nptr));
5466d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}
5478fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, AtoiAndFriendsOOBTest) {
5488fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  RunAtoiOOBTest(&CallAtoi);
5498fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  RunAtoiOOBTest(&CallAtol);
5508fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  RunAtoiOOBTest(&CallAtoll);
5518fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
5522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5538fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
5548fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanytypedef void(*PointerToCallStrtol)(const char*, char**, int);
5558fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
5568fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryanyvoid RunStrtolOOBTest(PointerToCallStrtol Strtol) {
5578fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  char *array = MallocAndMemsetString(3);
5588fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  array[0] = '1';
5598fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  array[1] = '2';
5608fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  array[2] = '3';
5618fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Invalid pointer to the string.
5628fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Strtol(array + 3, NULL, 0), RightOOBReadMessage(0));
5638fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Strtol(array - 1, NULL, 0), LeftOOBReadMessage(1));
5648fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Buffer overflow if there is no terminating null (depends on base).
5658fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));
5668fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  array[2] = 'z';
5678fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Strtol(array, NULL, 36), RightOOBReadMessage(0));
5688fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Add terminating zero to get rid of overflow.
5698fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  array[2] = '\0';
5708fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  Strtol(array, NULL, 36);
5718fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  // Sometimes we need to detect overflow if no digits are found.
5728fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  array[0] = array[1] = array[2] = ' ';
5738fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));
5748fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  array[2] = '+';
5758fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));
5768fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  array[2] = '-';
5778fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));
5788fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  free(array);
5798fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
5808fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
5812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !defined(_WIN32)  // FIXME: Fix and enable on Windows.
5826d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid CallStrtol(const char *nptr, char **endptr, int base) {
5836d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  Ident(strtol(nptr, endptr, base));
5846d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}
5856d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid CallStrtoll(const char *nptr, char **endptr, int base) {
5866d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  Ident(strtoll(nptr, endptr, base));
5876d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}
5888fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrtollOOBTest) {
5898fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  RunStrtolOOBTest(&CallStrtoll);
5908fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
5918fb1264341c079eda3e10480fb807a0f52bb8b19Kostya SerebryanyTEST(AddressSanitizer, StrtolOOBTest) {
5928fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany  RunStrtolOOBTest(&CallStrtol);
5938fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany}
5942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5958fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
5968fb1264341c079eda3e10480fb807a0f52bb8b19Kostya Serebryany
597