1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/private/SkMalloc.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include <cstdlib> 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN) 13cb93a386Sopenharmony_ci#include <intrin.h> 14cb93a386Sopenharmony_ci// This is a super stable value and setting it here avoids pulling in all of windows.h. 15cb93a386Sopenharmony_ci#ifndef FAST_FAIL_FATAL_APP_EXIT 16cb93a386Sopenharmony_ci#define FAST_FAIL_FATAL_APP_EXIT 7 17cb93a386Sopenharmony_ci#endif 18cb93a386Sopenharmony_ci#endif 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ci#define SK_DEBUGFAILF(fmt, ...) \ 21cb93a386Sopenharmony_ci SkASSERT((SkDebugf(fmt"\n", __VA_ARGS__), false)) 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_cistatic inline void sk_out_of_memory(size_t size) { 24cb93a386Sopenharmony_ci SK_DEBUGFAILF("sk_out_of_memory (asked for %zu bytes)", 25cb93a386Sopenharmony_ci size); 26cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_AFL_FUZZ) 27cb93a386Sopenharmony_ci exit(1); 28cb93a386Sopenharmony_ci#else 29cb93a386Sopenharmony_ci abort(); 30cb93a386Sopenharmony_ci#endif 31cb93a386Sopenharmony_ci} 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_cistatic inline void* throw_on_failure(size_t size, void* p) { 34cb93a386Sopenharmony_ci if (size > 0 && p == nullptr) { 35cb93a386Sopenharmony_ci // If we've got a nullptr here, the only reason we should have failed is running out of RAM. 36cb93a386Sopenharmony_ci sk_out_of_memory(size); 37cb93a386Sopenharmony_ci } 38cb93a386Sopenharmony_ci return p; 39cb93a386Sopenharmony_ci} 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_civoid sk_abort_no_print() { 42cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_WIN) && defined(SK_IS_BOT) 43cb93a386Sopenharmony_ci // do not display a system dialog before aborting the process 44cb93a386Sopenharmony_ci _set_abort_behavior(0, _WRITE_ABORT_MSG); 45cb93a386Sopenharmony_ci#endif 46cb93a386Sopenharmony_ci#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN) 47cb93a386Sopenharmony_ci __fastfail(FAST_FAIL_FATAL_APP_EXIT); 48cb93a386Sopenharmony_ci#elif defined(__clang__) 49cb93a386Sopenharmony_ci __builtin_trap(); 50cb93a386Sopenharmony_ci#else 51cb93a386Sopenharmony_ci abort(); 52cb93a386Sopenharmony_ci#endif 53cb93a386Sopenharmony_ci} 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_civoid sk_out_of_memory(void) { 56cb93a386Sopenharmony_ci SkDEBUGFAIL("sk_out_of_memory"); 57cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_AFL_FUZZ) 58cb93a386Sopenharmony_ci exit(1); 59cb93a386Sopenharmony_ci#else 60cb93a386Sopenharmony_ci abort(); 61cb93a386Sopenharmony_ci#endif 62cb93a386Sopenharmony_ci} 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_civoid* sk_realloc_throw(void* addr, size_t size) { 65cb93a386Sopenharmony_ci return throw_on_failure(size, realloc(addr, size)); 66cb93a386Sopenharmony_ci} 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_civoid sk_free(void* p) { 69cb93a386Sopenharmony_ci if (p) { 70cb93a386Sopenharmony_ci free(p); 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci} 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_civoid* sk_malloc_flags(size_t size, unsigned flags) { 75cb93a386Sopenharmony_ci void* p; 76cb93a386Sopenharmony_ci if (flags & SK_MALLOC_ZERO_INITIALIZE) { 77cb93a386Sopenharmony_ci p = calloc(size, 1); 78cb93a386Sopenharmony_ci } else { 79cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && defined(__BIONIC__) 80cb93a386Sopenharmony_ci /* TODO: After b/169449588 is fixed, we will want to change this to restore 81cb93a386Sopenharmony_ci * original behavior instead of always disabling the flag. 82cb93a386Sopenharmony_ci * TODO: After b/158870657 is fixed and scudo is used globally, we can assert when an 83cb93a386Sopenharmony_ci * an error is returned. 84cb93a386Sopenharmony_ci */ 85cb93a386Sopenharmony_ci // malloc() generally doesn't initialize its memory and that's a huge security hole, 86cb93a386Sopenharmony_ci // so Android has replaced its malloc() with one that zeros memory, 87cb93a386Sopenharmony_ci // but that's a huge performance hit for HWUI, so turn it back off again. 88cb93a386Sopenharmony_ci (void)mallopt(M_THREAD_DISABLE_MEM_INIT, 1); 89cb93a386Sopenharmony_ci#endif 90cb93a386Sopenharmony_ci p = malloc(size); 91cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && defined(__BIONIC__) 92cb93a386Sopenharmony_ci (void)mallopt(M_THREAD_DISABLE_MEM_INIT, 0); 93cb93a386Sopenharmony_ci#endif 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci if (flags & SK_MALLOC_THROW) { 96cb93a386Sopenharmony_ci return throw_on_failure(size, p); 97cb93a386Sopenharmony_ci } else { 98cb93a386Sopenharmony_ci return p; 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci} 101