![]() |
|
Message-ID: <Z_QE74Sei_2quSJS@cloudsdale.the-delta.net.eu.org> Date: Mon, 7 Apr 2025 19:01:35 +0200 From: "Haelwenn (lanodan) Monnier" <contact@...ktivis.me> To: musl@...ts.openwall.com Cc: Rich Felker <dalias@...c.org>, ipedrosa@...hat.com, ~hallyn/shadow@...ts.sr.ht, libc-alpha@...rceware.org Subject: Re: strptime("UTC", "%Z", &tm) in musl [2025-04-07 01:54:14+0200] Alejandro Colomar: >Hi Haelwenn, > >On Sun, Apr 06, 2025 at 10:55:46PM +0200, Haelwenn (lanodan) Monnier wrote: >> [2025-04-06 21:57:35+0200] Alejandro Colomar: >> > I was trying to develop a function that parses a UTC date in the shadow >> > project, and I came up with this: >> > <https://github.com/shadow-maint/shadow/pull/1217/> >> > >> > $ grepc -htfd get_date . >> > static long >> > get_date(const char *s) >> > { >> > struct tm tm; >> > const char *p; >> > >> > bzero(&tm, sizeof(tm)); >> > >> > p = strptime("UTC", "%Z", &tm); >> > if (p == NULL || !streq(p, "")) >> > return -1; >> >> That bzero seems like a bit of a bad idea, `struct tm` can have some extra >> fields where 0 isn't the correct value. >> Quite like how `tm_isdst` uses -1 for unknown state, 0 for no-DST, 1 for DST. >> >> Could probably use `if(!gmtime_r(0, &tm)) { /* handle err */ }` instead >> which also has the nice effect of initializing tm for UTC, >> allowing to skip the problematic strptime %Z. > >Thanks! This is quite clever. I've changed this to my patch: > > diff --git i/lib/strtoday.c w/lib/strtoday.c > index 2d88e8b6..ab03b921 100644 > --- i/lib/strtoday.c > +++ w/lib/strtoday.c > @@ -47,13 +47,13 @@ strtoday(const char *str) > static long > get_date(const char *s) > { > + time_t t; > struct tm tm; > const char *p; > > - bzero(&tm, sizeof(tm)); > - > - p = strptime("UTC", "%Z", &tm); > - if (p == NULL || !streq(p, "")) > + // Set timezone to UTC > + t = 0; > + if (gmtime_r(&t, &tm) == NULL) > return -1; > > p = strptime(s, "%F", &tm); > >If you don't mind, I'd like to add you as a co-author of the patch, and >assign you copyright in that file. Please sign the following commit, if >you approve it. Yeah, looks good to me. And I guess Signed-off-by is the correct field for this. Signed-off-by: "Haelwenn (lanodan) Monnier" <contact@...ktivis.me> Best regards >Have a lovely night! >Alex > > >--- > ><https://github.com/shadow-maint/shadow/pull/1217> > >Author: Alejandro Colomar <alx@...nel.org> >Date: Tue Feb 18 23:25:29 2025 +0100 > > lib/getdate.c: Use strptime(3) to simplify > > The following trick: > > t = 0; > gmtime_r(&t, &tm); > > is a clever way to clear the tm(3type) structure, and set it to use UTC. > > We need to set it to set UTC with this trick, because strptime(3) > doesn't set the timezone. I (Alex) tried previously using > > bzero(&tm, sizeof(tm)); > strptime("UTC", "%Z", &tm); > > but glibc ignores the timezone, and musl (at least I tried in an Alpine > container) seems to report an error. > > The idea to use gmtime_r(3) was from lanodan. > > Link: <https://inbox.sourceware.org/libc-alpha/Z_LqUgildoq33vI-@cloudsdale.the-delta.net.eu.org/T/#u> > Cc: Iker Pedrosa <ipedrosa@...hat.com> > Cc: Serge Hallyn <serge@...lyn.com> > Cc: Rich Felker <dalias@...c.org> > Co-authored-by: "Haelwenn (lanodan) Monnier" <contact@...ktivis.me> > Signed-off-by: Alejandro Colomar <alx@...nel.org> > >diff --git a/lib/getdate.c b/lib/getdate.c >index 31a5c25b..fa2df83e 100644 >--- a/lib/getdate.c >+++ b/lib/getdate.c >@@ -1,81 +1,31 @@ > // SPDX-FileCopyrightText: 2025, Alejandro Colomar <alx@...nel.org> >+// SPDX-FileCopyrightText: 2025, "Haelwenn (lanodan) Monnier" <contact@...ktivis.me> > // SPDX-License-Identifier: BSD-3-Clause > > > #include <config.h> > >-#include <errno.h> >-#include <limits.h> > #include <stddef.h> >-#include <string.h> > #include <time.h> > >-#include "atoi/a2i/a2s.h" > #include "getdate.h" >-#include "string/strchr/strchrcnt.h" > #include "string/strcmp/streq.h" >-#include "string/strcmp/strprefix.h" >-#include "string/strcmp/strsuffix.h" >-#include "string/strspn/stpspn.h" >- >- >-#define TM_YEAR_ORIGIN 1900 >- >- >-static long yyDay; >-static long yyMonth; >-static long yyYear; >- >- >-static int parse_date(const char *s); > > > time_t >-get_date(const char *s); >+get_date(const char *s) > { >- struct tm tm; >+ time_t t; >+ struct tm tm; >+ const char *p; > >- if (parse_date(p) == -1) >+ t = 0; >+ if (gmtime_r(&t, &tm) == NULL) > return -1; > >- tm.tm_year = yyYear - TM_YEAR_ORIGIN; >- tm.tm_mon = yyMonth - 1; >- tm.tm_mday = yyDay; >- tm.tm_hour = tm.tm_min = tm.tm_sec = 0; >- tm.tm_isdst = 0; >+ p = strptime(s, "%F", &tm); >+ if (p == NULL || !streq(p, "")) >+ return -1; > > return timegm(&tm); > } >- >- >-static int >-parse_date(const char *s) >-{ >- long n; >- >- if (!streq(stpspn(s, "0123456789-"), "") >- || strchrcnt(s, '-') != 2 >- || strprefix(s, "-") >- || strsuffix(s, "-") >- || strstr(s, "--")) >- { >- return -1; >- } >- >- if (a2sl(&yyYear, s, &s, 10, LONG_MIN, LONG_MAX) == -1 && errno != ENOTSUP) >- return -1; >- >- if (!strprefix(s++, "-")) >- return -1; >- >- if (a2sl(&yyMonth, s, &s, 10, LONG_MIN, LONG_MAX) == -1 && errno != ENOTSUP) >- return -1; >- >- if (!strprefix(s++, "-")) >- return -1; >- >- if (a2sl(&yyDay, s, NULL, 10, LONG_MIN, LONG_MAX) == -1) >- return -1; >- >- return 0; >-} > >-- ><https://www.alejandro-colomar.es/> ><https://www.alejandro-colomar.es:8443/> ><http://www.alejandro-colomar.es:8080/>
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.