#include "base/memory/advanced_memory_safety_checks.h"
#include "partition_alloc/buildflags.h"
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
#include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h"
#endif
namespace base::internal {
namespace {
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
constexpr bool ShouldUsePartitionAlloc(MemorySafetyCheck checks) {
return static_cast<bool>(checks &
(MemorySafetyCheck::kForcePartitionAlloc |
MemorySafetyCheck::kSchedulerLoopQuarantine));
}
constexpr partition_alloc::AllocFlags GetAllocFlags(MemorySafetyCheck checks) {
return partition_alloc::AllocFlags::kReturnNull |
partition_alloc::AllocFlags::kNoHooks;
}
constexpr partition_alloc::FreeFlags GetFreeFlags(MemorySafetyCheck checks) {
auto flags = partition_alloc::FreeFlags::kNone;
if (static_cast<bool>(checks & MemorySafetyCheck::kSchedulerLoopQuarantine)) {
flags |= partition_alloc::FreeFlags::
kSchedulerLoopQuarantineForAdvancedMemorySafetyChecks;
}
return flags;
}
#endif
}
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
ALWAYS_INLINE partition_alloc::PartitionRoot*
GetPartitionRootForMemorySafetyCheckedAllocation() {
return allocator_shim::internal::PartitionAllocMalloc::Allocator();
}
#endif
template <MemorySafetyCheck checks>
NOINLINE void* HandleMemorySafetyCheckedOperatorNew(std::size_t count) {
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
if constexpr (ShouldUsePartitionAlloc(checks)) {
return GetPartitionRootForMemorySafetyCheckedAllocation()
->AllocInline<GetAllocFlags(checks)>(count);
}
#endif
return ::operator new(count);
}
template <MemorySafetyCheck checks>
NOINLINE void* HandleMemorySafetyCheckedOperatorNew(
std::size_t count,
std::align_val_t alignment) {
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
if constexpr (ShouldUsePartitionAlloc(checks)) {
return GetPartitionRootForMemorySafetyCheckedAllocation()
->AlignedAlloc<GetAllocFlags(checks)>(static_cast<size_t>(alignment),
count);
}
#endif
return ::operator new(count, alignment);
}
template <MemorySafetyCheck checks>
NOINLINE void HandleMemorySafetyCheckedOperatorDelete(void* ptr) {
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
if constexpr (ShouldUsePartitionAlloc(checks)) {
GetPartitionRootForMemorySafetyCheckedAllocation()
->Free<GetFreeFlags(checks)>(ptr);
return;
}
#endif
::operator delete(ptr);
}
template <MemorySafetyCheck checks>
NOINLINE void HandleMemorySafetyCheckedOperatorDelete(
void* ptr,
std::align_val_t alignment) {
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
if constexpr (ShouldUsePartitionAlloc(checks)) {
GetPartitionRootForMemorySafetyCheckedAllocation()
->Free<GetFreeFlags(checks)>(ptr);
return;
}
#endif
::operator delete(ptr, alignment);
}
FOR_EACH_BASE_INTERNAL_MEMORY_SAFETY_CHECK_VALUE(
DEFINE_BASE_INTERNAL_HANDLE_MEMORY_SAFETY_CHECKED_OPERATORS)
}