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 "scudo/standalone/string_utils.h"
10 #include "gtest/gtest.h"
11 
12 #include <limits.h>
13 
14 TEST(ScudoStringsTest, Basic) {
15   scudo::ScopedString Str(128);
16   Str.append("a%db%zdc%ue%zuf%xh%zxq%pe%sr", static_cast<int>(-1),
17              static_cast<scudo::uptr>(-2), static_cast<unsigned>(-4),
18              static_cast<scudo::uptr>(5), static_cast<unsigned>(10),
19              static_cast<scudo::uptr>(11), reinterpret_cast<void *>(0x123),
20              "_string_");
21   EXPECT_EQ(Str.length(), strlen(Str.data()));
22 
23   std::string expectedString = "a-1b-2c4294967292e5fahbq0x";
24   expectedString += std::string(SCUDO_POINTER_FORMAT_LENGTH - 3, '0');
25   expectedString += "123e_string_r";
26   EXPECT_EQ(Str.length(), strlen(Str.data()));
27   EXPECT_STREQ(expectedString.c_str(), Str.data());
28 }
29 
30 TEST(ScudoStringsTest, Precision) {
31   scudo::ScopedString Str(128);
32   Str.append("%.*s", 3, "12345");
33   EXPECT_EQ(Str.length(), strlen(Str.data()));
34   EXPECT_STREQ("123", Str.data());
35   Str.clear();
36   Str.append("%.*s", 6, "12345");
37   EXPECT_EQ(Str.length(), strlen(Str.data()));
38   EXPECT_STREQ("12345", Str.data());
39   Str.clear();
40   Str.append("%-6s", "12345");
41   EXPECT_EQ(Str.length(), strlen(Str.data()));
42   EXPECT_STREQ("12345 ", Str.data());
43 }
44 
45 static void fillString(scudo::ScopedString &Str, scudo::uptr Size) {
46   for (scudo::uptr I = 0; I < Size; I++)
47     Str.append("A");
48 }
49 
50 TEST(ScudoStringTest, PotentialOverflows) {
51   // Use a ScopedString that spans a page, and attempt to write past the end
52   // of it with variations of append. The expectation is for nothing to crash.
53   const scudo::uptr PageSize = scudo::getPageSizeCached();
54   scudo::ScopedString Str(PageSize);
55   Str.clear();
56   fillString(Str, 2 * PageSize);
57   Str.clear();
58   fillString(Str, PageSize - 64);
59   Str.append("%-128s", "12345");
60   Str.clear();
61   fillString(Str, PageSize - 16);
62   Str.append("%024x", 12345);
63   Str.clear();
64   fillString(Str, PageSize - 16);
65   Str.append("EEEEEEEEEEEEEEEEEEEEEEEE");
66 }
67 
68 template <typename T>
69 static void testAgainstLibc(const char *Format, T Arg1, T Arg2) {
70   scudo::ScopedString Str(128);
71   Str.append(Format, Arg1, Arg2);
72   char Buffer[128];
73   snprintf(Buffer, sizeof(Buffer), Format, Arg1, Arg2);
74   EXPECT_EQ(Str.length(), strlen(Str.data()));
75   EXPECT_STREQ(Buffer, Str.data());
76 }
77 
78 TEST(ScudoStringsTest, MinMax) {
79   testAgainstLibc<int>("%d-%d", INT_MIN, INT_MAX);
80   testAgainstLibc<unsigned>("%u-%u", 0, UINT_MAX);
81   testAgainstLibc<unsigned>("%x-%x", 0, UINT_MAX);
82   testAgainstLibc<long>("%zd-%zd", LONG_MIN, LONG_MAX);
83   testAgainstLibc<unsigned long>("%zu-%zu", 0, ULONG_MAX);
84   testAgainstLibc<unsigned long>("%zx-%zx", 0, ULONG_MAX);
85 }
86 
87 TEST(ScudoStringsTest, Padding) {
88   testAgainstLibc<int>("%3d - %3d", 1, 0);
89   testAgainstLibc<int>("%3d - %3d", -1, 123);
90   testAgainstLibc<int>("%3d - %3d", -1, -123);
91   testAgainstLibc<int>("%3d - %3d", 12, 1234);
92   testAgainstLibc<int>("%3d - %3d", -12, -1234);
93   testAgainstLibc<int>("%03d - %03d", 1, 0);
94   testAgainstLibc<int>("%03d - %03d", -1, 123);
95   testAgainstLibc<int>("%03d - %03d", -1, -123);
96   testAgainstLibc<int>("%03d - %03d", 12, 1234);
97   testAgainstLibc<int>("%03d - %03d", -12, -1234);
98 }
99