]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/alloc-util.h
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
11 #if HAS_FEATURE_MEMORY_SANITIZER
12 # include <sanitizer/msan_interface.h>
15 typedef void (*free_func_t
)(void *p
);
16 typedef void* (*mfree_func_t
)(void *p
);
18 /* If for some reason more than 4M are allocated on the stack, let's abort immediately. It's better than
19 * proceeding and smashing the stack limits. Note that by default RLIMIT_STACK is 8M on Linux. */
20 #define ALLOCA_MAX (4U*1024U*1024U)
22 #define new(t, n) ((t*) malloc_multiply(sizeof(t), (n)))
24 #define new0(t, n) ((t*) calloc((n) ?: 1, sizeof(t)))
26 #define alloca_safe(n) \
29 assert(_nn_ <= ALLOCA_MAX); \
30 alloca(_nn_ == 0 ? 1 : _nn_); \
36 assert(!size_multiply_overflow(sizeof(t), _n_)); \
37 (t*) alloca_safe(sizeof(t)*_n_); \
43 assert(!size_multiply_overflow(sizeof(t), _n_)); \
44 (t*) alloca0((sizeof(t)*_n_)); \
47 #define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
49 #define newdup_suffix0(t, p, n) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n)))
51 #define malloc0(n) (calloc(1, (n) ?: 1))
53 #define free_and_replace_full(a, b, free_func) \
55 typeof(a)* _a = &(a); \
56 typeof(b)* _b = &(b); \
63 #define free_and_replace(a, b) \
64 free_and_replace_full(a, b, free)
66 void* memdup(const void *p
, size_t l
) _alloc_(2);
67 void* memdup_suffix0(const void *p
, size_t l
); /* We can't use _alloc_() here, since we return a buffer one byte larger than the specified size */
69 #define memdupa(p, l) \
73 _q_ = alloca_safe(_l_); \
74 memcpy_safe(_q_, p, _l_); \
77 #define memdupa_suffix0(p, l) \
81 _q_ = alloca_safe(_l_ + 1); \
82 ((uint8_t*) _q_)[_l_] = 0; \
83 memcpy_safe(_q_, p, _l_); \
86 static inline void unsetp(void *p
) {
87 /* A trivial "destructor" that can be used in cases where we want to
88 * unset a pointer from a _cleanup_ function. */
93 static inline void freep(void *p
) {
94 *(void**)p
= mfree(*(void**) p
);
97 #define _cleanup_free_ _cleanup_(freep)
99 static inline bool size_multiply_overflow(size_t size
, size_t need
) {
100 return _unlikely_(need
!= 0 && size
> (SIZE_MAX
/ need
));
103 _malloc_
_alloc_(1, 2) static inline void *malloc_multiply(size_t size
, size_t need
) {
104 if (size_multiply_overflow(size
, need
))
107 return malloc(size
* need
?: 1);
110 #if !HAVE_REALLOCARRAY
111 _alloc_(2, 3) static inline void *reallocarray(void *p
, size_t need
, size_t size
) {
112 if (size_multiply_overflow(size
, need
))
115 return realloc(p
, size
* need
?: 1);
119 _alloc_(2, 3) static inline void *memdup_multiply(const void *p
, size_t size
, size_t need
) {
120 if (size_multiply_overflow(size
, need
))
123 return memdup(p
, size
* need
);
126 /* Note that we can't decorate this function with _alloc_() since the returned memory area is one byte larger
127 * than the product of its parameters. */
128 static inline void *memdup_suffix0_multiply(const void *p
, size_t size
, size_t need
) {
129 if (size_multiply_overflow(size
, need
))
132 return memdup_suffix0(p
, size
* need
);
135 void* greedy_realloc(void **p
, size_t need
, size_t size
);
136 void* greedy_realloc0(void **p
, size_t need
, size_t size
);
138 #define GREEDY_REALLOC(array, need) \
139 greedy_realloc((void**) &(array), (need), sizeof((array)[0]))
141 #define GREEDY_REALLOC0(array, need) \
142 greedy_realloc0((void**) &(array), (need), sizeof((array)[0]))
148 _new_ = alloca_safe(_len_); \
149 memset(_new_, 0, _len_); \
152 /* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */
153 #define alloca_align(size, align) \
156 size_t _mask_ = (align) - 1; \
157 size_t _size_ = size; \
158 _ptr_ = alloca_safe(_size_ + _mask_); \
159 (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
162 #define alloca0_align(size, align) \
165 size_t _xsize_ = (size); \
166 _new_ = alloca_align(_xsize_, (align)); \
167 memset(_new_, 0, _xsize_); \
170 #if HAS_FEATURE_MEMORY_SANITIZER
171 # define msan_unpoison(r, s) __msan_unpoison(r, s)
173 # define msan_unpoison(r, s)
176 /* This returns the number of usable bytes in a malloc()ed region as per malloc_usable_size(), in a way that
177 * is compatible with _FORTIFY_SOURCES. If _FORTIFY_SOURCES is used many memory operations will take the
178 * object size as returned by __builtin_object_size() into account. Hence, let's return the smaller size of
179 * malloc_usable_size() and __builtin_object_size() here, so that we definitely operate in safe territory by
180 * both the compiler's and libc's standards. Note that __builtin_object_size() evaluates to SIZE_MAX if the
181 * size cannot be determined, hence the MIN() expression should be safe with dynamically sized memory,
182 * too. Moreover, when NULL is passed malloc_usable_size() is documented to return zero, and
183 * __builtin_object_size() returns SIZE_MAX too, hence we also return a sensible value of 0 in this corner
185 #define MALLOC_SIZEOF_SAFE(x) \
186 MIN(malloc_usable_size(x), __builtin_object_size(x, 0))
188 /* Inspired by ELEMENTSOF() but operates on malloc()'ed memory areas: typesafely returns the number of items
189 * that fit into the specified memory block */
190 #define MALLOC_ELEMENTSOF(x) \
191 (__builtin_choose_expr( \
192 __builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
193 MALLOC_SIZEOF_SAFE(x)/sizeof((x)[0]), \
197 /* These are like strdupa()/strndupa(), but honour ALLOCA_MAX */
198 #define strdupa_safe(s) \
200 const char *_t = (s); \
201 (char*) memdupa_suffix0(_t, strlen(_t)); \
204 #define strndupa_safe(s, n) \
206 const char *_t = (s); \
207 (char*) memdupa_suffix0(_t, strnlen(_t, (n))); \
210 #include "memory-util.h"