[PATCH 2/8] score: Fix allocation size calculation
Gedare Bloom
gedare at rtems.org
Thu Sep 24 16:30:43 UTC 2020
On Thu, Sep 24, 2020 at 6:13 AM Sebastian Huber
<sebastian.huber at embedded-brains.de> wrote:
>
> The previous multiplication error check is broken on 64-bit machines. Use the
> recommended check from SEI CERT C Coding Standard, "INT30-C. Ensure that
> unsigned integer operations do not wrap".
>
> Make sure the message size computation does not overflow.
>
> Update #4007.
> ---
> cpukit/score/src/coremsg.c | 74 ++++++++++++--------------------------
> 1 file changed, 23 insertions(+), 51 deletions(-)
>
> diff --git a/cpukit/score/src/coremsg.c b/cpukit/score/src/coremsg.c
> index af8dbd6583..137d9973f4 100644
> --- a/cpukit/score/src/coremsg.c
> +++ b/cpukit/score/src/coremsg.c
> @@ -19,28 +19,12 @@
> #endif
>
> #include <rtems/score/coremsgimpl.h>
> +#include <rtems/score/assert.h>
> #include <rtems/score/wkspace.h>
>
> -/*
> - * size_t_mult32_with_overflow
> - *
> - * This method multiplies two size_t 32-bit numbers and checks
> - * for overflow. It returns false if an overflow occurred and
> - * the result is bad.
> - */
> -static inline bool size_t_mult32_with_overflow(
> - size_t a,
> - size_t b,
> - size_t *c
> -)
> -{
> - long long x = (long long)a*b;
> -
> - if ( x > SIZE_MAX )
> - return false;
> - *c = (size_t) x;
> - return true;
> -}
> +#define MESSAGE_SIZE_LIMIT \
> + ( SIZE_MAX - sizeof( uintptr_t ) - 1 \
Minor: should it be - ( sizeof( uintptr_t ) - 1 )?
Or: - sizeof(uintptr_t) + 1
The alignment up can add at most sizeof(uintptr_t)-1 bytes overhead I
think is what this is trying to capture?
> + - sizeof( CORE_message_queue_Buffer_control ) )
>
> bool _CORE_message_queue_Initialize(
> CORE_message_queue_Control *the_message_queue,
> @@ -49,48 +33,36 @@ bool _CORE_message_queue_Initialize(
> size_t maximum_message_size
> )
> {
> - size_t message_buffering_required = 0;
> - size_t aligned_message_size;
> + size_t buffer_size;
>
> the_message_queue->maximum_pending_messages = maximum_pending_messages;
> the_message_queue->number_of_pending_messages = 0;
> the_message_queue->maximum_message_size = maximum_message_size;
> _CORE_message_queue_Set_notify( the_message_queue, NULL );
>
> - /*
> - * Align up the maximum message size to be an integral multiple of the
> - * pointer size.
> - */
> - aligned_message_size = RTEMS_ALIGN_UP(
> - maximum_message_size,
> - sizeof( uintptr_t )
> - );
> -
> - /*
> - * Check for an integer overflow. It can occur while aligning up the maximum
> - * message size.
> - */
> - if (aligned_message_size < maximum_message_size)
> + /* Make sure the message size computation does not overflow */
> + if ( maximum_message_size > MESSAGE_SIZE_LIMIT ) {
> return false;
> + }
>
> - /*
> - * Calculate how much total memory is required for message buffering and
> - * check for overflow on the multiplication.
> - */
> - if ( !size_t_mult32_with_overflow(
> - (size_t) maximum_pending_messages,
> - aligned_message_size + sizeof(CORE_message_queue_Buffer_control),
> - &message_buffering_required ) )
> + buffer_size = RTEMS_ALIGN_UP( maximum_message_size, sizeof( uintptr_t ) );
> + _Assert( buffer_size >= maximum_message_size );
> +
> + buffer_size += sizeof( CORE_message_queue_Buffer_control );
> + _Assert( buffer_size >= sizeof( CORE_message_queue_Buffer_control ) );
> +
> + /* Make sure the memory allocation size computation does not overflow */
> + if ( maximum_pending_messages > SIZE_MAX / buffer_size ) {
optimization: can we use mult instead?
if ( maximum_pending_messages * buffer_size > SIZE_MAX )
save a few cycles...
> return false;
> + }
>
> - /*
> - * Attempt to allocate the message memory
> - */
> - the_message_queue->message_buffers = (CORE_message_queue_Buffer *)
> - _Workspace_Allocate( message_buffering_required );
> + the_message_queue->message_buffers = _Workspace_Allocate(
> + (size_t) maximum_pending_messages * buffer_size
... and the compiler should propagate that value to here to save even
more cycles. Or it could be put in a variable for simpler code.
> + );
>
> - if (the_message_queue->message_buffers == 0)
> + if ( the_message_queue->message_buffers == NULL ) {
> return false;
> + }
>
> /*
> * Initialize the pool of inactive messages, pending messages,
> @@ -100,7 +72,7 @@ bool _CORE_message_queue_Initialize(
> &the_message_queue->Inactive_messages,
> the_message_queue->message_buffers,
> (size_t) maximum_pending_messages,
> - aligned_message_size + sizeof( CORE_message_queue_Buffer_control )
> + buffer_size
> );
>
> _Chain_Initialize_empty( &the_message_queue->Pending_messages );
> --
> 2.26.2
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
More information about the devel
mailing list