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;

Reply via email to