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;