1 //===-- strings_test.cpp ----------------------------------------*- C++ -*-===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "tests/scudo_unit_test.h" 10 11 #include "string_utils.h" 12 13 #include <limits.h> 14 15 TEST(ScudoStringsTest, Constructor) { 16 scudo::ScopedString Str; 17 EXPECT_EQ(0ul, Str.length()); 18 EXPECT_EQ('\0', *Str.data()); 19 } 20 21 TEST(ScudoStringsTest, Basic) { 22 scudo::ScopedString Str; 23 Str.append("a%db%zdc%ue%zuf%xh%zxq%pe%sr", static_cast<int>(-1), 24 static_cast<scudo::uptr>(-2), static_cast<unsigned>(-4), 25 static_cast<scudo::uptr>(5), static_cast<unsigned>(10), 26 static_cast<scudo::uptr>(11), reinterpret_cast<void *>(0x123), 27 "_string_"); 28 EXPECT_EQ(Str.length(), strlen(Str.data())); 29 30 std::string expectedString = "a-1b-2c4294967292e5fahbq0x"; 31 expectedString += std::string(SCUDO_POINTER_FORMAT_LENGTH - 3, '0'); 32 expectedString += "123e_string_r"; 33 EXPECT_EQ(Str.length(), strlen(Str.data())); 34 EXPECT_STREQ(expectedString.c_str(), Str.data()); 35 } 36 37 TEST(ScudoStringsTest, Clear) { 38 scudo::ScopedString Str; 39 Str.append("123"); 40 Str.clear(); 41 EXPECT_EQ(0ul, Str.length()); 42 EXPECT_EQ('\0', *Str.data()); 43 } 44 45 TEST(ScudoStringsTest, ClearLarge) { 46 constexpr char appendString[] = "123"; 47 scudo::ScopedString Str; 48 Str.reserve(sizeof(appendString) * 10000); 49 for (int i = 0; i < 10000; ++i) 50 Str.append(appendString); 51 Str.clear(); 52 EXPECT_EQ(0ul, Str.length()); 53 EXPECT_EQ('\0', *Str.data()); 54 } 55 56 TEST(ScudoStringsTest, Precision) { 57 scudo::ScopedString Str; 58 Str.append("%.*s", 3, "12345"); 59 EXPECT_EQ(Str.length(), strlen(Str.data())); 60 EXPECT_STREQ("123", Str.data()); 61 Str.clear(); 62 Str.append("%.*s", 6, "12345"); 63 EXPECT_EQ(Str.length(), strlen(Str.data())); 64 EXPECT_STREQ("12345", Str.data()); 65 Str.clear(); 66 Str.append("%-6s", "12345"); 67 EXPECT_EQ(Str.length(), strlen(Str.data())); 68 EXPECT_STREQ("12345 ", Str.data()); 69 Str.clear(); 70 Str.append("%-8s", "12345"); 71 EXPECT_EQ(Str.length(), strlen(Str.data())); 72 EXPECT_STREQ("12345 ", Str.data()); 73 } 74 75 static void fillString(scudo::ScopedString &Str, scudo::uptr Size) { 76 for (scudo::uptr I = 0; I < Size; I++) 77 Str.append("A"); 78 } 79 80 TEST(ScudoStringTest, PotentialOverflows) { 81 // Use a ScopedString that spans a page, and attempt to write past the end 82 // of it with variations of append. The expectation is for nothing to crash. 83 const scudo::uptr PageSize = scudo::getPageSizeCached(); 84 scudo::ScopedString Str; 85 Str.reserve(2 * PageSize); 86 Str.clear(); 87 fillString(Str, 2 * PageSize); 88 Str.clear(); 89 fillString(Str, PageSize - 64); 90 Str.append("%-128s", "12345"); 91 Str.clear(); 92 fillString(Str, PageSize - 16); 93 Str.append("%024x", 12345); 94 Str.clear(); 95 fillString(Str, PageSize - 16); 96 Str.append("EEEEEEEEEEEEEEEEEEEEEEEE"); 97 } 98 99 template <typename T> 100 static void testAgainstLibc(const char *Format, T Arg1, T Arg2) { 101 scudo::ScopedString Str; 102 Str.append(Format, Arg1, Arg2); 103 char Buffer[128]; 104 snprintf(Buffer, sizeof(Buffer), Format, Arg1, Arg2); 105 EXPECT_EQ(Str.length(), strlen(Str.data())); 106 EXPECT_STREQ(Buffer, Str.data()); 107 } 108 109 TEST(ScudoStringsTest, MinMax) { 110 testAgainstLibc<int>("%d-%d", INT_MIN, INT_MAX); 111 testAgainstLibc<unsigned>("%u-%u", 0, UINT_MAX); 112 testAgainstLibc<unsigned>("%x-%x", 0, UINT_MAX); 113 testAgainstLibc<long>("%zd-%zd", LONG_MIN, LONG_MAX); 114 testAgainstLibc<unsigned long>("%zu-%zu", 0, ULONG_MAX); 115 testAgainstLibc<unsigned long>("%zx-%zx", 0, ULONG_MAX); 116 } 117 118 TEST(ScudoStringsTest, Padding) { 119 testAgainstLibc<int>("%3d - %3d", 1, 0); 120 testAgainstLibc<int>("%3d - %3d", -1, 123); 121 testAgainstLibc<int>("%3d - %3d", -1, -123); 122 testAgainstLibc<int>("%3d - %3d", 12, 1234); 123 testAgainstLibc<int>("%3d - %3d", -12, -1234); 124 testAgainstLibc<int>("%03d - %03d", 1, 0); 125 testAgainstLibc<int>("%03d - %03d", -1, 123); 126 testAgainstLibc<int>("%03d - %03d", -1, -123); 127 testAgainstLibc<int>("%03d - %03d", 12, 1234); 128 testAgainstLibc<int>("%03d - %03d", -12, -1234); 129 } 130 131 #if defined(__linux__) 132 133 #include <sys/resource.h> 134 135 TEST(ScudoStringsTest, CapacityIncreaseFails) { 136 scudo::ScopedString Str; 137 138 rlimit Limit = {}; 139 EXPECT_EQ(0, getrlimit(RLIMIT_AS, &Limit)); 140 141 rlimit EmptyLimit = {.rlim_cur = 0, .rlim_max = Limit.rlim_max}; 142 EXPECT_EQ(0, setrlimit(RLIMIT_AS, &EmptyLimit)); 143 144 // qemu does not honor the setrlimit, so verify before proceeding. 145 scudo::MemMapT MemMap; 146 if (MemMap.map(/*Addr=*/0U, scudo::getPageSizeCached(), "scudo:test", 147 MAP_ALLOWNOMEM)) { 148 MemMap.unmap(); 149 setrlimit(RLIMIT_AS, &Limit); 150 TEST_SKIP("Limiting address space does not prevent mmap."); 151 } 152 153 // Test requires that the default length is at least 6 characters. 154 scudo::uptr MaxSize = Str.capacity(); 155 EXPECT_LE(6u, MaxSize); 156 157 for (size_t i = 0; i < MaxSize - 5; i++) { 158 Str.append("B"); 159 } 160 161 // Attempt to append past the end of the current capacity. 162 Str.append("%d", 12345678); 163 EXPECT_EQ(MaxSize, Str.capacity()); 164 EXPECT_STREQ("B12345", &Str.data()[MaxSize - 6]); 165 166 EXPECT_EQ(0, setrlimit(RLIMIT_AS, &Limit)); 167 } 168 #endif 169