[PATCH 2/8] score: Fix allocation size calculation
Gedare Bloom
gedare at rtems.org
Thu Sep 24 16:50:51 UTC 2020
On Thu, Sep 24, 2020 at 10:30 AM Gedare Bloom <gedare at rtems.org> wrote:
>
> 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...
Then again, maybe the division is needed here to ensure there isn't an
overflow later? This stuff gets a little tricky!
>
> > 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