#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))
if (!buf)
return -ENOMEM;
/* Use a bigger allocation if we got it anyway, but not more than the limit. */
- size = MIN3(malloc_usable_size(buf) - 1, max_size, READ_FULL_BYTES_MAX);
+ size = MIN3(MALLOC_SIZEOF_SAFE(buf) - 1, max_size, READ_FULL_BYTES_MAX);
for (;;) {
ssize_t k;
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);
if (!p)
return NULL;
- l = malloc_usable_size(p);
+ l = MALLOC_SIZEOF_SAFE(p);
explicit_bzero_safe(p, l);
return mfree(p);
}
/* Let's try to use the allocated buffer, if there's room at the end still. Otherwise let's extend by 64 chars. */
if (*x) {
m = strlen(*x);
- a = malloc_usable_size(*x);
+ a = MALLOC_SIZEOF_SAFE(*x);
assert(a >= m + 1);
} else
m = a = 0;
return -ENOMEM;
*x = n;
- a = malloc_usable_size(*x);
+ a = MALLOC_SIZEOF_SAFE(*x);
}
/* Now, let's try to format the string into it */