xref: /aosp_15_r20/external/scudo/standalone/tests/strings_test.cpp (revision 76559068c068bd27e82aff38fac3bfc865233bca)
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 
TEST(ScudoStringsTest,Constructor)15 TEST(ScudoStringsTest, Constructor) {
16   scudo::ScopedString Str;
17   EXPECT_EQ(0ul, Str.length());
18   EXPECT_EQ('\0', *Str.data());
19 }
20 
TEST(ScudoStringsTest,Basic)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 
TEST(ScudoStringsTest,Clear)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 
TEST(ScudoStringsTest,ClearLarge)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 
TEST(ScudoStringsTest,Precision)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 
fillString(scudo::ScopedString & Str,scudo::uptr Size)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 
TEST(ScudoStringTest,PotentialOverflows)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>
testAgainstLibc(const char * Format,T Arg1,T Arg2)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 
TEST(ScudoStringsTest,MinMax)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 
TEST(ScudoStringsTest,Padding)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 
TEST(ScudoStringsTest,CapacityIncreaseFails)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