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