1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2017 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkMalloc_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define SkMalloc_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker
11*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
12*c8dee2aaSAndroid Build Coastguard Worker
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAPI.h"
14*c8dee2aaSAndroid Build Coastguard Worker
15*c8dee2aaSAndroid Build Coastguard Worker /*
16*c8dee2aaSAndroid Build Coastguard Worker memory wrappers to be implemented by the porting layer (platform)
17*c8dee2aaSAndroid Build Coastguard Worker */
18*c8dee2aaSAndroid Build Coastguard Worker
19*c8dee2aaSAndroid Build Coastguard Worker
20*c8dee2aaSAndroid Build Coastguard Worker /** Free memory returned by sk_malloc(). It is safe to pass null. */
21*c8dee2aaSAndroid Build Coastguard Worker SK_API extern void sk_free(void*);
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker /**
24*c8dee2aaSAndroid Build Coastguard Worker * Called internally if we run out of memory. The platform implementation must
25*c8dee2aaSAndroid Build Coastguard Worker * not return, but should either throw an exception or otherwise exit.
26*c8dee2aaSAndroid Build Coastguard Worker */
27*c8dee2aaSAndroid Build Coastguard Worker SK_API extern void sk_out_of_memory(void);
28*c8dee2aaSAndroid Build Coastguard Worker
29*c8dee2aaSAndroid Build Coastguard Worker enum {
30*c8dee2aaSAndroid Build Coastguard Worker /**
31*c8dee2aaSAndroid Build Coastguard Worker * If this bit is set, the returned buffer must be zero-initialized. If this bit is not set
32*c8dee2aaSAndroid Build Coastguard Worker * the buffer can be uninitialized.
33*c8dee2aaSAndroid Build Coastguard Worker */
34*c8dee2aaSAndroid Build Coastguard Worker SK_MALLOC_ZERO_INITIALIZE = 1 << 0,
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard Worker /**
37*c8dee2aaSAndroid Build Coastguard Worker * If this bit is set, the implementation must throw/crash/quit if the request cannot
38*c8dee2aaSAndroid Build Coastguard Worker * be fulfilled. If this bit is not set, then it should return nullptr on failure.
39*c8dee2aaSAndroid Build Coastguard Worker */
40*c8dee2aaSAndroid Build Coastguard Worker SK_MALLOC_THROW = 1 << 1,
41*c8dee2aaSAndroid Build Coastguard Worker };
42*c8dee2aaSAndroid Build Coastguard Worker /**
43*c8dee2aaSAndroid Build Coastguard Worker * Return a block of memory (at least 4-byte aligned) of at least the specified size.
44*c8dee2aaSAndroid Build Coastguard Worker * If the requested memory cannot be returned, either return nullptr or throw/exit, depending
45*c8dee2aaSAndroid Build Coastguard Worker * on the SK_MALLOC_THROW bit. If the allocation succeeds, the memory will be zero-initialized
46*c8dee2aaSAndroid Build Coastguard Worker * if the SK_MALLOC_ZERO_INITIALIZE bit was set.
47*c8dee2aaSAndroid Build Coastguard Worker *
48*c8dee2aaSAndroid Build Coastguard Worker * To free the memory, call sk_free()
49*c8dee2aaSAndroid Build Coastguard Worker */
50*c8dee2aaSAndroid Build Coastguard Worker SK_API extern void* sk_malloc_flags(size_t size, unsigned flags);
51*c8dee2aaSAndroid Build Coastguard Worker
52*c8dee2aaSAndroid Build Coastguard Worker /** Same as standard realloc(), but this one never returns null on failure. It will throw
53*c8dee2aaSAndroid Build Coastguard Worker * if it fails.
54*c8dee2aaSAndroid Build Coastguard Worker * If size is 0, it will call sk_free on buffer and return null. (This behavior is implementation-
55*c8dee2aaSAndroid Build Coastguard Worker * defined for normal realloc. We follow what glibc does.)
56*c8dee2aaSAndroid Build Coastguard Worker */
57*c8dee2aaSAndroid Build Coastguard Worker SK_API extern void* sk_realloc_throw(void* buffer, size_t size);
58*c8dee2aaSAndroid Build Coastguard Worker
59*c8dee2aaSAndroid Build Coastguard Worker /**
60*c8dee2aaSAndroid Build Coastguard Worker * Return the size of the block of memory allocated in reality for a given pointer. The pointer
61*c8dee2aaSAndroid Build Coastguard Worker * passed must have been allocated using the sk_malloc_* or sk_realloc_* functions. The "size"
62*c8dee2aaSAndroid Build Coastguard Worker * parameter indicates the size originally requested when the memory block was allocated, and
63*c8dee2aaSAndroid Build Coastguard Worker * the value returned by this function must be bigger or equal to it.
64*c8dee2aaSAndroid Build Coastguard Worker */
65*c8dee2aaSAndroid Build Coastguard Worker SK_API extern size_t sk_malloc_size(void* addr, size_t size);
66*c8dee2aaSAndroid Build Coastguard Worker
sk_malloc_throw(size_t size)67*c8dee2aaSAndroid Build Coastguard Worker static inline void* sk_malloc_throw(size_t size) {
68*c8dee2aaSAndroid Build Coastguard Worker return sk_malloc_flags(size, SK_MALLOC_THROW);
69*c8dee2aaSAndroid Build Coastguard Worker }
70*c8dee2aaSAndroid Build Coastguard Worker
sk_calloc_throw(size_t size)71*c8dee2aaSAndroid Build Coastguard Worker static inline void* sk_calloc_throw(size_t size) {
72*c8dee2aaSAndroid Build Coastguard Worker return sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_ZERO_INITIALIZE);
73*c8dee2aaSAndroid Build Coastguard Worker }
74*c8dee2aaSAndroid Build Coastguard Worker
sk_calloc_canfail(size_t size)75*c8dee2aaSAndroid Build Coastguard Worker static inline void* sk_calloc_canfail(size_t size) {
76*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_FUZZER)
77*c8dee2aaSAndroid Build Coastguard Worker // To reduce the chance of OOM, pretend we can't allocate more than 200kb.
78*c8dee2aaSAndroid Build Coastguard Worker if (size > 200000) {
79*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
80*c8dee2aaSAndroid Build Coastguard Worker }
81*c8dee2aaSAndroid Build Coastguard Worker #endif
82*c8dee2aaSAndroid Build Coastguard Worker return sk_malloc_flags(size, SK_MALLOC_ZERO_INITIALIZE);
83*c8dee2aaSAndroid Build Coastguard Worker }
84*c8dee2aaSAndroid Build Coastguard Worker
85*c8dee2aaSAndroid Build Coastguard Worker // Performs a safe multiply count * elemSize, checking for overflow
86*c8dee2aaSAndroid Build Coastguard Worker SK_API extern void* sk_calloc_throw(size_t count, size_t elemSize);
87*c8dee2aaSAndroid Build Coastguard Worker SK_API extern void* sk_malloc_throw(size_t count, size_t elemSize);
88*c8dee2aaSAndroid Build Coastguard Worker SK_API extern void* sk_realloc_throw(void* buffer, size_t count, size_t elemSize);
89*c8dee2aaSAndroid Build Coastguard Worker
90*c8dee2aaSAndroid Build Coastguard Worker /**
91*c8dee2aaSAndroid Build Coastguard Worker * These variants return nullptr on failure
92*c8dee2aaSAndroid Build Coastguard Worker */
sk_malloc_canfail(size_t size)93*c8dee2aaSAndroid Build Coastguard Worker static inline void* sk_malloc_canfail(size_t size) {
94*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_FUZZER)
95*c8dee2aaSAndroid Build Coastguard Worker // To reduce the chance of OOM, pretend we can't allocate more than 200kb.
96*c8dee2aaSAndroid Build Coastguard Worker if (size > 200000) {
97*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
98*c8dee2aaSAndroid Build Coastguard Worker }
99*c8dee2aaSAndroid Build Coastguard Worker #endif
100*c8dee2aaSAndroid Build Coastguard Worker return sk_malloc_flags(size, 0);
101*c8dee2aaSAndroid Build Coastguard Worker }
102*c8dee2aaSAndroid Build Coastguard Worker SK_API extern void* sk_malloc_canfail(size_t count, size_t elemSize);
103*c8dee2aaSAndroid Build Coastguard Worker
104*c8dee2aaSAndroid Build Coastguard Worker // bzero is safer than memset, but we can't rely on it, so... sk_bzero()
sk_bzero(void * buffer,size_t size)105*c8dee2aaSAndroid Build Coastguard Worker static inline void sk_bzero(void* buffer, size_t size) {
106*c8dee2aaSAndroid Build Coastguard Worker // Please c.f. sk_careful_memcpy. It's undefined behavior to call memset(null, 0, 0).
107*c8dee2aaSAndroid Build Coastguard Worker if (size) {
108*c8dee2aaSAndroid Build Coastguard Worker memset(buffer, 0, size);
109*c8dee2aaSAndroid Build Coastguard Worker }
110*c8dee2aaSAndroid Build Coastguard Worker }
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker /**
113*c8dee2aaSAndroid Build Coastguard Worker * sk_careful_memcpy() is just like memcpy(), but guards against undefined behavior.
114*c8dee2aaSAndroid Build Coastguard Worker *
115*c8dee2aaSAndroid Build Coastguard Worker * It is undefined behavior to call memcpy() with null dst or src, even if len is 0.
116*c8dee2aaSAndroid Build Coastguard Worker * If an optimizer is "smart" enough, it can exploit this to do unexpected things.
117*c8dee2aaSAndroid Build Coastguard Worker * memcpy(dst, src, 0);
118*c8dee2aaSAndroid Build Coastguard Worker * if (src) {
119*c8dee2aaSAndroid Build Coastguard Worker * printf("%x\n", *src);
120*c8dee2aaSAndroid Build Coastguard Worker * }
121*c8dee2aaSAndroid Build Coastguard Worker * In this code the compiler can assume src is not null and omit the if (src) {...} check,
122*c8dee2aaSAndroid Build Coastguard Worker * unconditionally running the printf, crashing the program if src really is null.
123*c8dee2aaSAndroid Build Coastguard Worker * Of the compilers we pay attention to only GCC performs this optimization in practice.
124*c8dee2aaSAndroid Build Coastguard Worker */
sk_careful_memcpy(void * dst,const void * src,size_t len)125*c8dee2aaSAndroid Build Coastguard Worker static inline void* sk_careful_memcpy(void* dst, const void* src, size_t len) {
126*c8dee2aaSAndroid Build Coastguard Worker // When we pass >0 len we had better already be passing valid pointers.
127*c8dee2aaSAndroid Build Coastguard Worker // So we just need to skip calling memcpy when len == 0.
128*c8dee2aaSAndroid Build Coastguard Worker if (len) {
129*c8dee2aaSAndroid Build Coastguard Worker memcpy(dst,src,len);
130*c8dee2aaSAndroid Build Coastguard Worker }
131*c8dee2aaSAndroid Build Coastguard Worker return dst;
132*c8dee2aaSAndroid Build Coastguard Worker }
133*c8dee2aaSAndroid Build Coastguard Worker
sk_careful_memmove(void * dst,const void * src,size_t len)134*c8dee2aaSAndroid Build Coastguard Worker static inline void* sk_careful_memmove(void* dst, const void* src, size_t len) {
135*c8dee2aaSAndroid Build Coastguard Worker // When we pass >0 len we had better already be passing valid pointers.
136*c8dee2aaSAndroid Build Coastguard Worker // So we just need to skip calling memcpy when len == 0.
137*c8dee2aaSAndroid Build Coastguard Worker if (len) {
138*c8dee2aaSAndroid Build Coastguard Worker memmove(dst,src,len);
139*c8dee2aaSAndroid Build Coastguard Worker }
140*c8dee2aaSAndroid Build Coastguard Worker return dst;
141*c8dee2aaSAndroid Build Coastguard Worker }
142*c8dee2aaSAndroid Build Coastguard Worker
sk_careful_memcmp(const void * a,const void * b,size_t len)143*c8dee2aaSAndroid Build Coastguard Worker static inline int sk_careful_memcmp(const void* a, const void* b, size_t len) {
144*c8dee2aaSAndroid Build Coastguard Worker // When we pass >0 len we had better already be passing valid pointers.
145*c8dee2aaSAndroid Build Coastguard Worker // So we just need to skip calling memcmp when len == 0.
146*c8dee2aaSAndroid Build Coastguard Worker if (len == 0) {
147*c8dee2aaSAndroid Build Coastguard Worker return 0; // we treat zero-length buffers as "equal"
148*c8dee2aaSAndroid Build Coastguard Worker }
149*c8dee2aaSAndroid Build Coastguard Worker return memcmp(a, b, len);
150*c8dee2aaSAndroid Build Coastguard Worker }
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard Worker #endif // SkMalloc_DEFINED
153