From 8033540c7a6401d56530ba43be762d3890522e2f Mon Sep 17 00:00:00 2001 From: Martin Stumpf Date: Fri, 21 Nov 2025 13:41:14 +0100 Subject: [PATCH] MCUmgr: OS: fix set datetime millisecond handling According to the docs the millis were in the format `.SSSSSS`. In reality though, it only accepted exactly `.SSS`, not `.SS` or `.SSSS` and specifically also not `.SSSSSS`, contrary to the docs. Further, it did not fail with an error message but simply produced the wrong value. With this change it accepts everything from `.` to `.SSSSSS` and produces the correct result. This is compatible with the previous behavior, with the documentation and with everything in between. Signed-off-by: Martin Stumpf (cherry picked from commit ffb046b7971a928bb3a7f32445c35c6c90b476c9) --- subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c | 29 +++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c index 360385a1b95c2..d991f6f323f1c 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -117,8 +118,6 @@ struct datetime_parser { #define RTC_DATETIME_MINUTE_MAX 59 #define RTC_DATETIME_SECOND_MIN 0 #define RTC_DATETIME_SECOND_MAX 59 -#define RTC_DATETIME_MILLISECOND_MIN 0 -#define RTC_DATETIME_MILLISECOND_MAX 999 /* Size used for datetime creation buffer */ #ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_MS @@ -129,7 +128,7 @@ struct datetime_parser { /* Minimum/maximum size of a datetime string that a client can provide */ #define RTC_DATETIME_MIN_STRING_SIZE 19 -#define RTC_DATETIME_MAX_STRING_SIZE 26 +#define RTC_DATETIME_MAX_STRING_SIZE 31 #endif /* Specifies what the "all" ('a') of info parameter shows */ @@ -965,7 +964,7 @@ static int os_mgmt_datetime_write(struct smp_streamer *ctxt) bool ok = true; char *pos; char *new_pos; - char date_string[RTC_DATETIME_MAX_STRING_SIZE]; + char date_string[RTC_DATETIME_MAX_STRING_SIZE + 1]; struct rtc_time new_time = { .tm_wday = -1, .tm_yday = -1, @@ -1020,7 +1019,7 @@ static int os_mgmt_datetime_write(struct smp_streamer *ctxt) if (zcbor_map_decode_bulk(zsd, datetime_decode, ARRAY_SIZE(datetime_decode), &decoded)) { return MGMT_ERR_EINVAL; } else if (datetime.len < RTC_DATETIME_MIN_STRING_SIZE || - datetime.len >= RTC_DATETIME_MAX_STRING_SIZE) { + datetime.len > RTC_DATETIME_MAX_STRING_SIZE) { return MGMT_ERR_EINVAL; } @@ -1056,16 +1055,20 @@ static int os_mgmt_datetime_write(struct smp_streamer *ctxt) } #ifdef CONFIG_MCUMGR_GRP_OS_DATETIME_MS - if (*(pos - 1) == '.' && *pos != '\0') { - /* Provided value has a ms value, extract it */ - new_time.tm_nsec = strtol(pos, &new_pos, RTC_DATETIME_NUMERIC_BASE); - - if (new_time.tm_nsec < RTC_DATETIME_MILLISECOND_MIN || - new_time.tm_nsec > RTC_DATETIME_MILLISECOND_MAX) { - return MGMT_ERR_EINVAL; + if (*(pos - 1) == '.') { + uint32_t msec = 0; + uint32_t mul = 100; /* first digit: 10^-1 second = 100 ms */ + + /* Parse up to 3 fractional digits */ + while (isdigit((unsigned char)*pos) && mul >= 1) { + msec += (uint32_t)(*pos - '0') * mul; + mul /= 10; + pos++; } - new_time.tm_nsec *= RTC_DATETIME_MS_TO_NS; + /* "." without digits yields 0 µs */ + + new_time.tm_nsec = msec * RTC_DATETIME_MS_TO_NS; } #endif