Guarded _tx_thread_stack_analyze against inverted stack pointers (#727)

Fixes #460

`TX_ULONG_POINTER_DIF` casts the pointer difference to `ULONG`, so when
`tx_thread_stack_highest_ptr` sits below `tx_thread_stack_start` the midpoint
wraps to a huge value, the probe lands outside the stack, and the search never
converges: the caller hangs or faults.

`_tx_thread_stack_analyze` now requires the highest pointer to be strictly above
the start of the stack, and bounds the final scan by it. #464 covered the
`TX_THREAD_STACK_CHECK` path; this covers direct callers too, as
@billlamiework suggested on the issue.

Inconsistent pointers still mean a real overflow or a corrupted control block,
which remains the application's problem. What changes is that ThreadX reports it
through the stack error handler instead of hanging.

New cases for an inverted and an equal pointer pair crash the suite without the
fix and pass with it.

Assisted-by: Copilot (Opus 5) <noreply@github.com>
This commit is contained in:
Frédéric Desbiens
2026-09-15 16:24:35 -04:00
committed by GitHub
parent 5d235a534c
commit 1d4a4aeec8
4 changed files with 50 additions and 6 deletions
+10 -3
View File
@@ -73,6 +73,7 @@ ULONG *stack_ptr;
ULONG *stack_lowest;
ULONG *stack_highest;
ULONG *probe_ptr;
ULONG *stack_limit;
ULONG probe_count;
UINT fill_present;
ULONG size;
@@ -99,10 +100,16 @@ ULONG size;
/* Pickup the highest stack pointer. */
stack_highest = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_highest_ptr);
/* Determine if the pointer is null. */
if (stack_highest != TX_NULL)
/* Determine if the pointer is null or if the highest stack pointer is not above the
start of the stack. The latter indicates a stack overflow or a corrupted thread
control block, and the unsigned pointer arithmetic in the binary search below would
wrap around and never converge, hanging the caller. */
if ((stack_highest != TX_NULL) && (stack_highest > stack_lowest))
{
/* Remember the upper bound of the search so the scan below cannot run past it. */
stack_limit = stack_highest;
/* Restore interrupts. */
TX_RESTORE
@@ -173,7 +180,7 @@ ULONG size;
} while(size > ((ULONG) 1));
/* Position to first used word - at this point we are within a few words. */
while (*stack_ptr == TX_STACK_FILL)
while ((stack_ptr < stack_limit) && (*stack_ptr == TX_STACK_FILL))
{
/* Position to next word in stack. */