/src/systemd/src/basic/alloc-util.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: LGPL-2.1+ */ |
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 | 130k | void* memdup(const void *p, size_t l) { |
12 | 130k | void *ret; |
13 | 130k | |
14 | 130k | assert(l == 0 || p); |
15 | 130k | |
16 | 130k | ret = malloc(l ?: 1); |
17 | 130k | if (!ret) |
18 | 0 | return NULL; |
19 | 130k | |
20 | 130k | memcpy(ret, p, l); |
21 | 130k | return ret; |
22 | 130k | } |
23 | | |
24 | 441k | void* memdup_suffix0(const void *p, size_t l) { |
25 | 441k | void *ret; |
26 | 441k | |
27 | 441k | assert(l == 0 || p); |
28 | 441k | |
29 | 441k | /* The same as memdup() but place a safety NUL byte after the allocated memory */ |
30 | 441k | |
31 | 441k | if (_unlikely_(l == SIZE_MAX)) /* prevent overflow */ |
32 | 441k | return NULL; |
33 | 441k | |
34 | 441k | ret = malloc(l + 1); |
35 | 441k | if (!ret) |
36 | 0 | return NULL; |
37 | 441k | |
38 | 441k | *((uint8_t*) mempcpy(ret, p, l)) = 0; |
39 | 441k | return ret; |
40 | 441k | } |
41 | | |
42 | 562M | void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) { |
43 | 562M | size_t a, newalloc; |
44 | 562M | void *q; |
45 | 562M | |
46 | 562M | assert(p); |
47 | 562M | assert(allocated); |
48 | 562M | |
49 | 562M | if (*allocated >= need) |
50 | 528M | return *p; |
51 | 34.0M | |
52 | 34.0M | if (_unlikely_(need > SIZE_MAX/2)) /* Overflow check */ |
53 | 34.0M | return NULL; |
54 | 34.0M | |
55 | 34.0M | newalloc = need * 2; |
56 | 34.0M | if (size_multiply_overflow(newalloc, size)) |
57 | 0 | return NULL; |
58 | 34.0M | |
59 | 34.0M | a = newalloc * size; |
60 | 34.0M | if (a < 64) /* Allocate at least 64 bytes */ |
61 | 31.8M | a = 64; |
62 | 34.0M | |
63 | 34.0M | q = realloc(*p, a); |
64 | 34.0M | if (!q) |
65 | 0 | return NULL; |
66 | 34.0M | |
67 | 34.0M | if (size > 0) { |
68 | 34.0M | size_t bn; |
69 | 34.0M | |
70 | 34.0M | /* Adjust for the 64 byte minimum */ |
71 | 34.0M | newalloc = a / size; |
72 | 34.0M | |
73 | 34.0M | bn = malloc_usable_size(q) / size; |
74 | 34.0M | if (bn > newalloc) { |
75 | 31.8M | void *qq; |
76 | 31.8M | |
77 | 31.8M | /* The actual size allocated is larger than what we asked for. Let's call realloc() again to |
78 | 31.8M | * take possession of the extra space. This should be cheap, since libc doesn't have to move |
79 | 31.8M | * the memory for this. */ |
80 | 31.8M | |
81 | 31.8M | qq = realloc(q, bn * size); |
82 | 31.8M | if (_likely_(qq)) { |
83 | 31.8M | *p = qq; |
84 | 31.8M | *allocated = bn; |
85 | 31.8M | return qq; |
86 | 31.8M | } |
87 | 2.10M | } |
88 | 34.0M | } |
89 | 2.10M | |
90 | 2.10M | *p = q; |
91 | 2.10M | *allocated = newalloc; |
92 | 2.10M | return q; |
93 | 2.10M | } |
94 | | |
95 | 9.62k | void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) { |
96 | 9.62k | size_t prev; |
97 | 9.62k | uint8_t *q; |
98 | 9.62k | |
99 | 9.62k | assert(p); |
100 | 9.62k | assert(allocated); |
101 | 9.62k | |
102 | 9.62k | prev = *allocated; |
103 | 9.62k | |
104 | 9.62k | q = greedy_realloc(p, allocated, need, size); |
105 | 9.62k | if (!q) |
106 | 0 | return NULL; |
107 | 9.62k | |
108 | 9.62k | if (*allocated > prev) |
109 | 9.62k | memzero(q + prev * size, (*allocated - prev) * size); |
110 | 9.62k | |
111 | 9.62k | return q; |
112 | 9.62k | } |