From b385fc5985cbb658c3062833f59eddaf49f01ec7 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Thu, 29 Aug 2024 10:29:38 +0300 Subject: [PATCH] [NTUSER] Fix a 64 bit bug in timer code The return value of RtlFindClearBitsAndSet is an ULONG, assigning it to an ULONG_PTR will not sign extend it. The error value will stay 0xFFFFFFFF. Comparing it to (UINT_PTR)-1 will sign extend and thus compare it to 0xFFFFFFFFFFFFFFFF on x64. Also use NUM_WINDOW_LESS_TIMERS to initialize the bitmap, rather than the calculated size. This does not make a difference with the current value (32768), but if it was not the case, the bitmap would be larger than this, resulting in invalid bitmap indices being returned, which would cause bugs later on. Finally remove an ASSERT that can be triggered by tests. --- win32ss/user/ntuser/timer.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/win32ss/user/ntuser/timer.c b/win32ss/user/ntuser/timer.c index 6d4a4e983be..db029cc039d 100644 --- a/win32ss/user/ntuser/timer.c +++ b/win32ss/user/ntuser/timer.c @@ -183,7 +183,8 @@ IntSetTimer( PWND Window, INT Type) { PTIMER pTmr; - UINT Ret = IDEvent; + UINT_PTR Ret = IDEvent; + ULONG ulBitmapIndex; LARGE_INTEGER DueTime; DueTime.QuadPart = (LONGLONG)(-97656); // 1024hz .9765625 ms set to 10.0 ms @@ -221,22 +222,22 @@ IntSetTimer( PWND Window, { IntLockWindowlessTimerBitmap(); - IDEvent = RtlFindClearBitsAndSet(&WindowLessTimersBitMap, 1, HintIndex++); - if (IDEvent == (UINT_PTR)-1) + ulBitmapIndex = RtlFindClearBitsAndSet(&WindowLessTimersBitMap, 1, HintIndex++); + if (ulBitmapIndex == ULONG_MAX) { HintIndex = HINTINDEX_BEGIN_VALUE; - IDEvent = RtlFindClearBitsAndSet(&WindowLessTimersBitMap, 1, HintIndex++); + ulBitmapIndex = RtlFindClearBitsAndSet(&WindowLessTimersBitMap, 1, HintIndex++); } - if (IDEvent == (UINT_PTR) -1) + if (ulBitmapIndex == ULONG_MAX) { IntUnlockWindowlessTimerBitmap(); ERR("Unable to find a free window-less timer id\n"); EngSetLastError(ERROR_NO_SYSTEM_RESOURCES); - ASSERT(FALSE); return 0; } - IDEvent = NUM_WINDOW_LESS_TIMERS - IDEvent; + ASSERT(ulBitmapIndex < NUM_WINDOW_LESS_TIMERS); + IDEvent = NUM_WINDOW_LESS_TIMERS - ulBitmapIndex; Ret = IDEvent; IntUnlockWindowlessTimerBitmap(); @@ -619,7 +620,7 @@ InitTimerImpl(VOID) RtlInitializeBitMap(&WindowLessTimersBitMap, WindowLessTimersBitMapBuffer, - BitmapBytes * 8); + NUM_WINDOW_LESS_TIMERS); /* Yes we need this, since ExAllocatePoolWithTag isn't supposed to zero out allocated memory */ RtlClearAllBits(&WindowLessTimersBitMap);