1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdlib.h>
#include "forward.h"
#include "memory-util.h"
#if HAS_FEATURE_MEMORY_SANITIZER
# include <sanitizer/msan_interface.h>
#endif
/* If for some reason more than 4M are allocated on the stack, let's abort immediately. It's better than
* proceeding and smashing the stack limits. Note that by default RLIMIT_STACK is 8M on Linux. */
#define ALLOCA_MAX (4U*1024U*1024U)
#define new(t, n) ((t*) malloc_multiply(n, sizeof(t)))
#define new0(t, n) ((t*) calloc((n) ?: 1, sizeof(t)))
#define alloca_safe(n) \
({ \
size_t _nn_ = (n); \
assert(_nn_ <= ALLOCA_MAX); \
alloca(_nn_ == 0 ? 1 : _nn_); \
}) \
#define newa(t, n) \
({ \
size_t _n_ = (n); \
assert_se(MUL_ASSIGN_SAFE(&_n_, sizeof(t))); \
(t*) alloca_safe(_n_); \
})
#define newa0(t, n) \
({ \
size_t _n_ = (n); \
assert_se(MUL_ASSIGN_SAFE(&_n_, sizeof(t))); \
(t*) alloca0(_n_); \
})
#define newdup(t, p, n) ((t*) memdup_multiply(p, n, sizeof(t)))
#define newdup_suffix0(t, p, n) ((t*) memdup_suffix0_multiply(p, n, sizeof(t)))
#define malloc0(n) (calloc(1, (n) ?: 1))
#define free_and_replace(a, b) \
free_and_replace_full(a, b, free)
void* memdup(const void *p, size_t l) _alloc_(2);
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 */
#define memdupa(p, l) \
({ \
void *_q_; \
size_t _l_ = l; \
_q_ = alloca_safe(_l_); \
memcpy_safe(_q_, p, _l_); \
})
#define memdupa_suffix0(p, l) \
({ \
void *_q_; \
size_t _l_ = l; \
_q_ = alloca_safe(_l_ + 1); \
((uint8_t*) _q_)[_l_] = 0; \
memcpy_safe(_q_, p, _l_); \
})
static inline void unsetp(void *p) {
/* A trivial "destructor" that can be used in cases where we want to
* unset a pointer from a _cleanup_ function. */
*(void**)p = NULL;
}
static inline void freep(void *p) {
*(void**)p = mfree(*(void**) p);
}
#define _cleanup_free_ _cleanup_(freep)
static inline bool size_multiply_overflow(size_t size, size_t need) {
return _unlikely_(need != 0 && size > (SIZE_MAX / need));
}
_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t need, size_t size) {
if (size_multiply_overflow(size, need))
return NULL;
return malloc(size * need ?: 1);
}
_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t need, size_t size) {
if (size_multiply_overflow(size, need))
return NULL;
return memdup(p, size * need);
}
/* Note that we can't decorate this function with _alloc_() since the returned memory area is one byte larger
* than the product of its parameters. */
static inline void *memdup_suffix0_multiply(const void *p, size_t need, size_t size) {
if (size_multiply_overflow(size, need))
return NULL;
return memdup_suffix0(p, size * need);
}
static inline size_t GREEDY_ALLOC_ROUND_UP(size_t l) {
size_t m;
/* Round up allocation sizes a bit to some reasonable, likely larger value. This is supposed to be
* used for cases which are likely called in an allocation loop of some form, i.e. that repetitively
* grow stuff, for example strv_extend() and suchlike.
*
* Note the difference to GREEDY_REALLOC() here, as this helper operates on a single size value only,
* and rounds up to next multiple of 2, needing no further counter.
*
* Note the benefits of direct ALIGN_POWER2() usage: type-safety for size_t, sane handling for very
* small (i.e. <= 2) and safe handling for very large (i.e. > SSIZE_MAX) values. */
if (l <= 2)
return 2; /* Never allocate less than 2 of something. */
m = ALIGN_POWER2(l);
if (m == 0) /* overflow? */
return l;
return m;
}
void* greedy_realloc(void **p, size_t need, size_t size);
void* greedy_realloc0(void **p, size_t need, size_t size);
void* greedy_realloc_append(void **p, size_t *n_p, const void *from, size_t n_from, size_t size);
#define GREEDY_REALLOC(array, need) \
greedy_realloc((void**) &(array), (need), sizeof((array)[0]))
#define GREEDY_REALLOC0(array, need) \
greedy_realloc0((void**) &(array), (need), sizeof((array)[0]))
#define GREEDY_REALLOC_APPEND(array, n_array, from, n_from) \
({ \
const typeof(*(array)) *_from_ = (from); \
greedy_realloc_append((void**) &(array), &(n_array), _from_, (n_from), sizeof((array)[0])); \
})
#define alloca0(n) \
({ \
char *_new_; \
size_t _len_ = n; \
_new_ = alloca_safe(_len_); \
memset(_new_, 0, _len_); \
})
/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */
#define alloca_align(size, align) \
({ \
void *_ptr_; \
size_t _mask_ = (align) - 1; \
size_t _size_ = size; \
_ptr_ = alloca_safe(_size_ + _mask_); \
(void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
})
#define alloca0_align(size, align) \
({ \
void *_new_; \
size_t _xsize_ = (size); \
_new_ = alloca_align(_xsize_, (align)); \
memset(_new_, 0, _xsize_); \
})
#if HAS_FEATURE_MEMORY_SANITIZER
# define msan_unpoison(r, s) __msan_unpoison(r, s)
#else
# define msan_unpoison(r, s)
#endif
/* Dummy allocator to tell the compiler that the new size of p is newsize. The implementation returns the
* pointer as is; the only reason for its existence is as a conduit for the _alloc_ attribute. This must not
* be inlined (hence a non-static function with _noinline_ because LTO otherwise tries to inline it) because
* gcc then loses the attributes on the function.
* See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96503 */
void *expand_to_usable(void *p, size_t newsize) _alloc_(2) _returns_nonnull_ _noinline_;
size_t malloc_sizeof_safe(void **xp);
/* This returns the number of usable bytes in a malloc()ed region as per malloc_usable_size(), which may
* return a value larger than the size that was actually allocated. Access to that additional memory is
* discouraged because it violates the C standard; a compiler cannot see that this as valid. To help the
* compiler out, the MALLOC_SIZEOF_SAFE macro 'allocates' the usable size using a dummy allocator function
* expand_to_usable. There is a possibility of malloc_usable_size() returning different values during the
* lifetime of an object, which may cause problems, but the glibc allocator does not do that at the moment. */
#define MALLOC_SIZEOF_SAFE(x) \
malloc_sizeof_safe((void**) &__builtin_choose_expr(__builtin_constant_p(x), (void*) { NULL }, (x)))
/* Inspired by ELEMENTSOF() but operates on malloc()'ed memory areas: typesafely returns the number of items
* that fit into the specified memory block */
#define MALLOC_ELEMENTSOF(x) \
(__builtin_choose_expr( \
__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
MALLOC_SIZEOF_SAFE(x)/sizeof((x)[0]), \
VOID_0))
/* Free every element of the array. */
static inline void free_many(void **p, size_t n) {
assert(p || n == 0);
FOREACH_ARRAY(i, p, n)
*i = mfree(*i);
}
/* Typesafe wrapper for char** rather than void**. Unfortunately C won't implicitly cast this. */
static inline void free_many_charp(char **c, size_t n) {
free_many((void**) c, n);
}
_alloc_(2) static inline void *realloc0(void *p, size_t new_size) {
size_t old_size;
void *q;
/* Like realloc(), but initializes anything appended to zero */
old_size = MALLOC_SIZEOF_SAFE(p);
q = realloc(p, new_size);
if (!q)
return NULL;
new_size = MALLOC_SIZEOF_SAFE(q); /* Update with actually allocated space */
if (new_size > old_size)
memset((uint8_t*) q + old_size, 0, new_size - old_size);
return q;
}
|