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   scudo::ScopedString Str;
47   for (int i = 0; i < 10000; ++i)
48     Str.append("123");
49   Str.clear();
50   EXPECT_EQ(0ul, Str.length());
51   EXPECT_EQ('\0', *Str.data());
52 }
53 
54 TEST(ScudoStringsTest, Precision) {
55   scudo::ScopedString Str;
56   Str.append("%.*s", 3, "12345");
57   EXPECT_EQ(Str.length(), strlen(Str.data()));
58   EXPECT_STREQ("123", Str.data());
59   Str.clear();
60   Str.append("%.*s", 6, "12345");
61   EXPECT_EQ(Str.length(), strlen(Str.data()));
62   EXPECT_STREQ("12345", Str.data());
63   Str.clear();
64   Str.append("%-6s", "12345");
65   EXPECT_EQ(Str.length(), strlen(Str.data()));
66   EXPECT_STREQ("12345 ", Str.data());
67 }
68 
69 static void fillString(scudo::ScopedString &Str, scudo::uptr Size) {
70   for (scudo::uptr I = 0; I < Size; I++)
71     Str.append("A");
72 }
73 
74 TEST(ScudoStringTest, PotentialOverflows) {
75   // Use a ScopedString that spans a page, and attempt to write past the end
76   // of it with variations of append. The expectation is for nothing to crash.
77   const scudo::uptr PageSize = scudo::getPageSizeCached();
78   scudo::ScopedString Str;
79   Str.clear();
80   fillString(Str, 2 * PageSize);
81   Str.clear();
82   fillString(Str, PageSize - 64);
83   Str.append("%-128s", "12345");
84   Str.clear();
85   fillString(Str, PageSize - 16);
86   Str.append("%024x", 12345);
87   Str.clear();
88   fillString(Str, PageSize - 16);
89   Str.append("EEEEEEEEEEEEEEEEEEEEEEEE");
90 }
91 
92 template <typename T>
93 static void testAgainstLibc(const char *Format, T Arg1, T Arg2) {
94   scudo::ScopedString Str;
95   Str.append(Format, Arg1, Arg2);
96   char Buffer[128];
97   snprintf(Buffer, sizeof(Buffer), Format, Arg1, Arg2);
98   EXPECT_EQ(Str.length(), strlen(Str.data()));
99   EXPECT_STREQ(Buffer, Str.data());
100 }
101 
102 TEST(ScudoStringsTest, MinMax) {
103   testAgainstLibc<int>("%d-%d", INT_MIN, INT_MAX);
104   testAgainstLibc<unsigned>("%u-%u", 0, UINT_MAX);
105   testAgainstLibc<unsigned>("%x-%x", 0, UINT_MAX);
106   testAgainstLibc<long>("%zd-%zd", LONG_MIN, LONG_MAX);
107   testAgainstLibc<unsigned long>("%zu-%zu", 0, ULONG_MAX);
108   testAgainstLibc<unsigned long>("%zx-%zx", 0, ULONG_MAX);
109 }
110 
111 TEST(ScudoStringsTest, Padding) {
112   testAgainstLibc<int>("%3d - %3d", 1, 0);
113   testAgainstLibc<int>("%3d - %3d", -1, 123);
114   testAgainstLibc<int>("%3d - %3d", -1, -123);
115   testAgainstLibc<int>("%3d - %3d", 12, 1234);
116   testAgainstLibc<int>("%3d - %3d", -12, -1234);
117   testAgainstLibc<int>("%03d - %03d", 1, 0);
118   testAgainstLibc<int>("%03d - %03d", -1, 123);
119   testAgainstLibc<int>("%03d - %03d", -1, -123);
120   testAgainstLibc<int>("%03d - %03d", 12, 1234);
121   testAgainstLibc<int>("%03d - %03d", -12, -1234);
122 }
123