diff options
author | Nico Weber <nicolasweber@gmx.de> | 2019-08-01 14:38:49 +0000 |
---|---|---|
committer | Nico Weber <nicolasweber@gmx.de> | 2019-08-01 14:38:49 +0000 |
commit | ccaf8a02107d36bd7c852c184b4fdc0fc547eb8c (patch) | |
tree | 4521946f1322031cd3a669791359043ddf2f754b /lib/scudo/standalone/tests/wrappers_c_test.cpp | |
parent | b6f4b44f9bd9cbfd9bc80491544ab39cded26740 (diff) | |
download | compiler-rt-ccaf8a02107d36bd7c852c184b4fdc0fc547eb8c.tar.gz |
compiler-rt: Rename .cc file in lib/scudo/standalone/tests to .cpp
Like r367463, but for scudo/standalone/tests.
With this, all files in compiler-rt/lib have extension cpp.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@367569 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/scudo/standalone/tests/wrappers_c_test.cpp')
-rw-r--r-- | lib/scudo/standalone/tests/wrappers_c_test.cpp | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/lib/scudo/standalone/tests/wrappers_c_test.cpp b/lib/scudo/standalone/tests/wrappers_c_test.cpp new file mode 100644 index 000000000..4f3c9aea6 --- /dev/null +++ b/lib/scudo/standalone/tests/wrappers_c_test.cpp @@ -0,0 +1,225 @@ +//===-- wrappers_c_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 "platform.h" + +#include "gtest/gtest.h" + +#include <limits.h> +#include <malloc.h> +#include <unistd.h> + +// Note that every C allocation function in the test binary will be fulfilled +// by Scudo (this includes the gtest APIs, etc.), which is a test by itself. +// But this might also lead to unexpected side-effects, since the allocation and +// deallocation operations in the TEST functions will coexist with others (see +// the EXPECT_DEATH comment below). + +// We have to use a small quarantine to make sure that our double-free tests +// trigger. Otherwise EXPECT_DEATH ends up reallocating the chunk that was just +// freed (this depends on the size obviously) and the following free succeeds. +extern "C" __attribute__((visibility("default"))) const char * +__scudo_default_options() { + return "quarantine_size_kb=256:thread_local_quarantine_size_kb=128:" + "quarantine_max_chunk_size=512"; +} + +static const size_t Size = 100U; + +TEST(ScudoWrappersCTest, Malloc) { + void *P = malloc(Size); + EXPECT_NE(P, nullptr); + EXPECT_LE(Size, malloc_usable_size(P)); + EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % FIRST_32_SECOND_64(8U, 16U), 0U); + EXPECT_DEATH( + free(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(P) | 1U)), ""); + free(P); + EXPECT_DEATH(free(P), ""); + + P = malloc(0U); + EXPECT_NE(P, nullptr); + free(P); + + errno = 0; + EXPECT_EQ(malloc(SIZE_MAX), nullptr); + EXPECT_EQ(errno, ENOMEM); +} + +TEST(ScudoWrappersCTest, Calloc) { + void *P = calloc(1U, Size); + EXPECT_NE(P, nullptr); + EXPECT_LE(Size, malloc_usable_size(P)); + for (size_t I = 0; I < Size; I++) + EXPECT_EQ((reinterpret_cast<uint8_t *>(P))[I], 0U); + free(P); + + P = calloc(1U, 0U); + EXPECT_NE(P, nullptr); + free(P); + P = calloc(0U, 1U); + EXPECT_NE(P, nullptr); + free(P); + + errno = 0; + EXPECT_EQ(calloc(SIZE_MAX, 1U), nullptr); + EXPECT_EQ(errno, ENOMEM); + errno = 0; + EXPECT_EQ(calloc(static_cast<size_t>(LONG_MAX) + 1U, 2U), nullptr); + if (SCUDO_ANDROID) + EXPECT_EQ(errno, ENOMEM); + errno = 0; + EXPECT_EQ(calloc(SIZE_MAX, SIZE_MAX), nullptr); + EXPECT_EQ(errno, ENOMEM); +} + +TEST(ScudoWrappersCTest, Memalign) { + void *P; + for (size_t I = FIRST_32_SECOND_64(2U, 3U); I <= 18U; I++) { + const size_t Alignment = 1U << I; + + P = memalign(Alignment, Size); + EXPECT_NE(P, nullptr); + EXPECT_LE(Size, malloc_usable_size(P)); + EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % Alignment, 0U); + free(P); + + P = nullptr; + EXPECT_EQ(posix_memalign(&P, Alignment, Size), 0); + EXPECT_NE(P, nullptr); + EXPECT_LE(Size, malloc_usable_size(P)); + EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % Alignment, 0U); + free(P); + } + + EXPECT_EQ(memalign(4096U, SIZE_MAX), nullptr); + EXPECT_EQ(posix_memalign(&P, 15U, Size), EINVAL); + EXPECT_EQ(posix_memalign(&P, 4096U, SIZE_MAX), ENOMEM); + + // Android's memalign accepts non power-of-2 alignments, and 0. + if (SCUDO_ANDROID) { + for (size_t Alignment = 0U; Alignment <= 128U; Alignment++) { + P = memalign(Alignment, 1024U); + EXPECT_NE(P, nullptr); + free(P); + } + } +} + +TEST(ScudoWrappersCTest, AlignedAlloc) { + const size_t Alignment = 4096U; + void *P = aligned_alloc(Alignment, Alignment * 4U); + EXPECT_NE(P, nullptr); + EXPECT_LE(Alignment * 4U, malloc_usable_size(P)); + EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % Alignment, 0U); + free(P); + + errno = 0; + P = aligned_alloc(Alignment, Size); + EXPECT_EQ(P, nullptr); + EXPECT_EQ(errno, EINVAL); +} + +TEST(ScudoWrappersCTest, Realloc) { + // realloc(nullptr, N) is malloc(N) + void *P = realloc(nullptr, 0U); + EXPECT_NE(P, nullptr); + free(P); + + P = malloc(Size); + EXPECT_NE(P, nullptr); + // realloc(P, 0U) is free(P) and returns nullptr + EXPECT_EQ(realloc(P, 0U), nullptr); + + P = malloc(Size); + EXPECT_NE(P, nullptr); + EXPECT_LE(Size, malloc_usable_size(P)); + memset(P, 0x42, Size); + + P = realloc(P, Size * 2U); + EXPECT_NE(P, nullptr); + EXPECT_LE(Size * 2U, malloc_usable_size(P)); + for (size_t I = 0; I < Size; I++) + EXPECT_EQ(0x42, (reinterpret_cast<uint8_t *>(P))[I]); + + P = realloc(P, Size / 2U); + EXPECT_NE(P, nullptr); + EXPECT_LE(Size / 2U, malloc_usable_size(P)); + for (size_t I = 0; I < Size / 2U; I++) + EXPECT_EQ(0x42, (reinterpret_cast<uint8_t *>(P))[I]); + free(P); + + EXPECT_DEATH(P = realloc(P, Size), ""); + + errno = 0; + EXPECT_EQ(realloc(nullptr, SIZE_MAX), nullptr); + EXPECT_EQ(errno, ENOMEM); + P = malloc(Size); + EXPECT_NE(P, nullptr); + errno = 0; + EXPECT_EQ(realloc(P, SIZE_MAX), nullptr); + EXPECT_EQ(errno, ENOMEM); + free(P); + + // Android allows realloc of memalign pointers. + if (SCUDO_ANDROID) { + const size_t Alignment = 1024U; + P = memalign(Alignment, Size); + EXPECT_NE(P, nullptr); + EXPECT_LE(Size, malloc_usable_size(P)); + EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % Alignment, 0U); + memset(P, 0x42, Size); + + P = realloc(P, Size * 2U); + EXPECT_NE(P, nullptr); + EXPECT_LE(Size * 2U, malloc_usable_size(P)); + for (size_t I = 0; I < Size; I++) + EXPECT_EQ(0x42, (reinterpret_cast<uint8_t *>(P))[I]); + free(P); + } +} + +#ifndef M_DECAY_TIME +#define M_DECAY_TIME -100 +#endif + +#ifndef M_PURGE +#define M_PURGE -101 +#endif + +TEST(ScudoWrappersCTest, Mallopt) { + errno = 0; + EXPECT_EQ(mallopt(-1000, 1), 0); + // mallopt doesn't set errno. + EXPECT_EQ(errno, 0); + + EXPECT_EQ(mallopt(M_PURGE, 0), 1); + + EXPECT_EQ(mallopt(M_DECAY_TIME, 1), 1); + EXPECT_EQ(mallopt(M_DECAY_TIME, 0), 1); + EXPECT_EQ(mallopt(M_DECAY_TIME, 1), 1); + EXPECT_EQ(mallopt(M_DECAY_TIME, 0), 1); +} + +TEST(ScudoWrappersCTest, OtherAlloc) { + const size_t PageSize = sysconf(_SC_PAGESIZE); + + void *P = pvalloc(Size); + EXPECT_NE(P, nullptr); + EXPECT_EQ(reinterpret_cast<uintptr_t>(P) & (PageSize - 1), 0U); + EXPECT_LE(PageSize, malloc_usable_size(P)); + free(P); + + EXPECT_EQ(pvalloc(SIZE_MAX), nullptr); + + P = pvalloc(Size); + EXPECT_NE(P, nullptr); + EXPECT_EQ(reinterpret_cast<uintptr_t>(P) & (PageSize - 1), 0U); + free(P); + + EXPECT_EQ(valloc(SIZE_MAX), nullptr); +} |