]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Parse date strings more properly - the code now handles semi-colons in
authorShawn Routhier <sar@isc.org>
Mon, 13 Sep 2010 19:30:42 +0000 (19:30 +0000)
committerShawn Routhier <sar@isc.org>
Mon, 13 Sep 2010 19:30:42 +0000 (19:30 +0000)
date strings correctly.  Thanks to a patch from Jiri Popelka at Red Hat.
[ISC-Bugs #21501, #20598]

RELNOTES
common/parse.c

index 9cdc5ccb341e2294b57f48f8b5f9e33ad49693b7..a40a7d5504df460fdda37a7cd82cb6a78633f301 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -93,6 +93,10 @@ work on other platforms. Please report any problems and suggested fixes to
   code to move most of the common code to a single routine.
   [ISC-Bugs #21171].
 
+- Parse date strings more properly - the code now handles semi-colons in
+  date strings correctly.  Thanks to a patch from Jiri Popelka at Red Hat.
+  [ISC-Bugs #21501, #20598]
+
                        Changes since 4.2.0rc1
 
 - Documentation cleanup covering multiple tickets
index 35224b3d7a1d74f5d5587cc2c0b1d68202e8f0b3..3e1b3bb7aa4e27386ea38093f361a200e5bad696 100644 (file)
@@ -889,9 +889,10 @@ void convert_num (cfile, buf, str, base, size)
 
 /*
  * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER 
- *             NUMBER COLON NUMBER COLON NUMBER SEMI |
+ *             NUMBER COLON NUMBER COLON NUMBER |
  *          NUMBER NUMBER SLASH NUMBER SLASH NUMBER 
- *             NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI |
+ *             NUMBER COLON NUMBER COLON NUMBER NUMBER |
+ *          EPOCH NUMBER |
  *         NEVER
  *
  * Dates are stored in UTC or with a timezone offset; first number is day
@@ -900,7 +901,10 @@ void convert_num (cfile, buf, str, base, size)
  * optional.
  */
 
-/* just parse the date */
+/*
+ * just parse the date
+ * any trailing semi must be consumed by the caller of this routine
+ */
 TIME 
 parse_date_core(cfile)
        struct parse *cfile;
@@ -909,157 +913,171 @@ parse_date_core(cfile)
        int tzoff, wday, year, mon, mday, hour, min, sec;
        const char *val;
        enum dhcp_token token;
-       static int months [11] = { 31, 59, 90, 120, 151, 181,
-                                         212, 243, 273, 304, 334 };
+       static int months[11] = { 31, 59, 90, 120, 151, 181,
+                                 212, 243, 273, 304, 334 };
 
-       /* Day of week, or "never"... */
-       token = next_token (&val, (unsigned *)0, cfile);
+       /* "never", "epoch" or day of week */
+       token = peek_token(&val, NULL, cfile);
        if (token == NEVER) {
-               if (!parse_semi (cfile))
-                       return 0;
-               return MAX_TIME;
+               token = next_token(&val, NULL, cfile); /* consume NEVER */
+               return(MAX_TIME);
        }
 
        /* This indicates 'local' time format. */
        if (token == EPOCH) {
-               token = next_token(&val, NULL, cfile);
+               token = next_token(&val, NULL, cfile); /* consume EPOCH */
+               token = peek_token(&val, NULL, cfile);
 
                if (token != NUMBER) {
-                       parse_warn(cfile, "Seconds since epoch expected.");
                        if (token != SEMI)
-                               skip_to_semi(cfile);
-                       return (TIME)0;
+                               token = next_token(&val, NULL, cfile);
+                       parse_warn(cfile, "Seconds since epoch expected.");
+                       return((TIME)0);
                }
 
+               token = next_token(&val, NULL, cfile); /* consume number */
                guess = atoi(val);
 
-               if (!parse_semi(cfile))
-                       return (TIME)0;
-
-               return guess;
+               return((TIME)guess);
        }
 
        if (token != NUMBER) {
-               parse_warn (cfile, "numeric day of week expected.");
                if (token != SEMI)
-                       skip_to_semi (cfile);
-               return (TIME)0;
+                       token = next_token(&val, NULL, cfile);
+               parse_warn(cfile, "numeric day of week expected.");
+               return((TIME)0);
        }
-       wday = atoi (val);
+       token = next_token(&val, NULL, cfile); /* consume day of week */
+       wday = atoi(val);
 
        /* Year... */
-       token = next_token (&val, (unsigned *)0, cfile);
+       token = peek_token(&val, NULL, cfile);
        if (token != NUMBER) {
-               parse_warn (cfile, "numeric year expected.");
                if (token != SEMI)
-                       skip_to_semi (cfile);
-               return (TIME)0;
+                       token = next_token(&val, NULL, cfile);
+               parse_warn(cfile, "numeric year expected.");
+               return((TIME)0);
        }
+       token = next_token(&val, NULL, cfile); /* consume year */
 
        /* Note: the following is not a Y2K bug - it's a Y1.9K bug.   Until
           somebody invents a time machine, I think we can safely disregard
           it.   This actually works around a stupid Y2K bug that was present
           in a very early beta release of dhcpd. */
-       year = atoi (val);
+       year = atoi(val);
        if (year > 1900)
                year -= 1900;
 
        /* Slash separating year from month... */
-       token = next_token (&val, (unsigned *)0, cfile);
+       token = peek_token(&val, NULL, cfile);
        if (token != SLASH) {
-               parse_warn (cfile,
-                           "expected slash separating year from month.");
                if (token != SEMI)
-                       skip_to_semi (cfile);
-               return (TIME)0;
+                       token = next_token(&val, NULL, cfile);
+               parse_warn(cfile,
+                          "expected slash separating year from month.");
+               return((TIME)0);
        }
+       token = next_token(&val, NULL, cfile); /* consume SLASH */
 
        /* Month... */
-       token = next_token (&val, (unsigned *)0, cfile);
+       token = peek_token(&val, NULL, cfile);
        if (token != NUMBER) {
-               parse_warn (cfile, "numeric month expected.");
                if (token != SEMI)
-                       skip_to_semi (cfile);
-               return (TIME)0;
+                       token = next_token(&val, NULL, cfile);
+               parse_warn(cfile, "numeric month expected.");
+               return((TIME)0);
        }
-       mon = atoi (val) - 1;
+       token = next_token(&val, NULL, cfile); /* consume month */      
+       mon = atoi(val) - 1;
 
        /* Slash separating month from day... */
-       token = next_token (&val, (unsigned *)0, cfile);
+       token = peek_token(&val, NULL, cfile);
        if (token != SLASH) {
-               parse_warn (cfile,
-                           "expected slash separating month from day.");
                if (token != SEMI)
-                       skip_to_semi (cfile);
-               return (TIME)0;
+                       token = next_token(&val, NULL, cfile);
+               parse_warn(cfile,
+                          "expected slash separating month from day.");
+               return((TIME)0);
        }
+       token = next_token(&val, NULL, cfile); /* consume SLASH */
 
        /* Day of month... */
-       token = next_token (&val, (unsigned *)0, cfile);
+       token = peek_token(&val, NULL, cfile);
        if (token != NUMBER) {
-               parse_warn (cfile, "numeric day of month expected.");
                if (token != SEMI)
-                       skip_to_semi (cfile);
-               return (TIME)0;
+                       token = next_token(&val, NULL, cfile);
+               parse_warn(cfile, "numeric day of month expected.");
+               return((TIME)0);
        }
-       mday = atoi (val);
+       token = next_token(&val, NULL, cfile); /* consume day of month */
+       mday = atoi(val);
 
        /* Hour... */
-       token = next_token (&val, (unsigned *)0, cfile);
+       token = peek_token(&val, NULL, cfile);
        if (token != NUMBER) {
-               parse_warn (cfile, "numeric hour expected.");
                if (token != SEMI)
-                       skip_to_semi (cfile);
-               return (TIME)0;
+                       token = next_token(&val, NULL, cfile);
+               parse_warn(cfile, "numeric hour expected.");
+               return((TIME)0);
        }
-       hour = atoi (val);
+       token = next_token(&val, NULL, cfile); /* consume hour */
+       hour = atoi(val);
 
        /* Colon separating hour from minute... */
-       token = next_token (&val, (unsigned *)0, cfile);
+       token = peek_token(&val, NULL, cfile);
        if (token != COLON) {
-               parse_warn (cfile,
-                           "expected colon separating hour from minute.");
                if (token != SEMI)
-                       skip_to_semi (cfile);
-               return (TIME)0;
+                       token = next_token(&val, NULL, cfile);
+               parse_warn(cfile,
+                          "expected colon separating hour from minute.");
+               return((TIME)0);
        }
+       token = next_token(&val, NULL, cfile); /* consume colon */
 
        /* Minute... */
-       token = next_token (&val, (unsigned *)0, cfile);
+       token = peek_token(&val, NULL, cfile);
        if (token != NUMBER) {
-               parse_warn (cfile, "numeric minute expected.");
                if (token != SEMI)
-                       skip_to_semi (cfile);
-               return (TIME)0;
+                       token = next_token(&val, NULL, cfile);
+               parse_warn(cfile, "numeric minute expected.");
+               return((TIME)0);
        }
-       min = atoi (val);
+       token = next_token(&val, NULL, cfile); /* consume minute */
+       min = atoi(val);
 
        /* Colon separating minute from second... */
-       token = next_token (&val, (unsigned *)0, cfile);
+       token = peek_token(&val, NULL, cfile);
        if (token != COLON) {
-               parse_warn (cfile,
-                           "expected colon separating minute from second.");
                if (token != SEMI)
-                       skip_to_semi (cfile);
-               return (TIME)0;
+                       token = next_token(&val, NULL, cfile);
+               parse_warn(cfile,
+                          "expected colon separating minute from second.");
+               return((TIME)0);
        }
+       token = next_token(&val, NULL, cfile); /* consume colon */
 
        /* Second... */
-       token = next_token (&val, (unsigned *)0, cfile);
+       token = peek_token(&val, NULL, cfile);
        if (token != NUMBER) {
-               parse_warn (cfile, "numeric second expected.");
                if (token != SEMI)
-                       skip_to_semi (cfile);
-               return (TIME)0;
+                       token = next_token(&val, NULL, cfile);
+               parse_warn(cfile, "numeric second expected.");
+               return((TIME)0);
        }
-       sec = atoi (val);
+       token = next_token(&val, NULL, cfile); /* consume second */
+       sec = atoi(val);
 
-       token = peek_token (&val, (unsigned *)0, cfile);
+       tzoff = 0;
+       token = peek_token(&val, NULL, cfile);
        if (token == NUMBER) {
-               token = next_token (&val, (unsigned *)0, cfile);
-               tzoff = atoi (val);
-       } else
-               tzoff = 0;
+               token = next_token(&val, NULL, cfile); /* consume tzoff */
+               tzoff = atoi(val);
+       } else if (token != SEMI) {
+               token = next_token(&val, NULL, cfile);
+               parse_warn(cfile,
+                          "Time zone offset or semicolon expected.");
+               return((TIME)0);
+       }
 
        /* Guess the time value... */
        guess = ((((((365 * (year - 70) +       /* Days in years since '70 */
@@ -1082,21 +1100,25 @@ parse_date_core(cfile)
           is reread), the error could accumulate into something
           significant. */
 
-       return guess;
+       return((TIME)guess);
 }
 
-/* Wrapper to consume the semicolon after the date */
+/*
+ * Wrapper to consume the semicolon after the date
+ * :== date semi
+ */
+
 TIME 
 parse_date(cfile)
        struct parse *cfile;
 {
-       int guess;
+       TIME guess;
        guess = parse_date_core(cfile);
 
        /* Make sure the date ends in a semicolon... */
        if (!parse_semi(cfile))
-               return 0;
-       return guess;
+              return((TIME)0);
+       return(guess);
 }