brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.5 KiB · b28143d Raw
665 lines · cpp
1//=-- asan_str_test.cpp ---------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of AddressSanitizer, an address sanity checker.10//11//===----------------------------------------------------------------------===//12#include "asan_test_utils.h"13 14#if defined(__APPLE__)15#include <AvailabilityMacros.h>  // For MAC_OS_X_VERSION_*16#endif17 18// Used for string functions tests19static char global_string[] = "global";20static size_t global_string_length = 6;21 22const char kStackReadUnderflow[] =23#if !GTEST_USES_SIMPLE_RE24    ASAN_PCRE_DOTALL25    "READ.*"26#endif27    "underflows this variable";28const char kStackReadOverflow[] =29#if !GTEST_USES_SIMPLE_RE30    ASAN_PCRE_DOTALL31    "READ.*"32#endif33    "overflows this variable";34 35namespace {36enum class OOBKind {37  Heap,38  Stack,39  Global,40};41 42std::string LeftOOBReadMessage(OOBKind oob_kind, int oob_distance) {43  return oob_kind == OOBKind::Stack ? kStackReadUnderflow44                                    : ::LeftOOBReadMessage(oob_distance);45}46 47std::string RightOOBReadMessage(OOBKind oob_kind, int oob_distance) {48  return oob_kind == OOBKind::Stack ? kStackReadOverflow49                                    : ::RightOOBReadMessage(oob_distance);50}51}  // namespace52 53// Input to a test is a zero-terminated string str with given length54// Accesses to the bytes before and after str55// are presumed to produce OOB errors56void StrLenOOBTestTemplate(char *str, size_t length, OOBKind oob_kind) {57  // Normal strlen calls58  EXPECT_EQ(strlen(str), length);59  if (length > 0) {60    EXPECT_EQ(length - 1, strlen(str + 1));61    EXPECT_EQ(0U, strlen(str + length));62  }63  // Arg of strlen is not malloced, OOB access64  if (oob_kind != OOBKind::Global) {65    // We don't insert RedZones before global variables66    EXPECT_DEATH(Ident(strlen(str - 1)), LeftOOBReadMessage(oob_kind, 1));67    EXPECT_DEATH(Ident(strlen(str - 5)), LeftOOBReadMessage(oob_kind, 5));68  }69  EXPECT_DEATH(Ident(strlen(str + length + 1)),70               RightOOBReadMessage(oob_kind, 0));71  // Overwrite terminator72  str[length] = 'a';73  // String is not zero-terminated, strlen will lead to OOB access74  EXPECT_DEATH(Ident(strlen(str)), RightOOBReadMessage(oob_kind, 0));75  EXPECT_DEATH(Ident(strlen(str + length)), RightOOBReadMessage(oob_kind, 0));76  // Restore terminator77  str[length] = 0;78}79TEST(AddressSanitizer, StrLenOOBTest) {80  // Check heap-allocated string81  size_t length = Ident(10);82  char *heap_string = Ident((char*)malloc(length + 1));83  char stack_string[10 + 1];84  break_optimization(&stack_string);85  for (size_t i = 0; i < length; i++) {86    heap_string[i] = 'a';87    stack_string[i] = 'b';88  }89  heap_string[length] = 0;90  stack_string[length] = 0;91  StrLenOOBTestTemplate(heap_string, length, OOBKind::Heap);92  StrLenOOBTestTemplate(stack_string, length, OOBKind::Stack);93  StrLenOOBTestTemplate(global_string, global_string_length, OOBKind::Global);94  free(heap_string);95}96 97// 32-bit android libc++-based NDK toolchain links wcslen statically, disabling98// the interceptor.99#if !defined(__ANDROID__) || defined(__LP64__)100TEST(AddressSanitizer, WcsLenTest) {101  EXPECT_EQ(0U, wcslen(Ident(L"")));102  size_t hello_len = 13;103  size_t hello_size = (hello_len + 1) * sizeof(wchar_t);104  EXPECT_EQ(hello_len, wcslen(Ident(L"Hello, World!")));105  wchar_t *heap_string = Ident((wchar_t*)malloc(hello_size));106  memcpy(heap_string, L"Hello, World!", hello_size);107  EXPECT_EQ(hello_len, Ident(wcslen(heap_string)));108  EXPECT_DEATH(Ident(wcslen(heap_string + 14)), RightOOBReadMessage(0));109  free(heap_string);110}111#endif112 113// This test fails on MinGW-w64 because it still ships a static copy of strnlen114// despite it being available from UCRT.115#if defined(__MINGW32__)116#  define MAYBE_StrNLenOOBTest DISABLED_StrNLenOOBTest117#else118#  define MAYBE_StrNLenOOBTest StrNLenOOBTest119#endif120 121#if SANITIZER_TEST_HAS_STRNLEN122TEST(AddressSanitizer, MAYBE_StrNLenOOBTest) {123  size_t size = Ident(123);124  char *str = MallocAndMemsetString(size);125  // Normal strnlen calls.126  Ident(strnlen(str - 1, 0));127  Ident(strnlen(str, size));128  Ident(strnlen(str + size - 1, 1));129  str[size - 1] = '\0';130  Ident(strnlen(str, 2 * size));131  // Argument points to not allocated memory.132  EXPECT_DEATH(Ident(strnlen(str - 1, 1)), LeftOOBReadMessage(1));133  EXPECT_DEATH(Ident(strnlen(str + size, 1)), RightOOBReadMessage(0));134  // Overwrite the terminating '\0' and hit unallocated memory.135  str[size - 1] = 'z';136  EXPECT_DEATH(Ident(strnlen(str, size + 1)), RightOOBReadMessage(0));137  free(str);138}139#endif  // SANITIZER_TEST_HAS_STRNLEN140 141// This test fails with the WinASan dynamic runtime because we fail to intercept142// strdup.143#if (defined(_MSC_VER) && defined(_DLL)) || defined(__MINGW32__)144#  define MAYBE_StrDupOOBTest DISABLED_StrDupOOBTest145#else146#  define MAYBE_StrDupOOBTest StrDupOOBTest147#endif148 149TEST(AddressSanitizer, MAYBE_StrDupOOBTest) {150  size_t size = Ident(42);151  char *str = MallocAndMemsetString(size);152  char *new_str;153  // Normal strdup calls.154  str[size - 1] = '\0';155  new_str = strdup(str);156  free(new_str);157  new_str = strdup(str + size - 1);158  free(new_str);159  // Argument points to not allocated memory.160  EXPECT_DEATH(Ident(strdup(str - 1)), LeftOOBReadMessage(1));161  EXPECT_DEATH(Ident(strdup(str + size)), RightOOBReadMessage(0));162  // Overwrite the terminating '\0' and hit unallocated memory.163  str[size - 1] = 'z';164  EXPECT_DEATH(Ident(strdup(str)), RightOOBReadMessage(0));165  free(str);166}167 168#if SANITIZER_TEST_HAS_STRNDUP169TEST(AddressSanitizer, MAYBE_StrNDupOOBTest) {170  size_t size = Ident(42);171  char *str = MallocAndMemsetString(size);172  char *new_str;173  // Normal strndup calls.174  str[size - 1] = '\0';175  new_str = strndup(str, size - 13);176  free(new_str);177  new_str = strndup(str + size - 1, 13);178  free(new_str);179  // Argument points to not allocated memory.180  EXPECT_DEATH(Ident(strndup(str - 1, 13)), LeftOOBReadMessage(1));181  EXPECT_DEATH(Ident(strndup(str + size, 13)), RightOOBReadMessage(0));182  // Overwrite the terminating '\0' and hit unallocated memory.183  str[size - 1] = 'z';184  EXPECT_DEATH(Ident(strndup(str, size + 13)), RightOOBReadMessage(0));185  // Check handling of non 0 terminated strings.186  Ident(new_str = strndup(str + size - 1, 0));187  free(new_str);188  Ident(new_str = strndup(str + size - 1, 1));189  free(new_str);190  EXPECT_DEATH(Ident(strndup(str + size - 1, 2)), RightOOBReadMessage(0));191  free(str);192}193#endif // SANITIZER_TEST_HAS_STRNDUP194 195TEST(AddressSanitizer, StrCpyOOBTest) {196  size_t to_size = Ident(30);197  size_t from_size = Ident(6);  // less than to_size198  char *to = Ident((char*)malloc(to_size));199  char *from = Ident((char*)malloc(from_size));200  // Normal strcpy calls.201  strcpy(from, "hello");202  strcpy(to, from);203  strcpy(to + to_size - from_size, from);204  // Length of "from" is too small.205  EXPECT_DEATH(Ident(strcpy(from, "hello2")), RightOOBWriteMessage(0));206  // "to" or "from" points to not allocated memory.207  EXPECT_DEATH(Ident(strcpy(to - 1, from)), LeftOOBWriteMessage(1));208  EXPECT_DEATH(Ident(strcpy(to, from - 1)), LeftOOBReadMessage(1));209  EXPECT_DEATH(Ident(strcpy(to, from + from_size)), RightOOBReadMessage(0));210  EXPECT_DEATH(Ident(strcpy(to + to_size, from)), RightOOBWriteMessage(0));211  // Overwrite the terminating '\0' character and hit unallocated memory.212  from[from_size - 1] = '!';213  EXPECT_DEATH(Ident(strcpy(to, from)), RightOOBReadMessage(0));214  free(to);215  free(from);216}217 218TEST(AddressSanitizer, StrNCpyOOBTest) {219  size_t to_size = Ident(20);220  size_t from_size = Ident(6);  // less than to_size221  char *to = Ident((char*)malloc(to_size));222  // From is a zero-terminated string "hello\0" of length 6223  char *from = Ident((char*)malloc(from_size));224  strcpy(from, "hello");225  // copy 0 bytes226  strncpy(to, from, 0);227  strncpy(to - 1, from - 1, 0);228  // normal strncpy calls229  strncpy(to, from, from_size);230  strncpy(to, from, to_size);231  strncpy(to, from + from_size - 1, to_size);232  strncpy(to + to_size - 1, from, 1);233  // One of {to, from} points to not allocated memory234  EXPECT_DEATH(Ident(strncpy(to, from - 1, from_size)),235               LeftOOBReadMessage(1));236  EXPECT_DEATH(Ident(strncpy(to - 1, from, from_size)),237               LeftOOBWriteMessage(1));238  EXPECT_DEATH(Ident(strncpy(to, from + from_size, 1)),239               RightOOBReadMessage(0));240  EXPECT_DEATH(Ident(strncpy(to + to_size, from, 1)),241               RightOOBWriteMessage(0));242  // Length of "to" is too small243  EXPECT_DEATH(Ident(strncpy(to + to_size - from_size + 1, from, from_size)),244               RightOOBWriteMessage(0));245  EXPECT_DEATH(Ident(strncpy(to + 1, from, to_size)),246               RightOOBWriteMessage(0));247  // Overwrite terminator in from248  from[from_size - 1] = '!';249  // normal strncpy call250  strncpy(to, from, from_size);251  // Length of "from" is too small252  EXPECT_DEATH(Ident(strncpy(to, from, to_size)),253               RightOOBReadMessage(0));254  free(to);255  free(from);256}257 258// Users may have different definitions of "strchr" and "index", so provide259// function pointer typedefs and overload RunStrChrTest implementation.260// We can't use macro for RunStrChrTest body here, as this macro would261// confuse EXPECT_DEATH gtest macro.262typedef char*(*PointerToStrChr1)(const char*, int);263typedef char*(*PointerToStrChr2)(char*, int);264 265template<typename StrChrFn>266static void RunStrChrTestImpl(StrChrFn *StrChr) {267  size_t size = Ident(100);268  char *str = MallocAndMemsetString(size);269  str[10] = 'q';270  str[11] = '\0';271  EXPECT_EQ(str, StrChr(str, 'z'));272  EXPECT_EQ(str + 10, StrChr(str, 'q'));273  EXPECT_EQ(NULL, StrChr(str, 'a'));274  // StrChr argument points to not allocated memory.275  EXPECT_DEATH(Ident(StrChr(str - 1, 'z')), LeftOOBReadMessage(1));276  EXPECT_DEATH(Ident(StrChr(str + size, 'z')), RightOOBReadMessage(0));277  // Overwrite the terminator and hit not allocated memory.278  str[11] = 'z';279  EXPECT_DEATH(Ident(StrChr(str, 'a')), RightOOBReadMessage(0));280  free(str);281}282 283// Prefer to use the standard signature if both are available.284UNUSED static void RunStrChrTest(PointerToStrChr1 StrChr, ...) {285  RunStrChrTestImpl(StrChr);286}287UNUSED static void RunStrChrTest(PointerToStrChr2 StrChr, int) {288  RunStrChrTestImpl(StrChr);289}290 291TEST(AddressSanitizer, StrChrAndIndexOOBTest) {292  RunStrChrTest(&strchr, 0);293// No index() on Windows and on Android L.294#if !defined(_WIN32) && !defined(__ANDROID__)295  RunStrChrTest(&index, 0);296#endif297}298 299TEST(AddressSanitizer, StrCmpAndFriendsLogicTest) {300  // strcmp301  EXPECT_EQ(0, strcmp("", ""));302  EXPECT_EQ(0, strcmp("abcd", "abcd"));303  EXPECT_GT(0, strcmp("ab", "ac"));304  EXPECT_GT(0, strcmp("abc", "abcd"));305  EXPECT_LT(0, strcmp("acc", "abc"));306  EXPECT_LT(0, strcmp("abcd", "abc"));307 308  // strncmp309  EXPECT_EQ(0, strncmp("a", "b", 0));310  EXPECT_EQ(0, strncmp("abcd", "abcd", 10));311  EXPECT_EQ(0, strncmp("abcd", "abcef", 3));312  EXPECT_GT(0, strncmp("abcde", "abcfa", 4));313  EXPECT_GT(0, strncmp("a", "b", 5));314  EXPECT_GT(0, strncmp("bc", "bcde", 4));315  EXPECT_LT(0, strncmp("xyz", "xyy", 10));316  EXPECT_LT(0, strncmp("baa", "aaa", 1));317  EXPECT_LT(0, strncmp("zyx", "", 2));318 319#if !defined(_WIN32)  // no str[n]casecmp on Windows.320  // strcasecmp321  EXPECT_EQ(0, strcasecmp("", ""));322  EXPECT_EQ(0, strcasecmp("zzz", "zzz"));323  EXPECT_EQ(0, strcasecmp("abCD", "ABcd"));324  EXPECT_GT(0, strcasecmp("aB", "Ac"));325  EXPECT_GT(0, strcasecmp("ABC", "ABCd"));326  EXPECT_LT(0, strcasecmp("acc", "abc"));327  EXPECT_LT(0, strcasecmp("ABCd", "abc"));328 329  // strncasecmp330  EXPECT_EQ(0, strncasecmp("a", "b", 0));331  EXPECT_EQ(0, strncasecmp("abCD", "ABcd", 10));332  EXPECT_EQ(0, strncasecmp("abCd", "ABcef", 3));333  EXPECT_GT(0, strncasecmp("abcde", "ABCfa", 4));334  EXPECT_GT(0, strncasecmp("a", "B", 5));335  EXPECT_GT(0, strncasecmp("bc", "BCde", 4));336  EXPECT_LT(0, strncasecmp("xyz", "xyy", 10));337  EXPECT_LT(0, strncasecmp("Baa", "aaa", 1));338  EXPECT_LT(0, strncasecmp("zyx", "", 2));339#endif340 341  // memcmp342  EXPECT_EQ(0, memcmp("a", "b", 0));343  EXPECT_EQ(0, memcmp("ab\0c", "ab\0c", 4));344  EXPECT_GT(0, memcmp("\0ab", "\0ac", 3));345  EXPECT_GT(0, memcmp("abb\0", "abba", 4));346  EXPECT_LT(0, memcmp("ab\0cd", "ab\0c\0", 5));347  EXPECT_LT(0, memcmp("zza", "zyx", 3));348}349 350typedef int(*PointerToStrCmp)(const char*, const char*);351void RunStrCmpTest(PointerToStrCmp StrCmp) {352  size_t size = Ident(100);353  int fill = 'o';354  char *s1 = MallocAndMemsetString(size, fill);355  char *s2 = MallocAndMemsetString(size, fill);356  s1[size - 1] = '\0';357  s2[size - 1] = '\0';358  // Normal StrCmp calls359  Ident(StrCmp(s1, s2));360  Ident(StrCmp(s1, s2 + size - 1));361  Ident(StrCmp(s1 + size - 1, s2 + size - 1));362  // One of arguments points to not allocated memory.363  EXPECT_DEATH(Ident(StrCmp)(s1 - 1, s2), LeftOOBReadMessage(1));364  EXPECT_DEATH(Ident(StrCmp)(s1, s2 - 1), LeftOOBReadMessage(1));365  EXPECT_DEATH(Ident(StrCmp)(s1 + size, s2), RightOOBReadMessage(0));366  EXPECT_DEATH(Ident(StrCmp)(s1, s2 + size), RightOOBReadMessage(0));367  // Hit unallocated memory and die.368  s1[size - 1] = fill;369  EXPECT_DEATH(Ident(StrCmp)(s1, s1), RightOOBReadMessage(0));370  EXPECT_DEATH(Ident(StrCmp)(s1 + size - 1, s2), RightOOBReadMessage(0));371  free(s1);372  free(s2);373}374 375TEST(AddressSanitizer, StrCmpOOBTest) {376  RunStrCmpTest(&strcmp);377}378 379#if !defined(_WIN32)  // no str[n]casecmp on Windows.380TEST(AddressSanitizer, StrCaseCmpOOBTest) {381  RunStrCmpTest(&strcasecmp);382}383#endif384 385typedef int(*PointerToStrNCmp)(const char*, const char*, size_t);386void RunStrNCmpTest(PointerToStrNCmp StrNCmp) {387  size_t size = Ident(100);388  char *s1 = MallocAndMemsetString(size);389  char *s2 = MallocAndMemsetString(size);390  s1[size - 1] = '\0';391  s2[size - 1] = '\0';392  // Normal StrNCmp calls393  Ident(StrNCmp(s1, s2, size + 2));394  s1[size - 1] = 'z';395  s2[size - 1] = 'x';396  Ident(StrNCmp(s1 + size - 2, s2 + size - 2, size));397  s2[size - 1] = 'z';398  Ident(StrNCmp(s1 - 1, s2 - 1, 0));399  Ident(StrNCmp(s1 + size - 1, s2 + size - 1, 1));400  // One of arguments points to not allocated memory.401  EXPECT_DEATH(Ident(StrNCmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1));402  EXPECT_DEATH(Ident(StrNCmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1));403  EXPECT_DEATH(Ident(StrNCmp)(s1 + size, s2, 1), RightOOBReadMessage(0));404  EXPECT_DEATH(Ident(StrNCmp)(s1, s2 + size, 1), RightOOBReadMessage(0));405  // Hit unallocated memory and die.406  EXPECT_DEATH(Ident(StrNCmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0));407  EXPECT_DEATH(Ident(StrNCmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0));408  free(s1);409  free(s2);410}411 412TEST(AddressSanitizer, StrNCmpOOBTest) {413  RunStrNCmpTest(&strncmp);414}415 416#if !defined(_WIN32)  // no str[n]casecmp on Windows.417TEST(AddressSanitizer, StrNCaseCmpOOBTest) {418  RunStrNCmpTest(&strncasecmp);419}420#endif421 422TEST(AddressSanitizer, StrCatOOBTest) {423  // strcat() reads strlen(to) bytes from |to| before concatenating.424  size_t to_size = Ident(100);425  char *to = MallocAndMemsetString(to_size);426  to[0] = '\0';427  size_t from_size = Ident(20);428  char *from = MallocAndMemsetString(from_size);429  from[from_size - 1] = '\0';430  // Normal strcat calls.431  strcat(to, from);432  strcat(to, from);433  strcat(to + from_size, from + from_size - 2);434  // Passing an invalid pointer is an error even when concatenating an empty435  // string.436  EXPECT_DEATH(strcat(to - 1, from + from_size - 1), LeftOOBAccessMessage(1));437  // One of arguments points to not allocated memory.438  EXPECT_DEATH(strcat(to - 1, from), LeftOOBAccessMessage(1));439  EXPECT_DEATH(strcat(to, from - 1), LeftOOBReadMessage(1));440  EXPECT_DEATH(strcat(to, from + from_size), RightOOBReadMessage(0));441 442  // "from" is not zero-terminated.443  from[from_size - 1] = 'z';444  EXPECT_DEATH(strcat(to, from), RightOOBReadMessage(0));445  from[from_size - 1] = '\0';446  // "to" is too short to fit "from".447  memset(to, 'z', to_size);448  to[to_size - from_size + 1] = '\0';449  EXPECT_DEATH(strcat(to, from), RightOOBWriteMessage(0));450  // length of "to" is just enough.451  strcat(to, from + 1);452 453  free(to);454  free(from);455}456 457TEST(AddressSanitizer, StrNCatOOBTest) {458  // strncat() reads strlen(to) bytes from |to| before concatenating.459  size_t to_size = Ident(100);460  char *to = MallocAndMemsetString(to_size);461  to[0] = '\0';462  size_t from_size = Ident(20);463  char *from = MallocAndMemsetString(from_size);464  // Normal strncat calls.465  strncat(to, from, 0);466  strncat(to, from, from_size);467  from[from_size - 1] = '\0';468  strncat(to, from, 2 * from_size);469  strncat(to, from + from_size - 1, 10);470  // One of arguments points to not allocated memory.471  EXPECT_DEATH(strncat(to - 1, from, 2), LeftOOBAccessMessage(1));472  EXPECT_DEATH(strncat(to, from - 1, 2), LeftOOBReadMessage(1));473  EXPECT_DEATH(strncat(to, from + from_size, 2), RightOOBReadMessage(0));474 475  memset(from, 'z', from_size);476  memset(to, 'z', to_size);477  to[0] = '\0';478  // "from" is too short.479  EXPECT_DEATH(strncat(to, from, from_size + 1), RightOOBReadMessage(0));480  // "to" is too short to fit "from".481  to[0] = 'z';482  to[to_size - from_size + 1] = '\0';483  EXPECT_DEATH(strncat(to, from, from_size - 1), RightOOBWriteMessage(0));484  // "to" is just enough.485  strncat(to, from, from_size - 2);486 487  free(to);488  free(from);489}490 491static std::string OverlapErrorMessage(const std::string &func) {492  return func + "-param-overlap";493}494 495TEST(AddressSanitizer, StrArgsOverlapTest) {496  size_t size = Ident(100);497  char *str = Ident((char*)malloc(size));498 499// Do not check memcpy() on OS X 10.7 and later, where it actually aliases500// memmove().501#if !defined(__APPLE__) || !defined(MAC_OS_X_VERSION_10_7) || \502    (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7)503  // Check "memcpy". Use Ident() to avoid inlining.504#if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE505  memset(str, 'z', size);506  Ident(memcpy)(str + 1, str + 11, 10);507  Ident(memcpy)(str, str, 0);508  EXPECT_DEATH(Ident(memcpy)(str, str + 14, 15), OverlapErrorMessage("memcpy"));509  EXPECT_DEATH(Ident(memcpy)(str + 14, str, 15), OverlapErrorMessage("memcpy"));510#endif511#endif512 513  // We do not treat memcpy with to==from as a bug.514  // See http://llvm.org/bugs/show_bug.cgi?id=11763.515  // EXPECT_DEATH(Ident(memcpy)(str + 20, str + 20, 1),516  //              OverlapErrorMessage("memcpy"));517 518  // Check "strcpy".519  memset(str, 'z', size);520  str[9] = '\0';521  strcpy(str + 10, str);522  EXPECT_DEATH(strcpy(str + 9, str), OverlapErrorMessage("strcpy"));523  EXPECT_DEATH(strcpy(str, str + 4), OverlapErrorMessage("strcpy"));524  strcpy(str, str + 5);525 526  // Check "strncpy".527  memset(str, 'z', size);528  strncpy(str, str + 10, 10);529  EXPECT_DEATH(strncpy(str, str + 9, 10), OverlapErrorMessage("strncpy"));530  EXPECT_DEATH(strncpy(str + 9, str, 10), OverlapErrorMessage("strncpy"));531  str[10] = '\0';532  strncpy(str + 11, str, 20);533  EXPECT_DEATH(strncpy(str + 10, str, 20), OverlapErrorMessage("strncpy"));534 535  // Check "strcat".536  memset(str, 'z', size);537  str[10] = '\0';538  str[20] = '\0';539  strcat(str, str + 10);540  EXPECT_DEATH(strcat(str, str + 11), OverlapErrorMessage("strcat"));541  str[10] = '\0';542  strcat(str + 11, str);543  EXPECT_DEATH(strcat(str, str + 9), OverlapErrorMessage("strcat"));544  EXPECT_DEATH(strcat(str + 9, str), OverlapErrorMessage("strcat"));545  EXPECT_DEATH(strcat(str + 10, str), OverlapErrorMessage("strcat"));546 547  // Check "strncat".548  memset(str, 'z', size);549  str[10] = '\0';550  strncat(str, str + 10, 10);  // from is empty551  EXPECT_DEATH(strncat(str, str + 11, 10), OverlapErrorMessage("strncat"));552  str[10] = '\0';553  str[20] = '\0';554  strncat(str + 5, str, 5);555  str[10] = '\0';556  EXPECT_DEATH(strncat(str + 5, str, 6), OverlapErrorMessage("strncat"));557  EXPECT_DEATH(strncat(str, str + 9, 10), OverlapErrorMessage("strncat"));558 559  free(str);560}561 562typedef void(*PointerToCallAtoi)(const char*);563 564void RunAtoiOOBTest(PointerToCallAtoi Atoi) {565  char *array = MallocAndMemsetString(10, '1');566  // Invalid pointer to the string.567  EXPECT_DEATH(Atoi(array + 11), RightOOBReadMessage(1));568  EXPECT_DEATH(Atoi(array - 1), LeftOOBReadMessage(1));569  // Die if a buffer doesn't have terminating NULL.570  EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0));571  // Make last symbol a terminating NULL572  array[9] = '\0';573  Atoi(array);574  // Sometimes we need to detect overflow if no digits are found.575  memset(array, ' ', 10);576  EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0));577  array[9] = '-';578  EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0));579  EXPECT_DEATH(Atoi(array + 9), RightOOBReadMessage(0));580  free(array);581}582 583#if !defined(_WIN32)  // FIXME: Fix and enable on Windows.584void CallAtoi(const char *nptr) {585  Ident(atoi(nptr));586}587void CallAtol(const char *nptr) {588  Ident(atol(nptr));589}590void CallAtoll(const char *nptr) {591  Ident(atoll(nptr));592}593TEST(AddressSanitizer, AtoiAndFriendsOOBTest) {594  RunAtoiOOBTest(&CallAtoi);595  RunAtoiOOBTest(&CallAtol);596  RunAtoiOOBTest(&CallAtoll);597}598#endif599 600typedef void(*PointerToCallStrtol)(const char*, char**, int);601 602void RunStrtolOOBTest(PointerToCallStrtol Strtol) {603  char *array = MallocAndMemsetString(3);604  array[0] = '1';605  array[1] = '2';606  array[2] = '3';607  // Invalid pointer to the string.608  EXPECT_DEATH(Strtol(array + 3, NULL, 0), RightOOBReadMessage(0));609  EXPECT_DEATH(Strtol(array - 1, NULL, 0), LeftOOBReadMessage(1));610  // Buffer overflow if there is no terminating null (depends on base).611  EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));612  array[2] = 'z';613  EXPECT_DEATH(Strtol(array, NULL, 36), RightOOBReadMessage(0));614  // Add terminating zero to get rid of overflow.615  array[2] = '\0';616  Strtol(array, NULL, 36);617  // Sometimes we need to detect overflow if no digits are found.618  array[0] = array[1] = array[2] = ' ';619  EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));620  array[2] = '+';621  EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));622  array[2] = '-';623  EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));624  free(array);625}626 627#if !defined(_WIN32)  // FIXME: Fix and enable on Windows.628void CallStrtol(const char *nptr, char **endptr, int base) {629  Ident(strtol(nptr, endptr, base));630}631void CallStrtoll(const char *nptr, char **endptr, int base) {632  Ident(strtoll(nptr, endptr, base));633}634TEST(AddressSanitizer, StrtollOOBTest) {635  RunStrtolOOBTest(&CallStrtoll);636}637TEST(AddressSanitizer, StrtolOOBTest) {638  RunStrtolOOBTest(&CallStrtol);639}640#endif641 642TEST(AddressSanitizer, StrtolOverflow) {643  if (sizeof(long) == 4) {644    // Check that errno gets set correctly on 32-bit strtol overflow.645    long res;646    errno = 0;647    res = Ident(strtol("2147483647", NULL, 0));648    EXPECT_EQ(errno, 0);649    EXPECT_EQ(res, 2147483647);650 651    res = Ident(strtol("2147483648", NULL, 0));652    EXPECT_EQ(errno, ERANGE);653    EXPECT_EQ(res, 2147483647);654 655    errno = 0;656    res = Ident(strtol("-2147483648", NULL, 0));657    EXPECT_EQ(errno, 0);658    EXPECT_EQ(res, -2147483648);659 660    res = Ident(strtol("-2147483649", NULL, 0));661    EXPECT_EQ(errno, ERANGE);662    EXPECT_EQ(res, -2147483648);663  }664}665