Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions common/src/tx_thread_stack_analyze.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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

Expand Down Expand Up @@ -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. */
Expand Down
13 changes: 10 additions & 3 deletions common_smp/src/tx_thread_stack_analyze.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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

Expand Down Expand Up @@ -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. */
Expand Down
15 changes: 15 additions & 0 deletions test/smp/regression/threadx_thread_stack_checking_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
/* SPDX-License-Identifier: MIT */
/***************************************************************************/

// Some portions generated by Copilot (Opus 5).

/* This test is for the thread stack checking services. */

#include <stdio.h>
Expand Down Expand Up @@ -200,6 +202,19 @@ TX_THREAD fake_thread;
fake_thread.tx_thread_stack_highest_ptr = TX_NULL;
_tx_thread_stack_analyze(&fake_thread);

/* Call the stack analyze with a highest stack pointer below the start of the stack, which is
what a stack overflow or a corrupted control block looks like. This used to hang. */
fake_thread.tx_thread_id = ((ULONG) 0x54485244);
fake_thread.tx_thread_stack_start = (void *) 0x2000;
fake_thread.tx_thread_stack_highest_ptr = (void *) 0x1000;
_tx_thread_stack_analyze(&fake_thread);

/* Call the stack analyze with a highest stack pointer equal to the start of the stack. */
fake_thread.tx_thread_id = ((ULONG) 0x54485244);
fake_thread.tx_thread_stack_start = (void *) 0x2000;
fake_thread.tx_thread_stack_highest_ptr = (void *) 0x2000;
_tx_thread_stack_analyze(&fake_thread);

/* Clear the pattern in thread 2's stack. */
TX_MEMSET(thread_2_stack_start, (CHAR) 0x11, TEST_STACK_SIZE_PRINTF);

Expand Down
15 changes: 15 additions & 0 deletions test/tx/regression/threadx_thread_stack_checking_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
/* SPDX-License-Identifier: MIT */
/***************************************************************************/

// Some portions generated by Copilot (Opus 5).

/* This test is for the thread stack checking services. */

#include <stdio.h>
Expand Down Expand Up @@ -200,6 +202,19 @@ TX_THREAD fake_thread;
fake_thread.tx_thread_stack_highest_ptr = TX_NULL;
_tx_thread_stack_analyze(&fake_thread);

/* Call the stack analyze with a highest stack pointer below the start of the stack, which is
what a stack overflow or a corrupted control block looks like. This used to hang. */
fake_thread.tx_thread_id = ((ULONG) 0x54485244);
fake_thread.tx_thread_stack_start = (void *) 0x2000;
fake_thread.tx_thread_stack_highest_ptr = (void *) 0x1000;
_tx_thread_stack_analyze(&fake_thread);

/* Call the stack analyze with a highest stack pointer equal to the start of the stack. */
fake_thread.tx_thread_id = ((ULONG) 0x54485244);
fake_thread.tx_thread_stack_start = (void *) 0x2000;
fake_thread.tx_thread_stack_highest_ptr = (void *) 0x2000;
_tx_thread_stack_analyze(&fake_thread);

/* Clear the pattern in thread 2's stack. */
TX_MEMSET(thread_2_stack_start, (CHAR) 0x11, TEST_STACK_SIZE_PRINTF);

Expand Down
Loading