bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH]: Fix for several getdate.y issues (amended patch #3)


From: Jim Meyering
Subject: Re: [PATCH]: Fix for several getdate.y issues (amended patch #3)
Date: Tue, 02 Sep 2008 21:30:15 +0200

Ondřej Vašík <address@hidden> wrote:
> Jim Meyering wrote:
>> Documenting in getdate.texi will be enough, because that file is
>> included by coreutils.texi.  Thanks!
>
> Ok, here is amended version of the patch, first two (or less) digits are
> considered as hours, TZ correction limit set to +/-24:00, both changes
> in behaviour documented in getdate.texi.
>
> Greetings,
>          Ondrej
>
> From cf9655b40b3850e0d848490674949997f5b9402f Mon Sep 17 00:00:00 2001
> From: =?utf-8?q?Ond=C5=99ej=20Va=C5=A1=C3=ADk?= <address@hidden>
> Date: Fri, 25 Jul 2008 15:29:40 +0200
> Subject: [PATCH] getdate.y: add limits for TZ, handle TZ +HH format correctly
>
>  * doc/getdate.texi: Document new behaviour and limits of time zone
>  correction
>  * 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 specified. Invalid TZ will cause invalid date format
>  error.
>  * tests/test-getdate.c: Tests for that change

Sorry about the long delay.
Here's a revised patch that I'll push tomorrow.

>From 8bdfb3a55c87535fd58faf6fd04558680fb3e19f Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ond=C5=99ej=20Va=C5=A1=C3=ADk?= <address@hidden>
Date: Sat, 30 Aug 2008 15:04:04 +0200
Subject: [PATCH] getdate.y: reject an out-of-range timezone value

* lib/getdate.y (time_zone_hhmm): Reject any TZ offset that is outside
the range [-24...+24].  When specified with only one or two digits,
* tests/test-getdate.c: Tests for the fix.
* doc/getdate.texi: Document this change.
---
 doc/getdate.texi     |   13 ++++++----
 lib/getdate.y        |   34 +++++++++++++++++++++------
 tests/test-getdate.c |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 96 insertions(+), 13 deletions(-)

diff --git a/doc/getdate.texi b/doc/getdate.texi
index eae4526..7175e3d 100644
--- a/doc/getdate.texi
+++ b/doc/getdate.texi
@@ -265,16 +265,19 @@ which uses @samp{12m} for noon and @samp{12pm} for 
midnight.)
 The time may alternatively be followed by a time zone correction,
 expressed as @address@hidden@address@hidden, where @var{s} is @samp{+}
 or @samp{-}, @var{hh} is a number of zone hours and @var{mm} is a number
-of zone minutes.  You can also separate @var{hh} from @var{mm} with a colon.
+of zone minutes.
+The zone minutes term, @var{mm}, may be omitted, in which case
+the one- or two-digit correction is interpreted as a number of hours.
+You can also separate @var{hh} from @var{mm} with a colon.
 When a time zone correction is given this way, it
 forces interpretation of the time relative to
 Coordinated Universal Time (@sc{utc}), overriding any previous
 specification for the time zone or the local time zone.  For example,
 @samp{+0530} and @samp{+05:30} both stand for the time zone 5.5 hours
-ahead of @sc{utc} (e.g., India).  The @var{minute}
-part of the time of day may not be elided when a time zone correction
-is used.  This is the best way to specify a time zone correction by
-fractional parts of an hour.
+ahead of @sc{utc} (e.g., India).
+This is the best way to
+specify a time zone correction by fractional parts of an hour.
+The maximum zone correction is 24 hours.

 Either @samp{am}/@samp{pm} or a time zone correction may be specified,
 but not both.
diff --git a/lib/getdate.y b/lib/getdate.y
index a94bf8b..f9cd86c 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,33 @@ 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 in
+   http://www.opengroup.org/susv3xbd/xbd_chap08.html#tag_08_03, allow
+   only valid TZ range, and consider first two digits as hours, if no
+   minutes specified.  */

 static long int
-time_zone_hhmm (textint s, long int mm)
+time_zone_hhmm (parser_control *pc, textint s, long int mm)
 {
+  long int n_minutes;
+
+  /* If the length of S is 1 or 2 and no minutes are specified,
+     interpret it as a number of hours.  */
+  if (s.digits <= 2 && mm < 0)
+    s.value *= 100;
+
   if (mm < 0)
-    return (s.value / 100) * 60 + s.value % 100;
+    n_minutes = (s.value / 100) * 60 + s.value % 100;
   else
-    return s.value * 60 + (s.negative ? -mm : mm);
+    n_minutes = s.value * 60 + (s.negative ? -mm : mm);
+
+  /* If the absolute number of minutes is larger than 24 hours,
+     arrange to reject it by incrementing pc->zones_seen.  Thus,
+     we allow only values in the range UTC-24:00 to UTC+24:00.  */
+  if (24 * 60 < abs (n_minutes))
+    pc->zones_seen++;
+
+  return n_minutes;
 }

 static int
diff --git a/tests/test-getdate.c b/tests/test-getdate.c
index 901adf9..adbcf3a 100644
--- a/tests/test-getdate.c
+++ b/tests/test-getdate.c
@@ -98,5 +98,67 @@ 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+0:15";
+  ASSERT (get_date (&result, p, &now));
+  LOG (p, now, result);
+  p = "UTC+0015";
+  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-1:30";
+  ASSERT (get_date (&result, p, &now));
+  LOG (p, now, result);
+  p = "UTC-130";
+  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.6.0.1.161.g7f314




reply via email to

[Prev in Thread] Current Thread [Next in Thread]