1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <malloc.h>
4 #include <stdint.h>
5 #include <string.h>
6
7 #include "alloc-util.h"
8 #include "macro.h"
9 #include "memory-util.h"
10
memdup(const void * p,size_t l)11 void* memdup(const void *p, size_t l) {
12 void *ret;
13
14 assert(l == 0 || p);
15
16 ret = malloc(l ?: 1);
17 if (!ret)
18 return NULL;
19
20 return memcpy_safe(ret, p, l);
21 }
22
memdup_suffix0(const void * p,size_t l)23 void* memdup_suffix0(const void *p, size_t l) {
24 void *ret;
25
26 assert(l == 0 || p);
27
28 /* The same as memdup() but place a safety NUL byte after the allocated memory */
29
30 if (_unlikely_(l == SIZE_MAX)) /* prevent overflow */
31 return NULL;
32
33 ret = malloc(l + 1);
34 if (!ret)
35 return NULL;
36
37 ((uint8_t*) ret)[l] = 0;
38 return memcpy_safe(ret, p, l);
39 }
40
greedy_realloc(void ** p,size_t need,size_t size)41 void* greedy_realloc(
42 void **p,
43 size_t need,
44 size_t size) {
45
46 size_t a, newalloc;
47 void *q;
48
49 assert(p);
50
51 /* We use malloc_usable_size() for determining the current allocated size. On all systems we care
52 * about this should be safe to rely on. Should there ever arise the need to avoid relying on this we
53 * can instead locally fall back to realloc() on every call, rounded up to the next exponent of 2 or
54 * so. */
55
56 if (*p && (size == 0 || (MALLOC_SIZEOF_SAFE(*p) / size >= need)))
57 return *p;
58
59 if (_unlikely_(need > SIZE_MAX/2)) /* Overflow check */
60 return NULL;
61 newalloc = need * 2;
62
63 if (size_multiply_overflow(newalloc, size))
64 return NULL;
65 a = newalloc * size;
66
67 if (a < 64) /* Allocate at least 64 bytes */
68 a = 64;
69
70 q = realloc(*p, a);
71 if (!q)
72 return NULL;
73
74 return *p = q;
75 }
76
greedy_realloc0(void ** p,size_t need,size_t size)77 void* greedy_realloc0(
78 void **p,
79 size_t need,
80 size_t size) {
81
82 size_t before, after;
83 uint8_t *q;
84
85 assert(p);
86
87 before = MALLOC_SIZEOF_SAFE(*p); /* malloc_usable_size() will return 0 on NULL input, as per docs */
88
89 q = greedy_realloc(p, need, size);
90 if (!q)
91 return NULL;
92
93 after = MALLOC_SIZEOF_SAFE(q);
94
95 if (size == 0) /* avoid division by zero */
96 before = 0;
97 else
98 before = (before / size) * size; /* Round down */
99
100 if (after > before)
101 memzero(q + before, after - before);
102
103 return q;
104 }
105