Re: [PATCH v2 3/3] rtc: ftrtc010: fix integer overflow in time calculation

From: Liu Dalin

Date: Wed Oct 07 2026 - 22:16:12 EST



在 2026/10/2 18:59, Dan Carpenter 写道:
Commit 8ef8e9839a23 ("rtc: ftrtc010: fix integer overflow in time
calculation") from Aug 27, 2026 (linux-next), leads to the following
Smatch static checker warning:

drivers/rtc/rtc-ftrtc010.c:75 ftrtc010_rtc_read_time()
warn: cast after binop

On Thu, 27 Aug 2026 16:03:20 +0800 Liu Dalin <liudalin@xxxxxxxxxxxxxxx> wrote:
In ftrtc010_rtc_read_time() and ftrtc010_rtc_set_time(), all
variables (offset, days, hour, min, sec) are u32. The expression
"days * 86400 + hour * 3600 + min * 60 + sec" is evaluated in
32-bit arithmetic, which silently wraps around for dates beyond
approximately year 2106 (U32_MAX / 86400 ≈ 49710 days).

In ftrtc010_rtc_read_time(), perform the addition in 32-bit
arithmetic first to preserve two's complement wrapping for negative
offsets, then cast the result to timeu64_t. In
ftrtc010_rtc_set_time(), cast individual u32 operands to timeu64_t
before multiplication to prevent overflow in the right-hand side
of the offset calculation.

Fixes: 1d61d2592c1f ("rtc: ftrtc010: Rename to Faraday FTRTC010")
Assisted-by: Sashiko AI [static analysis]
Signed-off-by: Liu Dalin <liudalin@xxxxxxxxxxxxxxx>
---
drivers/rtc/rtc-ftrtc010.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c
index 19e6333bfbab..b29c96be40f4 100644
--- a/drivers/rtc/rtc-ftrtc010.c
+++ b/drivers/rtc/rtc-ftrtc010.c
@@ -72,7 +72,7 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm)
days = readl(rtc->rtc_base + FTRTC010_RTC_DAYS);
offset = readl(rtc->rtc_base + FTRTC010_RTC_RECORD);
- time = offset + days * 86400 + hour * 3600 + min * 60 + sec;
+ time = (timeu64_t)(offset + days * 86400 + hour * 3600 + min * 60 + sec);
There isn't any point in doing the cast outside the parentheses. The
other chunk probably does it correctly.

regards,
dan carpenter
Thanks Dan for review and catching this issue.

Commit 8ef8e9839a23 is now in Alexandre Belloni's rtc subsystem tree
(https://git.kernel.org/abelloni/c/8ef8e9839a23), not yet in linux‑next or mainline.

You are right, the original commit 8ef8e9839a23 only tried to preserve u32
wrap‑around for the RECORD offset but had two problems:
1. It triggers smatch "cast after binop" warning.
2. More importantly, casting the wrapped u32 value to timeu64_t does zero
extension instead of sign extension, so negative offsets become large
positive values and break time calculation.

I will send a separate fixup patch addressing both issues: cast raw RECORD
u32 value to s32 for proper two's complement interpretation, then perform
all calculations in timeu64_t to avoid 32‑bit overflow.

Regards,
Liu Dalin
rtc_time64_to_tm(time, tm);
@@ -92,7 +92,8 @@ static int ftrtc010_rtc_set_time(struct device *dev, struct rtc_time *tm)
hour = readl(rtc->rtc_base + FTRTC010_RTC_HOUR);
day = readl(rtc->rtc_base + FTRTC010_RTC_DAYS);
- offset = time - (day * 86400 + hour * 3600 + min * 60 + sec);
+ offset = time - ((timeu64_t)day * 86400 + (timeu64_t)hour * 3600 +
+ (timeu64_t)min * 60 + (timeu64_t)sec);
writel(offset, rtc->rtc_base + FTRTC010_RTC_RECORD);
writel(0x01, rtc->rtc_base + FTRTC010_RTC_CR);
--
2.43.0