parse-datetime: fix failure to diagnose invalid input
authorJim Meyering <meyering@redhat.com>
Wed, 4 Jul 2012 10:58:07 +0000 (12:58 +0200)
committerJim Meyering <meyering@redhat.com>
Wed, 4 Jul 2012 10:58:07 +0000 (12:58 +0200)
date -d "$(printf '\xb0')" would print 00:00:00 with today's date
rather than diagnosing the invalid input.  Now it reports this:
date: invalid date '\260'
* lib/parse-datetime.y (to_uchar): Define.
(yylex): Don't sign-extend "other" bytes.
* m4/parse-datetime.m4: Require AC_C_INLINE for first use of "inline".
Thanks to Bruno Haible for the patch to this file.
* tests/test-parse-datetime.c (main): Add a test to trigger the bug.
Peter Evans reported the bug in GNU date: http://bugs.gnu.org/11843

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

index 5edb6d4..cd3ba33 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2012-07-04  Jim Meyering  <meyering@redhat.com>
+
+       parse-datetime: fix failure to diagnose invalid input
+       date -d "$(printf '\xb0')" would print 00:00:00 with today's date
+       rather than diagnosing the invalid input.  Now it reports this:
+       date: invalid date '\260'
+       * lib/parse-datetime.y (to_uchar): Define.
+       (yylex): Don't sign-extend "other" bytes.
+       * m4/parse-datetime.m4: Require AC_C_INLINE for first use of "inline".
+       Thanks to Bruno Haible for the patch to this file.
+       * tests/test-parse-datetime.c (main): Add a test to trigger the bug.
+       Peter Evans reported the bug in GNU date: http://bugs.gnu.org/11843
+
 2012-07-03  Jim Meyering  <meyering@redhat.com>
 
        bootstrap: do not require now-removed build-aux/missing
index 67669f6..4d9f65a 100644 (file)
@@ -113,6 +113,11 @@ typedef long int long_time_t;
 typedef time_t long_time_t;
 #endif
 
+/* Convert a possibly-signed character to an unsigned character.  This is
+   a bit safer than casting to unsigned char, since it catches some type
+   errors that the cast doesn't.  */
+static inline unsigned char to_uchar (char ch) { return ch; }
+
 /* Lots of this code assumes time_t and time_t-like values fit into
    long_time_t.  */
 verify (TYPE_MINIMUM (long_time_t) <= TYPE_MINIMUM (time_t)
@@ -1171,7 +1176,8 @@ yylex (YYSTYPE *lvalp, parser_control *pc)
         }
 
       if (c != '(')
-        return *pc->input++;
+        return to_uchar (*pc->input++);
+
       count = 0;
       do
         {
index 8efefbe..3fb2d2b 100644 (file)
@@ -1,4 +1,4 @@
-# parse-datetime.m4 serial 19
+# parse-datetime.m4 serial 20
 dnl Copyright (C) 2002-2006, 2008-2012 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -32,6 +32,7 @@ AC_DEFUN([gl_PARSE_DATETIME],
 
   dnl Prerequisites of lib/parse-datetime.y.
   AC_REQUIRE([gl_BISON])
+  AC_REQUIRE([AC_C_INLINE])
   AC_REQUIRE([gl_C_COMPOUND_LITERALS])
   AC_STRUCT_TIMEZONE
   AC_REQUIRE([gl_CLOCK_TIME])
index 4c0370d..1c9fd2d 100644 (file)
@@ -409,5 +409,9 @@ main (int argc _GL_UNUSED, char **argv)
   ASSERT (result.tv_sec == 24 * 3600
           && result.tv_nsec == now.tv_nsec);
 
+  /* Exercise a sign-extension bug.  Before July 2012, an input
+     starting with a high-bit-set byte would be treated like "0".  */
+  ASSERT ( ! parse_datetime (&result, "\xb0", &now));
+
   return 0;
 }