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