xref: /aosp_15_r20/external/skia/src/ports/SkMemory_malloc.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 <algorithm>
14 #include <cstdlib>
15 
16 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
17 #include <malloc/malloc.h>
18 #elif defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX)
19 #include <malloc.h>
20 #elif defined(SK_BUILD_FOR_WIN)
21 #include <malloc.h>
22 #endif
23 
24 #if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN)
25 #include <intrin.h>
26 // This is a super stable value and setting it here avoids pulling in all of windows.h.
27 #ifndef FAST_FAIL_FATAL_APP_EXIT
28 #define FAST_FAIL_FATAL_APP_EXIT              7
29 #endif
30 #endif
31 
32 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
33     #define SK_DEBUGFAILF(fmt, ...) SK_ABORT(fmt"\n", __VA_ARGS__)
34 #else
35     #define SK_DEBUGFAILF(fmt, ...) SkASSERT((SkDebugf(fmt"\n", __VA_ARGS__), false))
36 #endif
37 
sk_out_of_memory(size_t size)38 static inline void sk_out_of_memory(size_t size) {
39     SK_DEBUGFAILF("sk_out_of_memory (asked for %zu bytes)",
40                   size);
41 #if defined(SK_BUILD_FOR_AFL_FUZZ)
42     exit(1);
43 #else
44     abort();
45 #endif
46 }
47 
throw_on_failure(size_t size,void * p)48 static inline void* throw_on_failure(size_t size, void* p) {
49     if (size > 0 && p == nullptr) {
50         // If we've got a nullptr here, the only reason we should have failed is running out of RAM.
51         sk_out_of_memory(size);
52     }
53     return p;
54 }
55 
sk_abort_no_print()56 void sk_abort_no_print() {
57 #if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN)
58     __fastfail(FAST_FAIL_FATAL_APP_EXIT);
59 #elif defined(__clang__)
60     __builtin_trap();
61 #else
62     abort();
63 #endif
64 }
65 
sk_out_of_memory(void)66 void sk_out_of_memory(void) {
67     SkDEBUGFAIL("sk_out_of_memory");
68 #if defined(SK_BUILD_FOR_AFL_FUZZ)
69     exit(1);
70 #else
71     abort();
72 #endif
73 }
74 
sk_realloc_throw(void * addr,size_t size)75 void* sk_realloc_throw(void* addr, size_t size) {
76     if (size == 0) {
77         sk_free(addr);
78         return nullptr;
79     }
80     return throw_on_failure(size, realloc(addr, size));
81 }
82 
sk_free(void * p)83 void sk_free(void* p) {
84     // The guard here produces a performance improvement across many tests, and many platforms.
85     // Removing the check was tried in skia cl 588037.
86     if (p != nullptr) {
87         free(p);
88     }
89 }
90 
sk_malloc_flags(size_t size,unsigned flags)91 void* sk_malloc_flags(size_t size, unsigned flags) {
92     void* p;
93     if (flags & SK_MALLOC_ZERO_INITIALIZE) {
94         p = calloc(size, 1);
95     } else {
96 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && defined(__BIONIC__)
97         /* TODO: After b/169449588 is fixed, we will want to change this to restore
98          *       original behavior instead of always disabling the flag.
99          * TODO: After b/158870657 is fixed and scudo is used globally, we can assert when an
100          *       an error is returned.
101          */
102         // malloc() generally doesn't initialize its memory and that's a huge security hole,
103         // so Android has replaced its malloc() with one that zeros memory,
104         // but that's a huge performance hit for HWUI, so turn it back off again.
105         (void)mallopt(M_THREAD_DISABLE_MEM_INIT, 1);
106 #endif
107         p = malloc(size);
108 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && defined(__BIONIC__)
109         (void)mallopt(M_THREAD_DISABLE_MEM_INIT, 0);
110 #endif
111     }
112     if (flags & SK_MALLOC_THROW) {
113         return throw_on_failure(size, p);
114     } else {
115         return p;
116     }
117 }
118 
sk_malloc_size(void * addr,size_t size)119 size_t sk_malloc_size(void* addr, size_t size) {
120     size_t completeSize = size;
121 
122     // Use the OS specific calls to find the actual capacity.
123     #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
124         // TODO: remove the max, when the chrome implementation of malloc_size doesn't return 0.
125         completeSize = std::max(malloc_size(addr), size);
126     #elif defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 17
127         completeSize = malloc_usable_size(addr);
128         SkASSERT(completeSize >= size);
129     #elif defined(SK_BUILD_FOR_UNIX)
130         completeSize = malloc_usable_size(addr);
131         SkASSERT(completeSize >= size);
132     #elif defined(SK_BUILD_FOR_WIN)
133         completeSize = _msize(addr);
134         SkASSERT(completeSize >= size);
135     #endif
136 
137     return completeSize;
138 }
139