[v2] eal/rte_malloc: add alloc_size() attribute to allocation functions

Message ID 20201015005524.24659-1-stephen@networkplumber.org (mailing list archive)
State Accepted, archived
Delegated to: Thomas Monjalon
Headers
Series [v2] eal/rte_malloc: add alloc_size() attribute to allocation functions |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-testing success Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/Intel-compilation success Compilation OK
ci/travis-robot warning Travis build: failed
ci/iol-mellanox-Performance success Performance Testing PASS

Commit Message

Stephen Hemminger Oct. 15, 2020, 12:55 a.m. UTC
  By using the alloc_size() attribute the compiler can optimize
better and detect errors at compile time.

For example, Gcc will fail one of the invalid allocation examples
in app/test/test_malloc.c because the allocation is outside the
limits of memory.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
v2 - rebase onto correct branch (main)

 app/test/test_malloc.c              |  5 ++++-
 lib/librte_eal/include/rte_common.h | 12 ++++++++++++
 lib/librte_eal/include/rte_malloc.h | 24 ++++++++++++++++--------
 3 files changed, 32 insertions(+), 9 deletions(-)
  

Comments

Thomas Monjalon Oct. 19, 2020, 2:13 p.m. UTC | #1
15/10/2020 02:55, Stephen Hemminger:
> By using the alloc_size() attribute the compiler can optimize
> better and detect errors at compile time.
> 
> For example, Gcc will fail one of the invalid allocation examples
> in app/test/test_malloc.c because the allocation is outside the
> limits of memory.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
> v2 - rebase onto correct branch (main)
[...]
> +/**
> + * Tells compiler that the function returns a value that points to
> + * memory, where the size is given by the one or two arguments.
> + * Used by compiler to validate object size.
> + */
> +#if defined(RTE_CC_GCC) || defined(RTE_CC_CLANG)
> +#define __rte_alloc_size(...) \
> +	__attribute__((alloc_size(__VA_ARGS__)))
> +#else
> +#define __rte_alloc_size(...)
> +#endif

Not sure about the rebase: RTE_CC_GCC and RTE_CC_CLANG don't exist.
  
Thomas Monjalon Oct. 19, 2020, 2:22 p.m. UTC | #2
19/10/2020 16:13, Thomas Monjalon:
> 15/10/2020 02:55, Stephen Hemminger:
> > By using the alloc_size() attribute the compiler can optimize
> > better and detect errors at compile time.
> > 
> > For example, Gcc will fail one of the invalid allocation examples
> > in app/test/test_malloc.c because the allocation is outside the
> > limits of memory.
> > 
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> > ---
> > v2 - rebase onto correct branch (main)
> [...]
> > +/**
> > + * Tells compiler that the function returns a value that points to
> > + * memory, where the size is given by the one or two arguments.
> > + * Used by compiler to validate object size.
> > + */
> > +#if defined(RTE_CC_GCC) || defined(RTE_CC_CLANG)
> > +#define __rte_alloc_size(...) \
> > +	__attribute__((alloc_size(__VA_ARGS__)))
> > +#else
> > +#define __rte_alloc_size(...)
> > +#endif
> 
> Not sure about the rebase: RTE_CC_GCC and RTE_CC_CLANG don't exist.

Actually no, I forgot my 7-month old patch introducing them.

Applied, thanks
  

Patch

diff --git a/app/test/test_malloc.c b/app/test/test_malloc.c
index 71b3cfdde5cf..fdf77b4f6a14 100644
--- a/app/test/test_malloc.c
+++ b/app/test/test_malloc.c
@@ -846,6 +846,9 @@  test_malloc_bad_params(void)
 	if (bad_ptr != NULL)
 		goto err_return;
 
+#if defined(RTE_CC_GCC) || defined(RTE_CC_CLANG)
+	/* this test can not be built, will get trapped at compile time! */
+#else
 	/* rte_malloc expected to return null with size will cause overflow */
 	align = RTE_CACHE_LINE_SIZE;
 	size = (size_t)-8;
@@ -857,7 +860,7 @@  test_malloc_bad_params(void)
 	bad_ptr = rte_realloc(NULL, size, align);
 	if (bad_ptr != NULL)
 		goto err_return;
-
+#endif
 	return 0;
 
 err_return:
diff --git a/lib/librte_eal/include/rte_common.h b/lib/librte_eal/include/rte_common.h
index 2920255fc1e3..e63ef0f1de5e 100644
--- a/lib/librte_eal/include/rte_common.h
+++ b/lib/librte_eal/include/rte_common.h
@@ -134,6 +134,18 @@  typedef uint16_t unaligned_uint16_t;
 	__attribute__((format(printf, format_index, first_arg)))
 #endif
 
+/**
+ * Tells compiler that the function returns a value that points to
+ * memory, where the size is given by the one or two arguments.
+ * Used by compiler to validate object size.
+ */
+#if defined(RTE_CC_GCC) || defined(RTE_CC_CLANG)
+#define __rte_alloc_size(...) \
+	__attribute__((alloc_size(__VA_ARGS__)))
+#else
+#define __rte_alloc_size(...)
+#endif
+
 #define RTE_PRIORITY_LOG 101
 #define RTE_PRIORITY_BUS 110
 #define RTE_PRIORITY_CLASS 120
diff --git a/lib/librte_eal/include/rte_malloc.h b/lib/librte_eal/include/rte_malloc.h
index 42ca05182f8e..3af64f87618e 100644
--- a/lib/librte_eal/include/rte_malloc.h
+++ b/lib/librte_eal/include/rte_malloc.h
@@ -54,7 +54,8 @@  struct rte_malloc_socket_stats {
  *   - Otherwise, the pointer to the allocated object.
  */
 void *
-rte_malloc(const char *type, size_t size, unsigned align);
+rte_malloc(const char *type, size_t size, unsigned align)
+	__rte_alloc_size(2);
 
 /**
  * Allocate zero'ed memory from the heap.
@@ -80,7 +81,8 @@  rte_malloc(const char *type, size_t size, unsigned align);
  *   - Otherwise, the pointer to the allocated object.
  */
 void *
-rte_zmalloc(const char *type, size_t size, unsigned align);
+rte_zmalloc(const char *type, size_t size, unsigned align)
+	__rte_alloc_size(2);
 
 /**
  * Replacement function for calloc(), using huge-page memory. Memory area is
@@ -106,7 +108,8 @@  rte_zmalloc(const char *type, size_t size, unsigned align);
  *   - Otherwise, the pointer to the allocated object.
  */
 void *
-rte_calloc(const char *type, size_t num, size_t size, unsigned align);
+rte_calloc(const char *type, size_t num, size_t size, unsigned align)
+	__rte_alloc_size(2, 3);
 
 /**
  * Replacement function for realloc(), using huge-page memory. Reserved area
@@ -129,7 +132,8 @@  rte_calloc(const char *type, size_t num, size_t size, unsigned align);
  *   - Otherwise, the pointer to the reallocated memory.
  */
 void *
-rte_realloc(void *ptr, size_t size, unsigned int align);
+rte_realloc(void *ptr, size_t size, unsigned int align)
+	__rte_alloc_size(2);
 
 /**
  * Replacement function for realloc(), using huge-page memory. Reserved area
@@ -155,7 +159,8 @@  rte_realloc(void *ptr, size_t size, unsigned int align);
  */
 __rte_experimental
 void *
-rte_realloc_socket(void *ptr, size_t size, unsigned int align, int socket);
+rte_realloc_socket(void *ptr, size_t size, unsigned int align, int socket)
+	__rte_alloc_size(2, 3);
 
 /**
  * This function allocates memory from the huge-page area of memory. The memory
@@ -181,7 +186,8 @@  rte_realloc_socket(void *ptr, size_t size, unsigned int align, int socket);
  *   - Otherwise, the pointer to the allocated object.
  */
 void *
-rte_malloc_socket(const char *type, size_t size, unsigned align, int socket);
+rte_malloc_socket(const char *type, size_t size, unsigned align, int socket)
+	__rte_alloc_size(2);
 
 /**
  * Allocate zero'ed memory from the heap.
@@ -209,7 +215,8 @@  rte_malloc_socket(const char *type, size_t size, unsigned align, int socket);
  *   - Otherwise, the pointer to the allocated object.
  */
 void *
-rte_zmalloc_socket(const char *type, size_t size, unsigned align, int socket);
+rte_zmalloc_socket(const char *type, size_t size, unsigned align, int socket)
+	__rte_alloc_size(2);
 
 /**
  * Replacement function for calloc(), using huge-page memory. Memory area is
@@ -237,7 +244,8 @@  rte_zmalloc_socket(const char *type, size_t size, unsigned align, int socket);
  *   - Otherwise, the pointer to the allocated object.
  */
 void *
-rte_calloc_socket(const char *type, size_t num, size_t size, unsigned align, int socket);
+rte_calloc_socket(const char *type, size_t num, size_t size, unsigned align, int socket)
+	__rte_alloc_size(2, 3);
 
 /**
  * Frees the memory space pointed to by the provided pointer.