From 1e32d5d5ce97b8eb03ce32d7eed632fd2ee9860f Mon Sep 17 00:00:00 2001 From: BDisp Date: Mon, 27 Oct 2025 01:46:59 +0000 Subject: [PATCH] Do a double operation first before cast to long (#4353) --- Terminal.Gui/App/Timeout/TimedEvents.cs | 8 +++++++- Tests/UnitTests/Application/TimedEventsTests.cs | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Terminal.Gui/App/Timeout/TimedEvents.cs b/Terminal.Gui/App/Timeout/TimedEvents.cs index fc8f36d17..da1dcc5c0 100644 --- a/Terminal.Gui/App/Timeout/TimedEvents.cs +++ b/Terminal.Gui/App/Timeout/TimedEvents.cs @@ -55,7 +55,13 @@ public class TimedEvents : ITimedEvents { // Convert Stopwatch ticks to TimeSpan ticks (100-nanosecond units) // Stopwatch.Frequency gives ticks per second, so we need to scale appropriately - return Stopwatch.GetTimestamp () * TimeSpan.TicksPerSecond / Stopwatch.Frequency; + // To avoid overflow, we perform the operation in double precision first and then cast to long. + var ticks = (long)((double)Stopwatch.GetTimestamp () * TimeSpan.TicksPerSecond / Stopwatch.Frequency); + + // Ensure ticks is positive and not overflowed (very unlikely now) + Debug.Assert (ticks > 0); + + return ticks; } /// diff --git a/Tests/UnitTests/Application/TimedEventsTests.cs b/Tests/UnitTests/Application/TimedEventsTests.cs index b35128350..e03c027c7 100644 --- a/Tests/UnitTests/Application/TimedEventsTests.cs +++ b/Tests/UnitTests/Application/TimedEventsTests.cs @@ -92,9 +92,12 @@ public class TimedEventsTests return false; }); + Assert.True (timedEvents.Timeouts.Keys [0] > 0); + // Should execute on first RunTimers call timedEvents.RunTimers (); + Assert.Empty (timedEvents.Timeouts); Assert.True (executed); }