[PATCH 2/2] malloc: use __attribute((alloc_size)) for dynamic memory allocation

Ahmad Fatoum a.fatoum at pengutronix.de
Thu Nov 9 03:38:07 PST 2023


Adorning functions allocating dynamic memory with __alloc_size allows
GCC to warn about heap overflows it notices during normal compilation.

Import the definitions from Linux and switch over barebox <malloc.h>
to make use of it.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 include/linux/compiler-gcc.h   |  8 ++++++++
 include/linux/compiler_types.h | 24 ++++++++++++++++++++++++
 include/malloc.h               |  9 +++++----
 3 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 4d36b27214fd..2534386d040f 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -234,3 +234,11 @@
 #else
 #define __diag_GCC_8(s)
 #endif
+
+/*
+ * Prior to 9.1, -Wno-alloc-size-larger-than (and therefore the "alloc_size"
+ * attribute) do not work, and must be disabled.
+ */
+#if GCC_VERSION < 90100
+#undef __alloc_size__
+#endif
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index 800bc518feea..9ef8115a396f 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -56,6 +56,16 @@ extern void __chk_io_ptr(const volatile void __iomem *);
 
 #ifdef __KERNEL__
 
+/*
+ * Note: do not use this directly. Instead, use __alloc_size() since it is conditionally
+ * available and includes other attributes. For GCC < 9.1, __alloc_size__ gets undefined
+ * in compiler-gcc.h, due to misbehaviors.
+ *
+ *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005fsize-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#alloc-size
+ */
+#define __alloc_size__(x, ...)		__attribute__((__alloc_size__(x, ## __VA_ARGS__)))
+
 /* Compiler specific macros. */
 #ifdef __clang__
 #include <linux/compiler-clang.h>
@@ -188,6 +198,20 @@ struct ftrace_likely_data {
 #define __assume_aligned(a, ...)
 #endif
 
+/*
+ * Any place that could be marked with the "alloc_size" attribute is also
+ * a place to be marked with the "malloc" attribute, except those that may
+ * be performing a _reallocation_, as that may alias the existing pointer.
+ * For these, use __realloc_size().
+ */
+#ifdef __alloc_size__
+# define __alloc_size(x, ...)	__alloc_size__(x, ## __VA_ARGS__) __malloc
+# define __realloc_size(x, ...)	__alloc_size__(x, ## __VA_ARGS__)
+#else
+# define __alloc_size(x, ...)	__malloc
+# define __realloc_size(x, ...)
+#endif
+
 /* Are two types/vars the same type (ignoring qualifiers)? */
 #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
 
diff --git a/include/malloc.h b/include/malloc.h
index 971fc4058bc6..d63853b91e91 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -2,13 +2,14 @@
 #ifndef __MALLOC_H
 #define __MALLOC_H
 
+#include <linux/compiler.h>
 #include <types.h>
 
-void *malloc(size_t);
+void *malloc(size_t) __alloc_size(1);
 void free(void *);
-void *realloc(void *, size_t);
-void *memalign(size_t, size_t);
-void *calloc(size_t, size_t);
+void *realloc(void *, size_t) __realloc_size(2);
+void *memalign(size_t, size_t) __alloc_size(2);
+void *calloc(size_t, size_t) __alloc_size(1, 2);
 void malloc_stats(void);
 void *sbrk(ptrdiff_t increment);
 
-- 
2.39.2




More information about the barebox mailing list