]> Savannah Git Hosting - gnulib.git/commitdiff
parse-datetime: fix crash or infloop in TZ="" parsing
authorPádraig Brady <P@draigBrady.com>
Tue, 25 Feb 2014 10:58:48 +0000 (10:58 +0000)
committerPádraig Brady <P@draigBrady.com>
Thu, 27 Feb 2014 23:15:43 +0000 (23:15 +0000)
This was reported in http://bugs.gnu.org/16872
from the coreutils command: date -d 'TZ="""'

The infinite loop for this case was present since the
initial TZ="" parsing support in commit de95bdc2 29-10-2004.
This was changed to a crash or heap corruption depending
on the platform with commit 2e3e4195 18-01-2010.

* lib/parse-datetime.y (parse_datetime): Break out of the
TZ="" parsing loop once the second significant " is found.
Also skip over any subsequent whitespace to be consistent
with the non TZ= case.
* tests/test-parse-datetime.c: Add test cases for TZ="" parsing.

ChangeLog
lib/parse-datetime.y
tests/test-parse-datetime.c

index e938204e2d6d5b154a4b8916f262f3150206021b..4e1984ca03a7ba762989413d0ed523327a7cad53 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2014-02-26  Pádraig Brady <P@draigBrady.com>
+
+       parse-datetime: fix crash or infloop in TZ="" parsing
+       * lib/parse-datetime.y (parse_datetime): Break out of the
+       TZ="" parsing loop once the second significant " is found.
+       Also skip over any subsequent whitespace to be consistent
+       with the non TZ= case.
+       * tests/test-parse-datetime.c: Add test cases for TZ="" parsing.
+
 2014-02-26  Paul Eggert  <eggert@cs.ucla.edu>
 
        savedir: new symbol for fast-read version
index 6ece7656a964b4267bb3f83fc359c7f532ec5411..0ba0a5253f13687b528fb2036897cbf32b3e6012 100644 (file)
@@ -1303,8 +1303,6 @@ parse_datetime (struct timespec *result, char const *p,
             char tz1buf[TZBUFSIZE];
             bool large_tz = TZBUFSIZE < tzsize;
             bool setenv_ok;
-            /* Free tz0, in case this is the 2nd or subsequent time through. */
-            free (tz0);
             tz0 = get_tz (tz0buf);
             z = tz1 = large_tz ? xmalloc (tzsize) : tz1buf;
             for (s = tzbase; *s != '"'; s++)
@@ -1316,7 +1314,12 @@ parse_datetime (struct timespec *result, char const *p,
             if (!setenv_ok)
               goto fail;
             tz_was_altered = true;
+
             p = s + 1;
+            while (c = *p, c_isspace (c))
+              p++;
+
+            break;
           }
     }
 
index a410d3d49d55d670c16963f2bb203d33350c2c25..25385ca7db33746e1cc38b37a0c3f8b790f16afd 100644 (file)
@@ -419,5 +419,21 @@ main (int argc _GL_UNUSED, char **argv)
      starting with a high-bit-set byte would be treated like "0".  */
   ASSERT ( ! parse_datetime (&result, "\xb0", &now));
 
+  /* Exercise TZ="" parsing code.  */
+  /* These two would infloop or segfault before Feb 2014.  */
+  ASSERT ( ! parse_datetime (&result, "TZ=\"\"\"", &now));
+  ASSERT ( ! parse_datetime (&result, "TZ=\"\" \"", &now));
+  /* Exercise invalid patterns.  */
+  ASSERT ( ! parse_datetime (&result, "TZ=\"", &now));
+  ASSERT ( ! parse_datetime (&result, "TZ=\"\\\"", &now));
+  ASSERT ( ! parse_datetime (&result, "TZ=\"\\n", &now));
+  ASSERT ( ! parse_datetime (&result, "TZ=\"\\n\"", &now));
+  /* Exercise valid patterns.  */
+  ASSERT (   parse_datetime (&result, "TZ=\"\"", &now));
+  ASSERT (   parse_datetime (&result, "TZ=\"\" ", &now));
+  ASSERT (   parse_datetime (&result, " TZ=\"\"", &now));
+  ASSERT (   parse_datetime (&result, "TZ=\"\\\\\"", &now));
+  ASSERT (   parse_datetime (&result, "TZ=\"\\\"\"", &now));
+
   return 0;
 }