From 54c3e971da6dbd6e11e48eef400add6dddbeec22 Mon Sep 17 00:00:00 2001 From: Kuoping Hsu Date: Fri, 15 May 2026 20:37:20 +0800 Subject: [PATCH] Fix undefined behavior in uxSchedulerCoreMask initialization and clamping logic --- tasks.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tasks.c b/tasks.c index d9fb2fc79..8e5abb867 100644 --- a/tasks.c +++ b/tasks.c @@ -515,8 +515,14 @@ PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandles[ configNUMBER_OF_CORES ]; /* Global scheduler core mask. Bit N = 1 means core N is allowed to run * non-idle tasks. Defaults to all cores enabled. Use * vTaskSetSchedulerCoreMask() / uxTaskGetSchedulerCoreMask() to change it - * at run time. */ - PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerCoreMask = ( UBaseType_t ) ( ( 1UL << configNUMBER_OF_CORES ) - 1UL ); + * at run time. + * + * The mask is derived by right-shifting ~0 rather than left-shifting 1, + * because left-shifting by a value equal to the type width is undefined + * behaviour in C (C11 ยง6.5.7). Using UBaseType_t throughout also avoids + * the assumption that unsigned long is at least as wide as UBaseType_t. */ + PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerCoreMask = + ( ( UBaseType_t ) ( ~( UBaseType_t ) 0U ) >> ( ( sizeof( UBaseType_t ) * ( size_t ) 8U ) - ( size_t ) configNUMBER_OF_CORES ) ); #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_SCHEDULER_CORE_MASK == 1 ) ) */ /* Improve support for OpenOCD. The kernel tracks Ready tasks via priority lists. @@ -3141,8 +3147,12 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, { uxOldMask = uxSchedulerCoreMask; - /* Clamp to the number of physical cores so stray bits are ignored. */ - uxSchedulerCoreMask = uxCoreMask & ( UBaseType_t ) ( ( 1UL << configNUMBER_OF_CORES ) - 1UL ); + /* Clamp to the number of physical cores so stray bits are ignored. + * The valid-core mask is derived by right-shifting ~0 to avoid + * left-shift UB and unsigned long width assumptions (see the + * uxSchedulerCoreMask initialiser for a full explanation). */ + uxSchedulerCoreMask = uxCoreMask & + ( ( UBaseType_t ) ( ~( UBaseType_t ) 0U ) >> ( ( sizeof( UBaseType_t ) * ( size_t ) 8U ) - ( size_t ) configNUMBER_OF_CORES ) ); if( xSchedulerRunning != pdFALSE ) {