Skip to content

[fix][kernel] fix timegm month overflow calculation - #11720

Open
liulangrenaaa wants to merge 1 commit into
RT-Thread:masterfrom
liulangrenaaa:fix-mktime-11686
Open

[fix][kernel] fix timegm month overflow calculation#11720
liulangrenaaa wants to merge 1 commit into
RT-Thread:masterfrom
liulangrenaaa:fix-mktime-11686

Conversation

@liulangrenaaa

@liulangrenaaa liulangrenaaa commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

When normalizing tm_mday, the original code used cumulative day offsets
from __spm[] as if they were the length of the current month. This caused
incorrect dates after crossing month boundaries. For example,
2026/08/05 + 420 days was normalized to 2027/03/01 instead of
2027/09/29.

The existing normalization also did not handle zero or negative tm_mday
values, leaving the broken-down time fields unnormalized.

Use the difference between adjacent __spm[] entries to obtain the actual
month length, with leap-year handling for February. Add backward
normalization for zero and negative days, and normalize negative
tm_sec, tm_min, tm_hour, and tm_mon values consistently with the existing
positive overflow handling.

Add regression tests covering month boundaries, leap years, large day
offsets, zero and negative days, negative time fields, carry boundaries,
combined overflow, and timestamp round-trip consistency.

Close #11686

拉取/合并请求描述:(PR description)

为什么提交这份PR (why to submit this PR)

修复 timegm() 在日期字段越界时的归一化错误(Issue #11686)。

原实现使用 __spm[] 的累计天数作为当前月份长度,导致 tm_mday 跨月时计算错误。
例如 2026/08/05 加 420 天,预期结果为 2027/09/29,实际却得到
2027/03/01。

此外,tm_mday 为 0 或负数时也没有向前归一化,可能导致返回时间戳与
struct tm 中的日期字段不一致。

你的解决方案是什么 (what is your solution)

使用 __spm[mon + 1] - __spm[mon] 计算当前月份的实际天数,并正确处理
闰年二月。

增加 tm_mday <= 0 时向前回退月份和年份的归一化逻辑,同时补充
tm_sec、tm_min、tm_hour 和 tm_mon 的负值归一化,使其与已有的正向
越界处理保持一致。

新增 src/utest/time_tc.c 回归测试,覆盖:

  • 普通跨月边界
  • 闰年二月
  • 大天数偏移
  • tm_mday 为 0 和负数
  • 负 tm_sec/tm_min/tm_hour/tm_mon
  • -61、-13 等进位/借位边界
  • 正负组合越界
  • timestamp 与 UTC round-trip 一致性

请提供验证的bsp和config (provide the config and bsp)

  • BSP: bsp/qemu-vexpress-a9
  • .config: CONFIG_RT_USING_POSIX_CLOCK=y, CONFIG_RT_UTEST_TIME=y
  • action: 本地 QEMU core.time 测试通过

当前拉取/合并请求的状态 Intent for your PR

必须选择一项 Choose one (Mandatory):

  • 本拉取/合并请求是一个草稿版本 This PR is for a code-review and is intended to get feedback
  • 本拉取/合并请求是一个成熟版本 This PR is mature, and ready to be integrated into the repo

代码质量 Code Quality:

我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:

  • 已经仔细查看过代码改动的对比 Already check the difference between PR and old code
  • 代码风格正确,包括缩进空格,命名及其他风格 Style guide is adhered to, including spacing, naming and other styles
  • 没有垃圾代码,代码尽量精简,不包含#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up
  • 所有变更均有原因及合理的,并且不会影响到其他软件组件代码或BSP All modifications are justified and not affect other components or BSP
  • 对难懂代码均提供对应的注释 I've commented appropriately where code is tricky
  • 代码是高质量的 Code in this PR is of high quality
  • 已经使用clang-format 源码格式化工具确保格式符合RT-Thread代码规范 This PR has been formatted with clang-format and complies with RT-Thread code specification
  • 如果是新增bsp, 已经添加ci检查到.github/ALL_BSP_COMPILE.json 详细请参考链接BSP自查

@CLAassistant

CLAassistant commented Aug 18, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@github-actions

Copy link
Copy Markdown

👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread!

为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。
To ensure your code complies with RT-Thread's coding style, please run the code formatting workflow by following the steps below (If the formatting of CI fails to run).


🛠 操作步骤 | Steps

  1. 前往 Actions 页面 | Go to the Actions page
    点击进入工作流 → | Click to open workflow →

  2. 点击 Run workflow | Click Run workflow

  • Use workflow from 保持默认分支(通常为 master
    Keep the default branch (usually master) in Use workflow from
  • branch 输入框填写 PR 分支 fix-mktime-11686
    Enter PR branch fix-mktime-11686 in the branch field
  • 设置需排除的文件/目录(目录请以"/"结尾)
    Set files/directories to exclude (directories should end with "/")
  1. 等待工作流完成 | Wait for the workflow to complete
    格式化后的代码将作为独立提交推送至你的分支。
    The formatting changes will be pushed to your branch as a separate commit.

完成后,提交将自动更新至 fix-mktime-11686 分支,关联的 Pull Request 也会同步更新。
Once completed, commits will be pushed to the fix-mktime-11686 branch automatically, and the related Pull Request will be updated.

如有问题欢迎联系我们,再次感谢您的贡献!💐
If you have any questions, feel free to reach out. Thanks again for your contribution!

@github-actions github-actions Bot added Kernel PR has src relate code Component labels Aug 18, 2026
@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown

📌 Code Review Assignment

🏷️ Tag: components

Reviewers: @Maihuanyi

Changed Files (Click to expand)
  • components/libc/compilers/common/ctime.c
  • components/libc/compilers/common/utest/Kconfig
  • components/libc/compilers/common/utest/SConscript
  • components/libc/compilers/common/utest/time_tc.c
  • components/utilities/utest/Kconfig

🏷️ Tag: components_libc

Reviewers: @GorrayLi @mysterywolf

Changed Files (Click to expand)
  • components/libc/compilers/common/ctime.c
  • components/libc/compilers/common/utest/Kconfig
  • components/libc/compilers/common/utest/SConscript
  • components/libc/compilers/common/utest/time_tc.c

🏷️ Tag: workflow

Reviewers: @Rbb666 @kurisaW @supperthomas

Changed Files (Click to expand)
  • .github/utest/configs/components/libc.cfg
  • .github/workflows/utest_auto_run.yml

📊 Current Review Status (Last Updated: 2026-08-20 19:06 CST)


📝 Review Instructions

  1. 维护者可以通过单击此处来刷新审查状态: 🔄 刷新状态
    Maintainers can refresh the review status by clicking here: 🔄 Refresh Status

  2. 确认审核通过后评论 LGTM/lgtm
    Comment LGTM/lgtm after confirming approval

  3. PR合并前需至少一位维护者确认
    PR must be confirmed by at least one maintainer before merging

ℹ️ 刷新CI状态操作需要具备仓库写入权限。
ℹ️ Refresh CI status operation requires repository Write permission.

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

k230

  • SRAM: .eh_frame +8 B (+0.0%, 1,122,995 B / 268,300,288 B, total: 0% used)

loongson-ls1cdev

  • Code: .text +576 B (+0.2%, 363,208 B)

nuvoton-m487

  • CODE: .text +152 B (+0.0%, 355,948 B / 524,288 B, total: 68% used)

simulator

  • Code: .rela.dyn +10,488 B, .rodata +1,600 B, .text +4,875 B (+0.6%, 2,672,238 B)
  • Data: .data +12,032 B (+0.8%, 1,609,220 B)

wch-ch32v208w-r0

  • FLASH: .text +392 B (+0.2%, 159,888 B / 491,520 B, total: 33% used)

x86

@liulangrenaaa
liulangrenaaa force-pushed the fix-mktime-11686 branch 5 times, most recently from 00764ae to 60cc901 Compare August 19, 2026 05:57
@liulangrenaaa

Copy link
Copy Markdown
Contributor Author

ToolsCI 的失败看起来与本 PR 无关。

当前失败来自最近加入 RT-Thread/packages 的 ai/LiME-TM/Kconfig:

warning: default on the choice symbol LIME_TM_USING_MNIST_FS_EXAMPLE
warning: default on the choice symbol LIME_TM_USING_MNIST_STATIC_EXAMPLE

LiME-TM 是今天由 commit 69de99ddb0b8 加入 packages 的,目前 choice 下的两个 symbol 使用了 default n / default y,kconfiglib 会对此产生 warning。

而 ToolsCI 当前会把任意 Kconfig warning 当成错误并直接失败,因此这里需要先修复 LiME-TM 的 Kconfig,之后再重新运行 ToolsCI。

本 PR 修改的是 timegm() 及对应 utest,与上述 package Kconfig warning 无关。

Comment thread components/libc/compilers/common/ctime.c Outdated
@Rbb666

Rbb666 commented Aug 20, 2026

Copy link
Copy Markdown
Member

有两个问题:

  1. 新增用例没有进入 CI 实际执行。RT_UTEST_TIME 是 default n
  2. src/utest/time_tc.c 归属不合适。

建议调整为:

components/libc/compilers/common/utest/
├── Kconfig
├── SConscript
└── time_tc.c

同时:

  • 删除本 PR 对 src/utest/Kconfig、src/utest/SConscript 的修改。
  • 在 components/utilities/utest/Kconfig 中 rsource 新的 libc 测试 Kconfig。
  • 配置名建议改成 RT_UTEST_LIBC_TIME。
  • 测试导出名由 core.time 改成 components.libc.time。
  • 新增 .github/utest/configs/components/libc.cfg:
CONFIG_RT_CONSOLEBUF_SIZE=1024
CONFIG_RT_USING_CI_ACTION=y
CONFIG_RT_USING_POSIX_CLOCK=y
CONFIG_RT_UTEST_LIBC_TIME=y

@github-actions github-actions Bot added the action github action yml imporve label Aug 20, 2026
@liulangrenaaa

Copy link
Copy Markdown
Contributor Author

有两个问题:

  1. 新增用例没有进入 CI 实际执行。RT_UTEST_TIME 是 default n
  2. src/utest/time_tc.c 归属不合适。

建议调整为:

components/libc/compilers/common/utest/
├── Kconfig
├── SConscript
└── time_tc.c

同时:

  • 删除本 PR 对 src/utest/Kconfig、src/utest/SConscript 的修改。
  • 在 components/utilities/utest/Kconfig 中 rsource 新的 libc 测试 Kconfig。
  • 配置名建议改成 RT_UTEST_LIBC_TIME。
  • 测试导出名由 core.time 改成 components.libc.time。
  • 新增 .github/utest/configs/components/libc.cfg:
CONFIG_RT_CONSOLEBUF_SIZE=1024
CONFIG_RT_USING_CI_ACTION=y
CONFIG_RT_USING_POSIX_CLOCK=y
CONFIG_RT_UTEST_LIBC_TIME=y

done

@Rbb666

Rbb666 commented Aug 20, 2026

Copy link
Copy Markdown
Member

看到测试用例已经运行了,建议在用例中添加点LOG,这样可以直观的看到输出结果

PixPin_2026-08-20_18-35-12

The original overflow logic used __spm[tm_mon] as the current month's
length when normalizing tm_mday. This produced incorrect dates after
crossing month boundaries and left zero or negative days unnormalized.

Use the difference between adjacent cumulative day offsets with
leap-year handling. Normalize overflow in tm_sec, tm_min, tm_hour,
tm_mday, and tm_mon to keep the affected broken-down fields normalized.

Add regression tests for month boundaries, leap years, large offsets,
zero and negative days, negative time fields, combined overflow, and
boundary carry cases.

Close RT-Thread#11686

Signed-off-by: Hui Su <3164683437@qq.com>
@liulangrenaaa

Copy link
Copy Markdown
Contributor Author

看到测试用例已经运行了,建议在用例中添加点LOG,这样可以直观的看到输出结果

测试日志:
[I/utest] [----------] [ testcase ] (components.libc.time) started
[I/utest] large day offset: timestamp=1822204800, normalized=2027-09-29 08:00:00
[I/utest] zero day: timestamp=1672444800, normalized=2022-12-31 00:00:00
[I/utest] negative day: timestamp=1709078400, normalized=2024-02-28 00:00:00
[I/utest] positive overflow: timestamp=1704160921, normalized=2024-01-02 02:02:01
[I/utest] combined negative overflow: timestamp=1638223079, normalized=2021-11-29 21:57:59
[I/utest] [ PASSED ] [ result ] testcase (components.libc.time)
[I/utest] [==========] 1 tests from 1 testcase ran.
[I/utest] [ PASSED ] [ result ] 1 tests.

done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action github action yml imporve Component Kernel PR has src relate code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 内核mktime函数bug

3 participants