Repository navigation
Conversation
settimeofday() decided whether the caller's arguments were valid by casting
them to long first:
if (tv != RT_NULL && (long)tv->tv_usec >= 0 && (long)tv->tv_sec >= 0)
On ILP32 targets where time_t is 64 bit (time64/long32, e.g. 32-bit ARM with
the default RT-Thread libc configuration) that cast narrows tv_sec to 32 bits.
Every timestamp from INT32_MAX + 1 to UINT32_MAX becomes negative, so the
function rejects perfectly valid values with EINVAL before it ever reaches the
RTC device. 2208988800 (2040-01-01) is rejected this way.
Validate the fields by their own type instead; tv_sec is compared as time_t,
which is signed in every configuration RT-Thread ships.
Verified on bsp/qemu-vexpress-a9 (32-bit ARM, RT_USING_RTC, on-board rtc
device, arm-none-eabi-gcc 15.2.1, QEMU 11.0.0), where the probe reports
sizeof(time_t) = 8 and sizeof(long) = 4:
tv_sec before after
0 ret=0 ret=0
2147483647 ret=0 ret=0
2147483648 ret=-1, errno=EINVAL ret=0
2208988800 ret=-1, errno=EINVAL ret=0
4294967295 ret=-1, errno=EINVAL ret=0
Values at or below INT32_MAX behave exactly as before.
Note: tv_usec is only checked for a negative value here, POSIX also requires
it to be below 1000000. That is a separate gap and is left untouched.
Refs RT-Thread#11922
|
👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread! 为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。 🛠 操作步骤 | Steps
完成后,提交将自动更新至 如有问题欢迎联系我们,再次感谢您的贡献!💐 |
📌 Code Review Assignment🏷️ Tag: componentsReviewers: @Maihuanyi Changed Files (Click to expand)
🏷️ Tag: components_libcReviewers: @GorrayLi @mysterywolf Changed Files (Click to expand)
📊 Current Review Status (Last Updated: 2026-10-25 01:14 CST)
📝 Review Instructions
|
|
拉取/合并请求描述:(PR description)
[
为什么提交这份PR (why to submit this PR)
修复 #11922。
settimeofday()用强转后的值判断参数是否合法:在 ILP32 且
time_t为 64 位的目标上(time64/long32,例如 32 位 ARM + RT-Thread 默认 libc 配置),这个(long)会把tv_sec截成 32 位。于是INT32_MAX + 1到UINT32_MAX区间的每个合法时间戳都变成负数,函数在碰到 RTC 设备之前就以EINVAL拒绝。2208988800(2040-01-01)就是这样被拒的。你的解决方案是什么 (what is your solution)
按字段自身类型校验,不做强转:
tv_sec直接按time_t比较,RT-Thread 各配置下time_t都是有符号类型,所以>= 0的判断依然有效,只是不再窄化。tv_usec的强转也一并去掉,只是为了两处写法统一;它在 ILP32 上原本就没问题(suseconds_t32 位)。如果希望改动更小,只动tv_sec也可以。请提供验证的bsp和config (provide the config and bsp)
bsp/qemu-vexpress-a9(32 位 ARM,RT_USING_RTC=y,板上有rtc设备)1c801efa运行时探针确认
sizeof(time_t)=8、sizeof(long)=4,正是 time64/long32。逐点扫描边界,同一份固件改前/改后各跑一次:
首个被拒值正好是
INT32_MAX + 1,与 issue 描述的区间一致;INT32_MAX及以下行为完全未变。两点说明
未包含的相邻缺陷:当前只校验
tv_usec >= 0,POSIX 还要求< 1000000。传tv_usec = 5000000会被放行并送进 RTC 驱动。这属于另一处校验缺失,为了避免把两种行为变更混在一个补丁里,本次没有改动,是否收紧由维护者判断。关于 utest:这个用例要能跑,前提是系统里有
rtc设备(_control_rtc()通过rt_device_find("rtc")查找,找不到会返回-RT_ENOSYS,这与强转问题是两条不同的失败路径)。CI 里的 qemu-vexpress-a9 有 rtc,但其他跑 utest 的 BSP 未必有,直接加会因找不到设备而误失败。如果维护者确认放在哪个 BSP/config 合适,我可以补一条RT_USING_RTC条件下编译的用例,断言INT32_MAX + 1与2208988800能通过。]
当前拉取/合并请求的状态 Intent for your PR
必须选择一项 Choose one (Mandatory):
代码质量 Code Quality:
我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:
#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up