Hello,
as discussed with Jim Meyering via IRC, I'm sending changed version of
the patch #3 to the list. This one patch adds range to valid TZ and
handles correctly hours when no minutes are specified (until that patch
is UTC+14 handled incorrectly as UTC+0:14) and are in common range of
UTC-12 to UTC+14. 
Although there are few different implementations of TZ limits (Microsoft
uses range UTC-14 to UTC+14 , various sources show that only TZ between
UTC-12 and UTC+14 are in use), this patch uses range UTC-24 to UTC+24 as
recommended for TZ environmental variable in POSIX
(http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html).
After applying that patch invalid TZ will show an invalid date format
error (because of double increment of pc->zones_seen).
I added few tests to gnulib getdate test suite to check if various TZ
formats are showing the same result.

Greetings,
         Ondrej Vasik
From 1c284d1a4155136ddaee44eab7fd5d55a75962fc Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ond=C5=99ej=20Va=C5=A1=C3=ADk?= <[EMAIL PROTECTED]>
Date: Fri, 4 Jul 2008 17:44:57 +0200
Subject: [PATCH] getdate.y: add limits for TZ, handle TZ +HH format correctly

* lib/getdate.y (time_zone_hh_mm): Allow only TZ in the range
UTC-24 to UTC+24 hours, consider first two digits of TZ as hours
when no minutes are specified and number is in the range -14
and +14 (as common TZ ranges UTC-12 to UTC+14). Invalid TZ will
cause invalid date format error.
* tests/test-getdate.c: Tests for that change
---
 ChangeLog            |    9 ++++++++
 lib/getdate.y        |   35 ++++++++++++++++++++++++++-------
 tests/test-getdate.c |   51 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 87 insertions(+), 8 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6c5f522..076d70e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-07-04  Ondřej Vašík  <[EMAIL PROTECTED]>
+
+	getdate.y: Allow only timezone range specified by POSIX
+	* lib/getdate.y (time_zone_hhmm): Allow only TZ in the range
+	-24 to +24 hours, consider first two digits between -14 and 14
+	as hours (as common TZ ranges UTC-12 to UTC+14). Invalid TZ
+	will cause invalid format error.
+	* tests/test-getdate.c: Tests for the fix
+
 2008-07-04  Jim Meyering  <[EMAIL PROTECTED]>
 
 	* users.txt: Add vc-dwim.
diff --git a/lib/getdate.y b/lib/getdate.y
index 695fd59..ace35be 100644
--- a/lib/getdate.y
+++ b/lib/getdate.y
@@ -205,7 +205,7 @@ typedef struct
 union YYSTYPE;
 static int yylex (union YYSTYPE *, parser_control *);
 static int yyerror (parser_control const *, char const *);
-static long int time_zone_hhmm (textint, long int);
+static long int time_zone_hhmm (parser_control *, textint, long int);
 
 /* Extract into *PC any date and time info from a string of digits
    of the form e.g., YYYYMMDD, YYMMDD, HHMM, HH (and sometimes YYY,
@@ -358,7 +358,7 @@ time:
 	set_hhmmss (pc, $1.value, $3.value, 0, 0);
 	pc->meridian = MER24;
 	pc->zones_seen++;
-	pc->time_zone = time_zone_hhmm ($4, $5);
+	pc->time_zone = time_zone_hhmm (pc, $4, $5);
       }
   | tUNUMBER ':' tUNUMBER ':' unsigned_seconds o_merid
       {
@@ -370,7 +370,7 @@ time:
 	set_hhmmss (pc, $1.value, $3.value, $5.tv_sec, $5.tv_nsec);
 	pc->meridian = MER24;
 	pc->zones_seen++;
-	pc->time_zone = time_zone_hhmm ($6, $7);
+	pc->time_zone = time_zone_hhmm (pc, $6, $7);
       }
   ;
 
@@ -394,7 +394,7 @@ zone:
       { pc->time_zone = $1;
 	apply_relative_time (pc, $2, 1); }
   | tZONE tSNUMBER o_colon_minutes
-      { pc->time_zone = $1 + time_zone_hhmm ($2, $3); }
+      { pc->time_zone = $1 + time_zone_hhmm (pc, $2, $3); }
   | tDAYZONE
       { pc->time_zone = $1 + 60; }
   | tZONE tDST
@@ -795,15 +795,34 @@ static table const military_table[] =
 
 /* Convert a time zone expressed as HH:MM into an integer count of
    minutes.  If MM is negative, then S is of the form HHMM and needs
-   to be picked apart; otherwise, S is of the form HH.  */
+   to be picked apart; otherwise, S is of the form HH. As specified at
+   http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html
+   allow only valid TZ range, otherwise increment pc->zones_seen to cause
+   invalid format error. */
 
 static long int
-time_zone_hhmm (textint s, long int mm)
+time_zone_hhmm (parser_control *pc, textint s, long int mm)
 {
+  long int returnvalue;
+
+  /* if s.value is lower than 15, add 00 minutes if minutes are
+     not specified as common time zones ranges between UTC-1200
+     and UTC+1400 */
+  if ((abs (s.value) < 15) && (mm < 0))
+    s.value *= 100;
+
   if (mm < 0)
-    return (s.value / 100) * 60 + s.value % 100;
+    returnvalue = (s.value / 100) * 60 + s.value % 100;
   else
-    return s.value * 60 + (s.negative ? -mm : mm);
+    returnvalue = s.value * 60 + (s.negative ? -mm : mm);
+
+  /* check if the return value is in real timezone range,
+     otherwise increment pc->zones_seen to cause time format
+     error, allow UTC-24:00 to UTC+24:00 */
+  if (abs (returnvalue) > 1440)
+    pc->zones_seen++;
+
+  return returnvalue;
 }
 
 static int
diff --git a/tests/test-getdate.c b/tests/test-getdate.c
index 901adf9..d84db84 100644
--- a/tests/test-getdate.c
+++ b/tests/test-getdate.c
@@ -53,6 +53,7 @@ main (int argc, char **argv)
   struct timespec result;
   struct timespec result2;
   struct timespec now;
+  int i;
   const char *p;
 
   now.tv_sec = 4711;
@@ -98,5 +99,55 @@ main (int argc, char **argv)
   ASSERT (result.tv_sec == result2.tv_sec
 	  && result.tv_nsec == result2.tv_nsec);
 
+  /* test if several time zones formats are handled same way */
+  now.tv_sec = 4711;
+  now.tv_nsec = 1267;
+  p = "UTC+14:00";
+  ASSERT (get_date (&result, p, &now));
+  LOG (p, now, result);
+  p = "UTC+14";
+  ASSERT (get_date (&result2, p, &now));
+  LOG (p, now, result2);
+  ASSERT (result.tv_sec == result2.tv_sec
+	  && result.tv_nsec == result2.tv_nsec);
+  p = "UTC+1400";
+  ASSERT (get_date (&result2, p, &now));
+  LOG (p, now, result2);
+  ASSERT (result.tv_sec == result2.tv_sec
+	  && result.tv_nsec == result2.tv_nsec);
+
+  now.tv_sec = 4711;
+  now.tv_nsec = 1267;
+  p = "UTC-14:00";
+  ASSERT (get_date (&result, p, &now));
+  LOG (p, now, result);
+  p = "UTC-14";
+  ASSERT (get_date (&result2, p, &now));
+  LOG (p, now, result2);
+  ASSERT (result.tv_sec == result2.tv_sec
+	  && result.tv_nsec == result2.tv_nsec);
+  p = "UTC-1400";
+  ASSERT (get_date (&result2, p, &now));
+  LOG (p, now, result2);
+  ASSERT (result.tv_sec == result2.tv_sec
+	  && result.tv_nsec == result2.tv_nsec);
+
+  now.tv_sec = 4711;
+  now.tv_nsec = 1267;
+  p = "UTC+00:15";
+  ASSERT (get_date (&result, p, &now));
+  LOG (p, now, result);
+  p = "UTC+15";
+  ASSERT (get_date (&result2, p, &now));
+  LOG (p, now, result2);
+  ASSERT (result.tv_sec == result2.tv_sec
+	  && result.tv_nsec == result2.tv_nsec);
+
+  /* TZ out of range should cause get_date failure */
+  now.tv_sec = 4711;
+  now.tv_nsec = 1267;
+  p = "UTC+25:00";
+  ASSERT (!get_date (&result, p, &now));
+
   return 0;
 }
-- 
1.5.6.1.156.ge903b

Attachment: signature.asc
Description: Toto je digitálně podepsaná část zprávy

_______________________________________________
Bug-coreutils mailing list
Bug-coreutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-coreutils

Reply via email to