Branch data 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 : 3196 : void* memdup(const void *p, size_t l) { 12 : : void *ret; 13 : : 14 [ + - - + ]: 3196 : assert(l == 0 || p); 15 : : 16 [ + - ]: 3196 : ret = malloc(l ?: 1); 17 [ - + ]: 3196 : if (!ret) 18 : 0 : return NULL; 19 : : 20 : 3196 : memcpy(ret, p, l); 21 : 3196 : return ret; 22 : : } 23 : : 24 : 15624 : void* memdup_suffix0(const void *p, size_t l) { 25 : : void *ret; 26 : : 27 [ + + - + ]: 15624 : assert(l == 0 || p); 28 : : 29 : : /* The same as memdup() but place a safety NUL byte after the allocated memory */ 30 : : 31 [ - + ]: 15624 : if (_unlikely_(l == SIZE_MAX)) /* prevent overflow */ 32 : 0 : return NULL; 33 : : 34 : 15624 : ret = malloc(l + 1); 35 [ - + ]: 15624 : if (!ret) 36 : 0 : return NULL; 37 : : 38 : 15624 : *((uint8_t*) mempcpy(ret, p, l)) = 0; 39 : 15624 : return ret; 40 : : } 41 : : 42 : 42695858 : void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) { 43 : : size_t a, newalloc; 44 : : void *q; 45 : : 46 [ - + ]: 42695858 : assert(p); 47 [ - + ]: 42695858 : assert(allocated); 48 : : 49 [ + + ]: 42695858 : if (*allocated >= need) 50 : 41234974 : return *p; 51 : : 52 [ - + ]: 1460884 : if (_unlikely_(need > SIZE_MAX/2)) /* Overflow check */ 53 : 0 : return NULL; 54 : : 55 : 1460884 : newalloc = need * 2; 56 [ - + ]: 1460884 : if (size_multiply_overflow(newalloc, size)) 57 : 0 : return NULL; 58 : : 59 : 1460884 : a = newalloc * size; 60 [ + + ]: 1460884 : if (a < 64) /* Allocate at least 64 bytes */ 61 : 1361464 : a = 64; 62 : : 63 : 1460884 : q = realloc(*p, a); 64 [ - + ]: 1460884 : if (!q) 65 : 0 : return NULL; 66 : : 67 [ + - ]: 1460884 : if (size > 0) { 68 : : size_t bn; 69 : : 70 : : /* Adjust for the 64 byte minimum */ 71 : 1460884 : newalloc = a / size; 72 : : 73 : 1460884 : bn = malloc_usable_size(q) / size; 74 [ + + ]: 1460884 : 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 : 1455149 : qq = realloc(q, bn * size); 82 [ + - ]: 1455149 : if (_likely_(qq)) { 83 : 1455149 : *p = qq; 84 : 1455149 : *allocated = bn; 85 : 1455149 : return qq; 86 : : } 87 : : } 88 : : } 89 : : 90 : 5735 : *p = q; 91 : 5735 : *allocated = newalloc; 92 : 5735 : return q; 93 : : } 94 : : 95 : 3272 : void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) { 96 : : size_t prev; 97 : : uint8_t *q; 98 : : 99 [ - + ]: 3272 : assert(p); 100 [ - + ]: 3272 : assert(allocated); 101 : : 102 : 3272 : prev = *allocated; 103 : : 104 : 3272 : q = greedy_realloc(p, allocated, need, size); 105 [ - + ]: 3272 : if (!q) 106 : 0 : return NULL; 107 : : 108 [ + + ]: 3272 : if (*allocated > prev) 109 [ + - ]: 788 : memzero(q + prev * size, (*allocated - prev) * size); 110 : : 111 : 3272 : return q; 112 : : }