Skip to content

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

Open
saikumar-mandaji wants to merge 1 commit into
FreeRTOS:mainfrom
saikumar-mandaji:fix-xtaskcreate-stack-size-overflow
Open

fix(tasks): reject uxStackDepth that overflows the stack allocation size#1489
saikumar-mandaji wants to merge 1 commit into
FreeRTOS:mainfrom
saikumar-mandaji:fix-xtaskcreate-stack-size-overflow

Conversation

@saikumar-mandaji

Copy link
Copy Markdown

Bug

prvCreateTask() computes the stack allocation size as (size_t) uxStackDepth * sizeof(StackType_t) with no overflow check (both the portSTACK_GROWTH > 0 and < 0 branches). 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 requested.

prvInitialiseNewTask() is unaware of the wrap: it still computes the top-of-stack and fills the stack using the original, oversized uxStackDepth (pxStack[uxStackDepth - 1], plus the memset fill), which walks off the end of the undersized allocation. See #1472 for the full repro (0x40000020 words wraps the allocation to 128 bytes).

Fix

Check for the overflow before attempting either allocation branch, and fail task creation the same way a genuine pvPortMalloc()/pvPortMallocStack() failure is already handled (pxNewTCB left NULL). Uses the same SIZE_MAX / x >= y overflow-check idiom already used for exactly this purpose in queue.c (xQueueGenericReset(), xQueueGenericCreate()), so it's consistent with existing project convention rather than a new idiom.

Verification

  • Compiled tasks.c clean (-std=gnu99 -mcpu=cortex-m4 -mthumb -Wall -Wextra) against the real portable/GCC/ARM_CM4F port headers with a minimal FreeRTOSConfig.h (dynamic allocation, no static allocation) — this exercises the exact 32-bit size_t/StackType_t configuration the bug report describes, using arm-none-eabi-gcc since no host-native compiler was available in this environment.
  • Did not run the kernel under an emulator/QEMU to reproduce the original wrap+overflow at runtime — the fix is a straightforward precondition check mirroring an existing, already-tested pattern in the same codebase (queue.c), so I'm confident in the logic but flagging this honestly.

Fixes #1472

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 FreeRTOS#1472
@sonarqubecloud

sonarqubecloud Bot commented Sep 7, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] xTaskCreate() unsigned integer overflow when calculating stack size

1 participant