]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/alloc-util.c
f4bd33f4e014246a9c9e68f8f75e0023541a967d
[thirdparty/systemd.git] / src / basic / alloc-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <stdint.h>
4 #include <string.h>
5
6 #include "alloc-util.h"
7 #include "macro.h"
8 #include "memory-util.h"
9
10 void* memdup(const void *p, size_t l) {
11 void *ret;
12
13 assert(l == 0 || p);
14
15 ret = malloc(l ?: 1);
16 if (!ret)
17 return NULL;
18
19 memcpy(ret, p, l);
20 return ret;
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*) mempcpy(ret, p, l)) = 0;
38 return ret;
39 }
40
41 void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
42 size_t a, newalloc;
43 void *q;
44
45 assert(p);
46 assert(allocated);
47
48 if (*allocated >= need)
49 return *p;
50
51 if (_unlikely_(need > SIZE_MAX/2)) /* Overflow check */
52 return NULL;
53
54 newalloc = need * 2;
55 if (size_multiply_overflow(newalloc, size))
56 return NULL;
57
58 a = newalloc * size;
59 if (a < 64) /* Allocate at least 64 bytes */
60 a = 64;
61
62 q = realloc(*p, a);
63 if (!q)
64 return NULL;
65
66 *p = q;
67 *allocated = newalloc;
68 return q;
69 }
70
71 void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
72 size_t prev;
73 uint8_t *q;
74
75 assert(p);
76 assert(allocated);
77
78 prev = *allocated;
79
80 q = greedy_realloc(p, allocated, need, size);
81 if (!q)
82 return NULL;
83
84 if (*allocated > prev)
85 memzero(q + prev * size, (*allocated - prev) * size);
86
87 return q;
88 }