fix(tasks): reject uxStackDepth that overflows the stack allocation size

prvCreateTask() computes the stack allocation size as
(size_t) uxStackDepth * sizeof(StackType_t) with no overflow check.
On 32-bit targets (where both size_t and the default
configSTACK_DEPTH_TYPE == StackType_t are 32-bit, e.g. the Cortex-M
ports), a caller-supplied uxStackDepth greater than
SIZE_MAX / sizeof(StackType_t) makes this multiplication wrap,
so pvPortMallocStack() allocates a much smaller buffer than the
caller asked for.

prvInitialiseNewTask() is unaware of the wrap: it still computes the
top-of-stack and fills the stack using the original, oversized
uxStackDepth (e.g. pxStack[uxStackDepth - 1]), which walks off the
end of the undersized allocation.

Fix: check for the overflow before attempting either allocation
branch (portSTACK_GROWTH > 0 or < 0) and fail the task creation the
same way a genuine pvPortMalloc()/pvPortMallocStack() failure is
already handled (pxNewTCB left NULL), using the same
'SIZE_MAX / x >= y' overflow-check idiom already used for this exact
purpose in queue.c (xQueueGenericReset(), xQueueGenericCreate()).

Fixes #1472
This commit is contained in:
saikumar-mandaji 2026-09-07 23:56:56 +05:30
parent 8be86d4a24
commit d698ab2a01

13
tasks.c
View file

@ -1637,6 +1637,19 @@ STATIC void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
{ {
TCB_t * pxNewTCB; TCB_t * pxNewTCB;
/* uxStackDepth is a word count that gets multiplied by
* sizeof( StackType_t ) below to get a byte count for the stack
* allocation. On targets where configSTACK_DEPTH_TYPE / size_t is
* 32-bit, an oversized uxStackDepth can make that multiplication
* wrap, silently allocating a far smaller stack than requested
* while prvInitialiseNewTask() still initialises the task using
* the original, larger uxStackDepth. Reject that up front and
* treat it the same as any other allocation failure. */
if( ( SIZE_MAX / sizeof( StackType_t ) ) < ( size_t ) uxStackDepth )
{
pxNewTCB = NULL;
}
else
/* If the stack grows down then allocate the stack then the TCB so the stack /* If the stack grows down then allocate the stack then the TCB so the stack
* does not grow into the TCB. Likewise if the stack grows up then allocate * does not grow into the TCB. Likewise if the stack grows up then allocate
* the TCB then the stack. */ * the TCB then the stack. */