[PATCH] Fix calloc() behaviour in case of overflow

Gedare Bloom gedare at rtems.org
Tue Apr 20 18:37:26 UTC 2021


Looks good.

On Tue, Apr 20, 2021, 12:33 PM Sebastian Huber <
sebastian.huber at embedded-brains.de> wrote:

> The multiplication to calculate the length of the memory area to
> allocate may overflow.  Return NULL in case of an overflow.
>
> Close #4389.
> ---
>  cpukit/libcsupport/src/calloc.c       | 13 ++++++++++++-
>  cpukit/libcsupport/src/rtemscalloc.c  |  9 ++++++++-
>  testsuites/libtests/malloctest/init.c | 23 +++++++++++++----------
>  3 files changed, 33 insertions(+), 12 deletions(-)
>
> diff --git a/cpukit/libcsupport/src/calloc.c
> b/cpukit/libcsupport/src/calloc.c
> index e015f30d6c..693aa21453 100644
> --- a/cpukit/libcsupport/src/calloc.c
> +++ b/cpukit/libcsupport/src/calloc.c
> @@ -20,7 +20,10 @@
>
>  #if defined(RTEMS_NEWLIB) && !defined(HAVE_CALLOC)
>  #include <stdlib.h>
> +
> +#include <errno.h>
>  #include <string.h>
> +
>  #include <rtems/score/basedefs.h>
>
>  void *calloc(
> @@ -31,7 +34,15 @@ void *calloc(
>    void   *cptr;
>    size_t  length;
>
> -  length = nelem * elsize;
> +  if ( nelem == 0 ) {
> +    length = 0;
> +  } else if ( elsize > SIZE_MAX / nelem ) {
> +    errno = ENOMEM;
> +    return NULL;
> +  } else {
> +    length = nelem * elsize;
> +  }
> +
>    cptr = malloc( length );
>    RTEMS_OBFUSCATE_VARIABLE( cptr );
>    if ( RTEMS_PREDICT_FALSE( cptr == NULL ) ) {
> diff --git a/cpukit/libcsupport/src/rtemscalloc.c
> b/cpukit/libcsupport/src/rtemscalloc.c
> index 4e189e8367..836f1da64d 100644
> --- a/cpukit/libcsupport/src/rtemscalloc.c
> +++ b/cpukit/libcsupport/src/rtemscalloc.c
> @@ -46,7 +46,14 @@ void *rtems_calloc( size_t nelem, size_t elsize )
>    size_t  length;
>    void   *p;
>
> -  length = nelem * elsize;
> +  if ( nelem == 0 ) {
> +    length = 0;
> +  } else if ( elsize > SIZE_MAX / nelem ) {
> +    return NULL;
> +  } else {
> +    length = nelem * elsize;
> +  }
> +
>    p = rtems_malloc( length );
>    RTEMS_OBFUSCATE_VARIABLE( p );
>    if ( RTEMS_PREDICT_FALSE( p == NULL ) ) {
> diff --git a/testsuites/libtests/malloctest/init.c
> b/testsuites/libtests/malloctest/init.c
> index 1d91385683..4d0f421c02 100644
> --- a/testsuites/libtests/malloctest/init.c
> +++ b/testsuites/libtests/malloctest/init.c
> @@ -1190,6 +1190,14 @@ static void test_rtems_calloc(void)
>    rtems_test_assert(p == NULL);
>    rtems_test_assert(errno == 0);
>
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Walloc-size-larger-than=N"
> +  errno = 0;
> +  p = rtems_calloc(SIZE_MAX, SIZE_MAX);
> +  rtems_test_assert(p == NULL);
> +  rtems_test_assert(errno == 0);
> +#pragma GCC diagnostic pop
> +
>    i = rtems_calloc(1, sizeof(*i));
>    rtems_test_assert(i != NULL);
>    rtems_test_assert(*i == 0);
> @@ -1313,22 +1321,17 @@ rtems_task Init(
>  #pragma GCC diagnostic push
>  #pragma GCC diagnostic ignored "-Walloc-size-larger-than=N"
>    p1 = calloc( 1, SIZE_MAX );
> +  rtems_test_assert( p1 == NULL );
> +
> +  p1 = calloc( SIZE_MAX, SIZE_MAX );
> +  rtems_test_assert( p1 == NULL );
>  #pragma GCC diagnostic pop
> -  if (p1) {
> -    printf("ERROR on attempt to calloc SIZE_MAX block expected failure.");
> -    free( p1 );
> -  }
>
>    /*
>     * Verify error case where malloc of size 0.
>     */
>    p1 = malloc( 0 );
> -  if (p1) {
> -    printf("ERROR on attempt to malloc size 0 block expected failure.");
> -    free( p1 );
> -  }
> -
> -
> +  rtems_test_assert( p1 == NULL );
>
>    test_heap_initialize();
>    test_heap_block_allocate();
> --
> 2.26.2
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20210420/d55edffa/attachment.html>


More information about the devel mailing list