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