]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/alloc-util.c
man/run0: remove @ syntax for --machine=
[thirdparty/systemd.git] / src / basic / alloc-util.c
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
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
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
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
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
106 void* greedy_realloc_append(
107 void **p,
108 size_t *n_p,
109 const void *from,
110 size_t n_from,
111 size_t size) {
112
113 uint8_t *q;
114
115 assert(p);
116 assert(n_p);
117 assert(from || n_from == 0);
118
119 if (n_from > SIZE_MAX - *n_p)
120 return NULL;
121
122 q = greedy_realloc(p, *n_p + n_from, size);
123 if (!q)
124 return NULL;
125
126 memcpy_safe(q + *n_p * size, from, n_from * size);
127
128 *n_p += n_from;
129
130 return q;
131 }
132
133 void *expand_to_usable(void *ptr, size_t newsize _unused_) {
134 return ptr;
135 }