Hi Todd,
Todd C. Miller wrote on Fri, May 10, 2019 at 02:08:45PM -0600:
> On Fri, 10 May 2019 16:52:35 +0200, Ingo Schwarze wrote:
>> Here is a patch to fix the code.
> OK millert@ for that part.
Thanks, committed.
>> The change to %Z is exactly what Hiltjo sent.
>> The current code for %z is unnecessarily complicated.
>> Rather than fixing it, i simply rewrote it from scratch.
>> I like it when a bugfix results in -28 +11 LOC and better readability.
> I don't believe this handles the "[+-]hh" form.
Ouch. No, it does not. Thanks for spotting the regression.
The following patch preserves the parsing behaviour
and correctly stores the number of seconds into tm_gmtoff.
OK?
Ingo
$ ./z +1
NULL
$ ./z +02
7200
$ ./z +02x
7200 (rest "x")
$ ./z +02:
7200
$ ./z +02:x
7200 (rest "x")
$ ./z +02:1
NULL
$ ./z +02:01
7260
$ ./z +02:013
7260 (rest "3")
Index: strptime.c
===================================================================
RCS file: /cvs/src/lib/libc/time/strptime.c,v
retrieving revision 1.27
diff -u -p -r1.27 strptime.c
--- strptime.c 10 May 2019 20:24:58 -0000 1.27
+++ strptime.c 10 May 2019 20:43:35 -0000
@@ -519,32 +519,17 @@ literal:
}
return NULL;
}
- offs = 0;
- for (i = 0; i < 4; ) {
- if (isdigit(*bp)) {
- offs = offs * 10 + (*bp++ - '0');
- i++;
- continue;
- }
- if (i == 2 && *bp == ':') {
- bp++;
- continue;
- }
- break;
- }
- switch (i) {
- case 2:
- offs *= 100;
- break;
- case 4:
- i = offs % 100;
- if (i >= 60)
- return NULL;
- /* Convert minutes into decimal */
- offs = (offs / 100) * 100 + (i * 50) / 30;
- break;
- default:
+ if (!isdigit(bp[0]) || !isdigit(bp[1]))
return NULL;
+ offs = ((bp[0]-'0') * 10 + (bp[1]-'0')) * SECSPERHOUR;
+ bp += 2;
+ if (*bp == ':')
+ bp++;
+ if (isdigit(*bp)) {
+ offs += (*bp++ - '0') * 10 * SECSPERMIN;
+ if (!isdigit(*bp))
+ return NULL;
+ offs += (*bp++ - '0') * SECSPERMIN;
}
if (neg)
offs = -offs;