#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "components/gwp_asan/client/sampling_malloc_shims.h"
#include <stdlib.h>
#include <cstdlib>
#include <memory>
#include <string>
#include "base/functional/callback_helpers.h"
#include "base/memory/page_size.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/gtest_util.h"
#include "base/test/multiprocess_test.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "components/crash/core/common/crash_key.h"
#include "components/gwp_asan/client/guarded_page_allocator.h"
#include "components/gwp_asan/client/gwp_asan.h"
#include "components/gwp_asan/common/crash_key_name.h"
#include "partition_alloc/buildflags.h"
#include "partition_alloc/shim/allocator_shim.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
#if BUILDFLAG(IS_WIN)
#include <malloc.h>
static size_t GetUsableSize(void* mem) {
return _msize(mem);
}
#elif BUILDFLAG(IS_APPLE)
#include <malloc/malloc.h>
static size_t GetUsableSize(void* mem) {
return malloc_size(mem);
}
#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include <malloc.h>
static size_t GetUsableSize(void* mem) { … }
#endif
namespace gwp_asan {
namespace internal {
extern GuardedPageAllocator& GetMallocGpaForTesting();
namespace {
constexpr size_t kSamplingFrequency = …;
constexpr size_t kLoopIterations = …;
constexpr int kSuccess = …;
constexpr int kFailure = …;
class SamplingMallocShimsTest : public base::MultiProcessTest { … };
bool allocationCheck(std::function<void*(void)> allocate,
std::function<void(void*)> free,
int* failures) { … }
MULTIPROCESS_TEST_MAIN_WITH_SETUP(
BasicFunctionality,
SamplingMallocShimsTest::multiprocessTestSetup) { … }
#if BUILDFLAG(IS_APPLE)
#define MAYBE_BasicFunctionality …
#else
#define MAYBE_BasicFunctionality …
#endif
TEST_F(SamplingMallocShimsTest, MAYBE_BasicFunctionality) { … }
MULTIPROCESS_TEST_MAIN_WITH_SETUP(
Realloc,
SamplingMallocShimsTest::multiprocessTestSetup) { … }
TEST_F(SamplingMallocShimsTest, Realloc) { … }
MULTIPROCESS_TEST_MAIN_WITH_SETUP(
Calloc,
SamplingMallocShimsTest::multiprocessTestSetup) { … }
TEST_F(SamplingMallocShimsTest, Calloc) { … }
#if !defined(COMPONENT_BUILD)
MULTIPROCESS_TEST_MAIN_WITH_SETUP(
CrashKey,
SamplingMallocShimsTest::multiprocessTestSetup) {
if (crash_reporter::GetCrashKeyValue(kMallocCrashKey) !=
GetMallocGpaForTesting().GetCrashKey()) {
return kFailure;
}
return kSuccess;
}
TEST_F(SamplingMallocShimsTest, CrashKey) {
runTest("CrashKey");
}
#endif
#if !BUILDFLAG(IS_ANDROID)
MULTIPROCESS_TEST_MAIN_WITH_SETUP(
GetSizeEstimate,
SamplingMallocShimsTest::multiprocessTestSetup) { … }
TEST_F(SamplingMallocShimsTest, GetSizeEstimate) { … }
#endif
#if BUILDFLAG(IS_WIN)
MULTIPROCESS_TEST_MAIN_WITH_SETUP(
AlignedRealloc,
SamplingMallocShimsTest::multiprocessTestSetup) {
constexpr size_t kAllocationSize = 123;
constexpr size_t kAllocationAlignment = 64;
for (size_t i = 0; i < kLoopIterations; i++) {
void* ptr = _aligned_malloc(kAllocationSize, kAllocationAlignment);
CHECK(ptr);
ptr = _aligned_realloc(ptr, kAllocationSize * 2, kAllocationAlignment);
CHECK(ptr);
_aligned_free(ptr);
}
return kSuccess;
}
TEST_F(SamplingMallocShimsTest, AlignedRealloc) {
runTest("AlignedRealloc");
}
#endif
#if BUILDFLAG(IS_APPLE) && !PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
MULTIPROCESS_TEST_MAIN_WITH_SETUP(
BatchFree,
SamplingMallocShimsTest::multiprocessTestSetup) {
void* ptrs[AllocatorState::kMaxMetadata + 1];
for (size_t i = 0; i < AllocatorState::kMaxMetadata; i++) {
ptrs[i] = GetMallocGpaForTesting().Allocate(16);
CHECK(ptrs[i]);
}
CHECK_EQ(GetMallocGpaForTesting().Allocate(16), nullptr);
ptrs[AllocatorState::kMaxMetadata] =
malloc_zone_malloc(malloc_default_zone(), 16);
CHECK(ptrs[AllocatorState::kMaxMetadata]);
malloc_zone_batch_free(malloc_default_zone(), ptrs,
AllocatorState::kMaxMetadata + 1);
CHECK(GetMallocGpaForTesting().Allocate(16));
return kSuccess;
}
TEST_F(SamplingMallocShimsTest, BatchFree) {
runTest("BatchFree");
}
#endif
}
}
}