Bug 282916 - The strptime() function in libc/stdtime parses an incorrect wday value with the %x format for dates after 12/31/00
Summary: The strptime() function in libc/stdtime parses an incorrect wday value with t...
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 14.1-RELEASE
Hardware: amd64 Any
: --- Affects Many People
Assignee: Dag-Erling Smørgrav
URL: https://reviews.freebsd.org/D47977
Keywords:
Depends on:
Blocks:
 
Reported: 2024-11-22 10:36 UTC by Erkki Moorits
Modified: 2024-12-16 14:37 UTC (History)
6 users (show)

See Also:
des: mfc-stable14+
des: mfc-stable13+


Attachments
Test code for strptime(..., "%x", ...) (1.62 KB, text/plain)
2024-11-22 10:36 UTC, Erkki Moorits
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Erkki Moorits 2024-11-22 10:36:14 UTC
Created attachment 255388 [details]
Test code for strptime(..., "%x", ...)

When I use strptime() input descriptor "%x" to decode date, then after 12/31/00 strptime() decodes wrong wday.

Here are the different test results from the attached test program.

Expected decoded values are (reference tests on Ubuntu Linux):
12/31/00:
	Time: 00:00:00  	Date: 2000-12-31
	Wday: 0 Yday: 365 (DST 0 Zone [(null)] offset 0)

01/01/01:
	Time: 00:00:00  	Date: 2001-01-01
	Wday: 1 Yday: 000 (DST 0 Zone [(null)] offset 0)

01/02/01:
	Time: 00:00:00  	Date: 2001-01-02
	Wday: 2 Yday: 001 (DST 0 Zone [(null)] offset 0)


Actual values on FreeBSD 14.1-RELEASE-p5 GENERIC amd64:
12/31/00:
	Time: 00:00:00  	Date: 2000-12-31
	Wday: 0 Yday: 365 (DST 0 Zone [(null)] offset 0)

01/01/01:
	Time: 00:00:00  	Date: 2001-01-01
	Wday: 0 Yday: 000 (DST 0 Zone [(null)] offset 0)

01/02/01:
	Time: 00:00:00  	Date: 2001-01-02
	Wday: 1 Yday: 001 (DST 0 Zone [(null)] offset 0)

Also wday values from %c and %x are different (first lines are decoded by using %c, last by using %x):
Fri Mar  4 20:05:34 2005:
	Time: 20:05:34  	Date: 2005-03-04
	Wday: 5 Yday: 062 (DST 0 Zone [(null)] offset 0)

03/04/05:
	Time: 00:00:00  	Date: 2005-03-04
	Wday: 4 Yday: 062 (DST 0 Zone [(null)] offset 0)
Comment 1 Mark Johnston freebsd_committer freebsd_triage 2024-12-06 17:14:54 UTC
Philip, do you sync the strptime() implementation from an upstream together with timezone info?  Maybe we're missing a bug fix somewhere.
Comment 2 Jose Luis Duran freebsd_committer freebsd_triage 2024-12-06 17:19:55 UTC
It might be worth also taking a look at:

https://github.com/apple-oss-distributions/Libc/blob/main/stdtime/FreeBSD/strptime.c
Comment 3 Philip Paeps freebsd_committer freebsd_triage 2024-12-07 01:25:49 UTC
I've only been syncing tzdata.  DES has been tracking tzcode of late.

I thought we were mostly in sync with upstream, but something may have been missed.

DES: do you have time to take a look at this?  If not, feel free to assign to me and I'll look for a round tuit. :) Thank you!
Comment 4 Dag-Erling Smørgrav freebsd_committer freebsd_triage 2024-12-07 12:22:18 UTC
strptime(3) is not part of tzcode, but I'll take a look.
Comment 5 Dag-Erling Smørgrav freebsd_committer freebsd_triage 2024-12-07 13:36:13 UTC
The situation was worse than I expected, with only 4 out of my 13 test cases passing:

    *** Check failed: expected 1 for 1582-12-20, got 2
    *** Check failed: expected 4 for 1752-09-14, got 3
    *** Check failed: expected 4 for 1801-01-01, got -3
    *** Check failed: expected 1 for 1900-12-31, got 0
    *** Check failed: expected 1 for 2001-01-01, got 0
    *** Check failed: expected 5 for 2100-12-31, got 4
    *** Check failed: expected 6 for 2101-01-01, got 5
    *** Check failed: expected 3 for 2200-12-31, got 2
    *** Check failed: expected 4 for 2201-01-01, got 3
Comment 6 commit-hook freebsd_committer freebsd_triage 2024-12-09 12:39:41 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=4285e024baa80f81d13cdcc016fdf0721fe57862

commit 4285e024baa80f81d13cdcc016fdf0721fe57862
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2024-12-09 12:37:45 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2024-12-09 12:38:22 +0000

    strptime: Fix day-of-week calculation.

    The day-of-week calculation used the raw year value without adjusting
    for TM_YEAR_BASE, so it was off by one for 300 years out of every 400;
    it just happened to be correct for 1901 through 2000.  It also used a
    loop where a simple addition would have sufficed.

    While here, simplify our version of Gauss's algorithm, and document
    that we assume the Gregorian calendar.

    MFC after:      1 week
    PR:             282916
    Reviewed by:    imp, allanjude, philip
    Differential Revision:  https://reviews.freebsd.org/D47977

 etc/mtree/BSD.tests.dist                     |  2 ++
 lib/libc/stdtime/strptime.3                  |  7 +++-
 lib/libc/stdtime/strptime.c                  | 22 +++++-------
 lib/libc/tests/Makefile                      |  1 +
 lib/libc/tests/stdtime/Makefile (new)        |  7 ++++
 lib/libc/tests/stdtime/strptime_test.c (new) | 50 ++++++++++++++++++++++++++++
 6 files changed, 74 insertions(+), 15 deletions(-)
Comment 7 commit-hook freebsd_committer freebsd_triage 2024-12-16 13:35:54 UTC
A commit in branch stable/14 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=259dcedc4ade538c35100d364e5cfe30b89c9a95

commit 259dcedc4ade538c35100d364e5cfe30b89c9a95
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2024-12-09 12:37:45 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2024-12-16 10:37:08 +0000

    strptime: Fix day-of-week calculation.

    The day-of-week calculation used the raw year value without adjusting
    for TM_YEAR_BASE, so it was off by one for 300 years out of every 400;
    it just happened to be correct for 1901 through 2000.  It also used a
    loop where a simple addition would have sufficed.

    While here, simplify our version of Gauss's algorithm, and document
    that we assume the Gregorian calendar.

    MFC after:      1 week
    PR:             282916
    Reviewed by:    imp, allanjude, philip
    Differential Revision:  https://reviews.freebsd.org/D47977

    (cherry picked from commit 4285e024baa80f81d13cdcc016fdf0721fe57862)

 etc/mtree/BSD.tests.dist                     |  2 ++
 lib/libc/stdtime/strptime.3                  |  7 +++-
 lib/libc/stdtime/strptime.c                  | 22 +++++-------
 lib/libc/tests/Makefile                      |  1 +
 lib/libc/tests/stdtime/Makefile (new)        |  7 ++++
 lib/libc/tests/stdtime/strptime_test.c (new) | 50 ++++++++++++++++++++++++++++
 6 files changed, 74 insertions(+), 15 deletions(-)
Comment 8 commit-hook freebsd_committer freebsd_triage 2024-12-16 13:35:59 UTC
A commit in branch stable/13 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=48d21d15a8f22c766f1651c0a244554f6b5d7af7

commit 48d21d15a8f22c766f1651c0a244554f6b5d7af7
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2024-12-09 12:37:45 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2024-12-16 10:38:57 +0000

    strptime: Fix day-of-week calculation.

    The day-of-week calculation used the raw year value without adjusting
    for TM_YEAR_BASE, so it was off by one for 300 years out of every 400;
    it just happened to be correct for 1901 through 2000.  It also used a
    loop where a simple addition would have sufficed.

    While here, simplify our version of Gauss's algorithm, and document
    that we assume the Gregorian calendar.

    MFC after:      1 week
    PR:             282916
    Reviewed by:    imp, allanjude, philip
    Differential Revision:  https://reviews.freebsd.org/D47977

    (cherry picked from commit 4285e024baa80f81d13cdcc016fdf0721fe57862)

 etc/mtree/BSD.tests.dist                     |  2 ++
 lib/libc/stdtime/strptime.3                  |  7 +++-
 lib/libc/stdtime/strptime.c                  | 22 +++++-------
 lib/libc/tests/Makefile                      |  1 +
 lib/libc/tests/stdtime/Makefile (new)        |  7 ++++
 lib/libc/tests/stdtime/strptime_test.c (new) | 50 ++++++++++++++++++++++++++++
 6 files changed, 74 insertions(+), 15 deletions(-)