From bbae86d3d2997a853ca0365e8eb7a3ca7489ee09 Mon Sep 17 00:00:00 2001 From: Sebastien Bacher Date: Fri, 25 Jan 2019 11:24:41 +0100 Subject: New upstream version 1.15.2 --- shared/systemd/src/basic/alloc-util.h | 147 ++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 shared/systemd/src/basic/alloc-util.h (limited to 'shared/systemd/src/basic/alloc-util.h') diff --git a/shared/systemd/src/basic/alloc-util.h b/shared/systemd/src/basic/alloc-util.h new file mode 100644 index 00000000..ff7a4679 --- /dev/null +++ b/shared/systemd/src/basic/alloc-util.h @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "macro.h" + +typedef void (*free_func_t)(void *p); + +#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n))) + +#define new0(t, n) ((t*) calloc((n) ?: 1, sizeof(t))) + +#define newa(t, n) \ + ({ \ + assert(!size_multiply_overflow(sizeof(t), n)); \ + (t*) alloca(sizeof(t)*(n)); \ + }) + +#define newa0(t, n) \ + ({ \ + assert(!size_multiply_overflow(sizeof(t), n)); \ + (t*) alloca0(sizeof(t)*(n)); \ + }) + +#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n))) + +#define newdup_suffix0(t, p, n) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) + +#define malloc0(n) (calloc(1, (n))) + +static inline void *mfree(void *memory) { + free(memory); + return NULL; +} + +#define free_and_replace(a, b) \ + ({ \ + free(a); \ + (a) = (b); \ + (b) = NULL; \ + 0; \ + }) + +void* memdup(const void *p, size_t l) _alloc_(2); +void* memdup_suffix0(const void *p, size_t l) _alloc_(2); + +#define memdupa(p, l) \ + ({ \ + void *_q_; \ + _q_ = alloca(l); \ + memcpy(_q_, p, l); \ + }) + +#define memdupa_suffix0(p, l) \ + ({ \ + void *_q_; \ + _q_ = alloca(l + 1); \ + ((uint8_t*) _q_)[l] = 0; \ + memcpy(_q_, p, l); \ + }) + +static inline void freep(void *p) { + free(*(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 size, size_t need) { + if (size_multiply_overflow(size, need)) + return NULL; + + return malloc(size * need ?: 1); +} + +#if !HAVE_REALLOCARRAY +_alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) { + if (size_multiply_overflow(size, need)) + return NULL; + + return realloc(p, size * need ?: 1); +} +#endif + +_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) { + if (size_multiply_overflow(size, need)) + return NULL; + + return memdup(p, size * need); +} + +_alloc_(2, 3) static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) { + if (size_multiply_overflow(size, need)) + return NULL; + + return memdup_suffix0(p, size * need); +} + +void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size); +void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); + +#define GREEDY_REALLOC(array, allocated, need) \ + greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0])) + +#define GREEDY_REALLOC0(array, allocated, need) \ + greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0])) + +#define alloca0(n) \ + ({ \ + char *_new_; \ + size_t _len_ = n; \ + _new_ = alloca(_len_); \ + (void *) 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; \ + _ptr_ = alloca((size) + _mask_); \ + (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ + }) + +#define alloca0_align(size, align) \ + ({ \ + void *_new_; \ + size_t _size_ = (size); \ + _new_ = alloca_align(_size_, (align)); \ + (void*)memset(_new_, 0, _size_); \ + }) + +/* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to + * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */ +#define TAKE_PTR(ptr) \ + ({ \ + typeof(ptr) _ptr_ = (ptr); \ + (ptr) = NULL; \ + _ptr_; \ + }) -- cgit 1.3.0-6-gf8a5