#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_libc_calls
#endif
#include <stddef.h>
#include <stdlib.h>
#include <algorithm>
#include <tuple>
#include "base/debug/alias.h"
#include "base/process/memory.h"
#include "build/build_config.h"
#include "third_party/skia/include/core/SkTypes.h"
#include "third_party/skia/include/private/base/SkMalloc.h"
#if BUILDFLAG(IS_WIN)
#include <malloc.h>
#include <windows.h>
#elif BUILDFLAG(IS_APPLE)
#include <malloc/malloc.h>
#else
#include <malloc.h>
#endif
static inline void* throw_on_failure(size_t size, void* p) {
if (size > 0 && p == NULL) {
sk_out_of_memory();
}
return p;
}
void sk_abort_no_print() {
static int static_variable_to_make_this_function_unique = 0x736b;
base::debug::Alias(&static_variable_to_make_this_function_unique);
abort();
}
void sk_out_of_memory(void) {
SkDEBUGFAIL("sk_out_of_memory");
base::TerminateBecauseOutOfMemory(0);
abort();
}
void* sk_realloc_throw(void* addr, size_t size) {
if (size == 0) {
sk_free(addr);
return nullptr;
}
#if defined(UNDEFINED_SANITIZER)
size_t old_size = sk_malloc_size(addr, 0);
void* result = sk_malloc_throw(size);
sk_careful_memcpy(result, addr, std::min(size, old_size));
sk_free(addr);
return result;
#else
return throw_on_failure(size, realloc(addr, size));
#endif
}
void sk_free(void* p) {
if (p) {
#if BUILDFLAG(IS_IOS)
free(p);
#else
base::UncheckedFree(p);
#endif
}
}
static void* prevent_overcommit(int fill, size_t size, void* p) {
SkDEBUGCODE(memset(p, fill, size));
return p;
}
static void* malloc_nothrow(size_t size, int debug_sentinel) {
void* result;
#if BUILDFLAG(IS_IOS)
result = malloc(size);
#else
std::ignore = base::UncheckedMalloc(size, &result);
#endif
if (result) {
prevent_overcommit(debug_sentinel, size, result);
}
return result;
}
static void* malloc_throw(size_t size, int debug_sentinel) {
return throw_on_failure(size, malloc_nothrow(size, debug_sentinel));
}
static void* calloc_nothrow(size_t size) {
void* result;
#if BUILDFLAG(IS_IOS)
result = calloc(1, size);
#else
std::ignore = base::UncheckedCalloc(size, 1, &result);
#endif
if (result) {
prevent_overcommit(0, size, result);
}
return result;
}
static void* calloc_throw(size_t size) {
return throw_on_failure(size, calloc_nothrow(size));
}
void* sk_malloc_flags(size_t size, unsigned flags) {
if (flags & SK_MALLOC_ZERO_INITIALIZE) {
if (flags & SK_MALLOC_THROW) {
return calloc_throw(size);
} else {
return calloc_nothrow(size);
}
} else {
if (flags & SK_MALLOC_THROW) {
return malloc_throw(size, 0x42);
} else {
return malloc_nothrow(size, 0x47);
}
}
}
size_t sk_malloc_size(void* addr, size_t size) {
if (!addr) {
return 0;
}
size_t completeSize = 0;
#if BUILDFLAG(IS_WIN)
completeSize = _msize(addr);
#elif BUILDFLAG(IS_APPLE)
completeSize = malloc_size(addr);
#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
completeSize = malloc_usable_size(addr);
#endif
return std::max(completeSize, size);
}