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