Files
clang-p2996/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp
Christopher Ferris c0a3c5c81f [scudo] Change tests that use setrlimit to cause mmap to fail. (#87004)
It appears that qemu does not actually cause mmap to fail when calling
setrlimit to limit the address space size. In the two tests that use
setrlimit, detect if mmap still works and skip the tests in that case.

Since all Android targets should support setrlimit, compile out the mmap
check code for them.
2024-03-29 14:19:10 -07:00

169 lines
5.2 KiB
C++

//===-- strings_test.cpp ----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "tests/scudo_unit_test.h"
#include "string_utils.h"
#include <limits.h>
TEST(ScudoStringsTest, Constructor) {
scudo::ScopedString Str;
EXPECT_EQ(0ul, Str.length());
EXPECT_EQ('\0', *Str.data());
}
TEST(ScudoStringsTest, Basic) {
scudo::ScopedString Str;
Str.append("a%db%zdc%ue%zuf%xh%zxq%pe%sr", static_cast<int>(-1),
static_cast<scudo::uptr>(-2), static_cast<unsigned>(-4),
static_cast<scudo::uptr>(5), static_cast<unsigned>(10),
static_cast<scudo::uptr>(11), reinterpret_cast<void *>(0x123),
"_string_");
EXPECT_EQ(Str.length(), strlen(Str.data()));
std::string expectedString = "a-1b-2c4294967292e5fahbq0x";
expectedString += std::string(SCUDO_POINTER_FORMAT_LENGTH - 3, '0');
expectedString += "123e_string_r";
EXPECT_EQ(Str.length(), strlen(Str.data()));
EXPECT_STREQ(expectedString.c_str(), Str.data());
}
TEST(ScudoStringsTest, Clear) {
scudo::ScopedString Str;
Str.append("123");
Str.clear();
EXPECT_EQ(0ul, Str.length());
EXPECT_EQ('\0', *Str.data());
}
TEST(ScudoStringsTest, ClearLarge) {
constexpr char appendString[] = "123";
scudo::ScopedString Str;
Str.reserve(sizeof(appendString) * 10000);
for (int i = 0; i < 10000; ++i)
Str.append(appendString);
Str.clear();
EXPECT_EQ(0ul, Str.length());
EXPECT_EQ('\0', *Str.data());
}
TEST(ScudoStringsTest, Precision) {
scudo::ScopedString Str;
Str.append("%.*s", 3, "12345");
EXPECT_EQ(Str.length(), strlen(Str.data()));
EXPECT_STREQ("123", Str.data());
Str.clear();
Str.append("%.*s", 6, "12345");
EXPECT_EQ(Str.length(), strlen(Str.data()));
EXPECT_STREQ("12345", Str.data());
Str.clear();
Str.append("%-6s", "12345");
EXPECT_EQ(Str.length(), strlen(Str.data()));
EXPECT_STREQ("12345 ", Str.data());
Str.clear();
Str.append("%-8s", "12345");
EXPECT_EQ(Str.length(), strlen(Str.data()));
EXPECT_STREQ("12345 ", Str.data());
}
static void fillString(scudo::ScopedString &Str, scudo::uptr Size) {
for (scudo::uptr I = 0; I < Size; I++)
Str.append("A");
}
TEST(ScudoStringTest, PotentialOverflows) {
// Use a ScopedString that spans a page, and attempt to write past the end
// of it with variations of append. The expectation is for nothing to crash.
const scudo::uptr PageSize = scudo::getPageSizeCached();
scudo::ScopedString Str;
Str.reserve(2 * PageSize);
Str.clear();
fillString(Str, 2 * PageSize);
Str.clear();
fillString(Str, PageSize - 64);
Str.append("%-128s", "12345");
Str.clear();
fillString(Str, PageSize - 16);
Str.append("%024x", 12345);
Str.clear();
fillString(Str, PageSize - 16);
Str.append("EEEEEEEEEEEEEEEEEEEEEEEE");
}
template <typename T>
static void testAgainstLibc(const char *Format, T Arg1, T Arg2) {
scudo::ScopedString Str;
Str.append(Format, Arg1, Arg2);
char Buffer[128];
snprintf(Buffer, sizeof(Buffer), Format, Arg1, Arg2);
EXPECT_EQ(Str.length(), strlen(Str.data()));
EXPECT_STREQ(Buffer, Str.data());
}
TEST(ScudoStringsTest, MinMax) {
testAgainstLibc<int>("%d-%d", INT_MIN, INT_MAX);
testAgainstLibc<unsigned>("%u-%u", 0, UINT_MAX);
testAgainstLibc<unsigned>("%x-%x", 0, UINT_MAX);
testAgainstLibc<long>("%zd-%zd", LONG_MIN, LONG_MAX);
testAgainstLibc<unsigned long>("%zu-%zu", 0, ULONG_MAX);
testAgainstLibc<unsigned long>("%zx-%zx", 0, ULONG_MAX);
}
TEST(ScudoStringsTest, Padding) {
testAgainstLibc<int>("%3d - %3d", 1, 0);
testAgainstLibc<int>("%3d - %3d", -1, 123);
testAgainstLibc<int>("%3d - %3d", -1, -123);
testAgainstLibc<int>("%3d - %3d", 12, 1234);
testAgainstLibc<int>("%3d - %3d", -12, -1234);
testAgainstLibc<int>("%03d - %03d", 1, 0);
testAgainstLibc<int>("%03d - %03d", -1, 123);
testAgainstLibc<int>("%03d - %03d", -1, -123);
testAgainstLibc<int>("%03d - %03d", 12, 1234);
testAgainstLibc<int>("%03d - %03d", -12, -1234);
}
#if defined(__linux__)
#include <sys/resource.h>
TEST(ScudoStringsTest, CapacityIncreaseFails) {
scudo::ScopedString Str;
rlimit Limit = {};
EXPECT_EQ(0, getrlimit(RLIMIT_AS, &Limit));
rlimit EmptyLimit = {.rlim_cur = 0, .rlim_max = Limit.rlim_max};
EXPECT_EQ(0, setrlimit(RLIMIT_AS, &EmptyLimit));
// qemu does not honor the setrlimit, so verify before proceeding.
scudo::MemMapT MemMap;
if (MemMap.map(/*Addr=*/0U, scudo::getPageSizeCached(), "scudo:test",
MAP_ALLOWNOMEM)) {
MemMap.unmap(MemMap.getBase(), MemMap.getCapacity());
setrlimit(RLIMIT_AS, &Limit);
GTEST_SKIP() << "Limiting address space does not prevent mmap.";
}
// Test requires that the default length is at least 6 characters.
scudo::uptr MaxSize = Str.capacity();
EXPECT_LE(6u, MaxSize);
for (size_t i = 0; i < MaxSize - 5; i++) {
Str.append("B");
}
// Attempt to append past the end of the current capacity.
Str.append("%d", 12345678);
EXPECT_EQ(MaxSize, Str.capacity());
EXPECT_STREQ("B12345", &Str.data()[MaxSize - 6]);
EXPECT_EQ(0, setrlimit(RLIMIT_AS, &Limit));
}
#endif