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/base/SkAssert.h"
9 #include "include/private/base/SkDebug.h"
10 #include "include/private/base/SkFeatures.h"
11 #include "include/private/base/SkMalloc.h"
12 
13 #include <cstdlib>
14 
15 #if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN)
16 #include <intrin.h>
17 // This is a super stable value and setting it here avoids pulling in all of windows.h.
18 #ifndef FAST_FAIL_FATAL_APP_EXIT
19 #define FAST_FAIL_FATAL_APP_EXIT              7
20 #endif
21 #endif
22 
23 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
24     #define SK_DEBUGFAILF(fmt, ...) SK_ABORT(fmt"\n", __VA_ARGS__)
25 #else
26     #define SK_DEBUGFAILF(fmt, ...) SkASSERT((SkDebugf(fmt"\n", __VA_ARGS__), false))
27 #endif
28 
sk_out_of_memory(size_t size)29 static inline void sk_out_of_memory(size_t size) {
30     SK_DEBUGFAILF("sk_out_of_memory (asked for %zu bytes)",
31                   size);
32 #if defined(SK_BUILD_FOR_AFL_FUZZ)
33     exit(1);
34 #else
35     abort();
36 #endif
37 }
38 
throw_on_failure(size_t size,void * p)39 static inline void* throw_on_failure(size_t size, void* p) {
40     if (size > 0 && p == nullptr) {
41         // If we've got a nullptr here, the only reason we should have failed is running out of RAM.
42         sk_out_of_memory(size);
43     }
44     return p;
45 }
46 
sk_abort_no_print()47 void sk_abort_no_print() {
48 #if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN)
49     __fastfail(FAST_FAIL_FATAL_APP_EXIT);
50 #elif defined(__clang__)
51     __builtin_trap();
52 #else
53     abort();
54 #endif
55 }
56 
sk_out_of_memory(void)57 void sk_out_of_memory(void) {
58     SkDEBUGFAIL("sk_out_of_memory");
59 #if defined(SK_BUILD_FOR_AFL_FUZZ)
60     exit(1);
61 #else
62     abort();
63 #endif
64 }
65 
sk_realloc_throw(void * addr,size_t size)66 void* sk_realloc_throw(void* addr, size_t size) {
67     if (size == 0) {
68         sk_free(addr);
69         return nullptr;
70     }
71     return throw_on_failure(size, realloc(addr, size));
72 }
73 
sk_free(void * p)74 void sk_free(void* p) {
75     // The guard here produces a performance improvement across many tests, and many platforms.
76     // Removing the check was tried in skia cl 588037.
77     if (p != nullptr) {
78         free(p);
79     }
80 }
81 
sk_malloc_flags(size_t size,unsigned flags)82 void* sk_malloc_flags(size_t size, unsigned flags) {
83     void* p;
84     if (flags & SK_MALLOC_ZERO_INITIALIZE) {
85         p = calloc(size, 1);
86     } else {
87 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && defined(__BIONIC__)
88         /* TODO: After b/169449588 is fixed, we will want to change this to restore
89          *       original behavior instead of always disabling the flag.
90          * TODO: After b/158870657 is fixed and scudo is used globally, we can assert when an
91          *       an error is returned.
92          */
93         // malloc() generally doesn't initialize its memory and that's a huge security hole,
94         // so Android has replaced its malloc() with one that zeros memory,
95         // but that's a huge performance hit for HWUI, so turn it back off again.
96         (void)mallopt(M_THREAD_DISABLE_MEM_INIT, 1);
97 #endif
98         p = malloc(size);
99 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && defined(__BIONIC__)
100         (void)mallopt(M_THREAD_DISABLE_MEM_INIT, 0);
101 #endif
102     }
103     if (flags & SK_MALLOC_THROW) {
104         return throw_on_failure(size, p);
105     } else {
106         return p;
107     }
108 }
109