alloc-util: add new helpers memdup_suffix0() and newdup_suffix0()

These are similar to memdup() and newdup(), but reserve one extra NUL
byte at the end of the new allocation and initialize it. It's useful
when copying out data from fixed size character arrays where NUL
termination can't be assumed.
This commit is contained in:
Lennart Poettering 2017-07-20 14:14:55 +02:00
parent 7bf7ce28b5
commit c165d97d16
3 changed files with 34 additions and 10 deletions

View File

@ -25,16 +25,31 @@
#include "util.h"
void* memdup(const void *p, size_t l) {
void *r;
void *ret;
assert(p);
assert(l == 0 || p);
r = malloc(l);
if (!r)
ret = malloc(l);
if (!ret)
return NULL;
memcpy(r, p, l);
return r;
memcpy(ret, p, l);
return ret;
}
void* memdup_suffix0(const void*p, size_t l) {
void *ret;
assert(l == 0 || p);
/* The same as memdup() but place a safety NUL byte after the allocated memory */
ret = malloc(l + 1);
if (!ret)
return NULL;
*((uint8_t*) mempcpy(ret, p, l)) = 0;
return ret;
}
void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {

View File

@ -36,6 +36,8 @@
#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
#define newdup_suffix0(t, p, n) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n)))
#define malloc0(n) (calloc(1, (n)))
static inline void *mfree(void *memory) {
@ -52,6 +54,7 @@ static inline void *mfree(void *memory) {
})
void* memdup(const void *p, size_t l) _alloc_(2);
void* memdup_suffix0(const void*p, size_t l) _alloc_(2);
static inline void freep(void *p) {
free(*(void**) p);
@ -84,6 +87,13 @@ _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, si
return memdup(p, size * need);
}
_alloc_(2, 3) static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) {
if (size_multiply_overflow(size, need))
return NULL;
return memdup_suffix0(p, size * need);
}
void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);

View File

@ -95,13 +95,12 @@ static int parse_field(const void *data, size_t length, const char *field, char
return 0;
nl = length - fl;
buf = new(char, nl+1);
buf = newdup_suffix0(char, (const char*) data + fl, nl);
if (!buf)
return log_oom();
memcpy(buf, (const char*) data + fl, nl);
buf[nl] = 0;
free(*target);
*target = buf;