diff options
-rw-r--r-- | src/basic/alloc-util.h | 12 | ||||
-rw-r--r-- | src/basic/fileio.c | 4 | ||||
-rw-r--r-- | src/basic/memory-util.h | 2 |
3 files changed, 15 insertions, 3 deletions
diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h index 698a6583c5..66bee6cb87 100644 --- a/src/basic/alloc-util.h +++ b/src/basic/alloc-util.h @@ -163,3 +163,15 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); #else # define msan_unpoison(r, s) #endif + +/* This returns the number of usable bytes in a malloc()ed region as per malloc_usable_size(), in a way that + * is compatible with _FORTIFY_SOURCES. If _FORTIFY_SOURCES is used many memory operations will take the + * object size as returned by __builtin_object_size() into account. Hence, let's return the smaller size of + * malloc_usable_size() and __builtin_object_size() here, so that we definitely operate in safe territory by + * both the compiler's and libc's standards. Note that __builtin_object_size() evaluates to SIZE_MAX if the + * size cannot be determined, hence the MIN() expression should be safe with dynamically sized memory, + * too. Moreover, when NULL is passed malloc_usable_size() is documented to return zero, and + * __builtin_object_size() returns SIZE_MAX too, hence we also return a sensible value of 0 in this corner + * case. */ +#define MALLOC_SIZEOF_SAFE(x) \ + MIN(malloc_usable_size(x), __builtin_object_size(x, 0)) diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 08b46ef6f3..b2ffcd3287 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -421,7 +421,7 @@ int read_full_virtual_file(const char *filename, char **ret_contents, size_t *re if (!buf) return -ENOMEM; /* Use a bigger allocation if we got it anyway, but not more than the limit. */ - size = MIN(malloc_usable_size(buf) - 1, READ_VIRTUAL_BYTES_MAX); + size = MIN(MALLOC_SIZEOF_SAFE(buf) - 1, READ_VIRTUAL_BYTES_MAX); for (;;) { ssize_t k; @@ -560,7 +560,7 @@ int read_full_stream_full( buf = t; /* Unless a size has been explicitly specified, try to read as much as fits into the memory * we allocated (minus 1, to leave one byte for the safety NUL byte) */ - n = size == SIZE_MAX ? malloc_usable_size(buf) - 1 : n_next; + n = size == SIZE_MAX ? MALLOC_SIZEOF_SAFE(buf) - 1 : n_next; errno = 0; k = fread(buf + l, 1, n - l, f); diff --git a/src/basic/memory-util.h b/src/basic/memory-util.h index 179edd247b..e3f7980d12 100644 --- a/src/basic/memory-util.h +++ b/src/basic/memory-util.h @@ -88,7 +88,7 @@ static inline void* erase_and_free(void *p) { if (!p) return NULL; - l = malloc_usable_size(p); + l = MALLOC_SIZEOF_SAFE(p); explicit_bzero_safe(p, l); return mfree(p); } |