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