fix(strptime): Don't clobber struct tm

Our strptime implementation uses subformatting to handle specifiers that
expand to other specifiers. For example, '%T' expands to "%H:%M%:%S".
Relibc calls strptime again to handle '%T' by expanding it.

However, our strptime zeroes out struct tm which clobbers old values. If
strptime is called with a format string like "%D%t%T", the set values
for '%D' are clobbered.

Zeroing out the struct is extra, unneeded work as well. The user may
want to preserve old values. We don't read from struct tm so we don't
have to worry about invalid values. Finally, `musl` and `glibc` don't
clear the values either so we can default to their behavior.
This commit is contained in:
Josh Megnauth
2025-04-01 23:35:29 -04:00
parent 7f2a2ffe13
commit 090391d94f
2 changed files with 15 additions and 22 deletions
-6
View File
@@ -89,12 +89,6 @@ pub unsafe extern "C" fn strptime(
}
};
// Zero-initialize the output `tm` structure
// (equivalent to: tm_sec=0, tm_min=0, tm_hour=0...)
unsafe {
ptr::write_bytes(tm, 0, 1);
}
// We parse the format specifiers in a loop
let mut fmt_chars = fmt_str.chars().peekable();
let mut index_in_input = 0;
+15 -16
View File
@@ -99,22 +99,21 @@ int main(void) {
);
// TODO: Locale offset
// Also, this test is broken on Redox
/* const char redox[] = "Mon Oct 31 11:19:57 2016"; */
/* struct tm redox_expect = { */
/* .tm_year = 116, */
/* .tm_mon = 9, */
/* .tm_mday = 31, */
/* .tm_hour = 11, */
/* .tm_min = 19, */
/* .tm_sec = 57, */
/* .tm_yday = 304, */
/* .tm_wday = 1, */
/* }; */
/* strptime_test(redox, */
/* "%a%t%b%t%d%t%T%t%Y", */
/* redox_expect, */
/* ""); */
const char redox[] = "Mon Oct 31 11:19:57 2016";
struct tm redox_expect = {
.tm_year = 116,
.tm_mon = 9,
.tm_mday = 31,
.tm_hour = 11,
.tm_min = 19,
.tm_sec = 57,
/* .tm_yday = 304, */
.tm_wday = 1,
};
strptime_test(redox,
"%a%t%b%t%d%t%T%t%Y",
redox_expect,
"");
// Roundtrip
const char roundtrip[] = "2012-01-19 13:37:00";