2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-22 18:07:25 +00:00

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]
This commit is contained in:
Shawn Routhier 2010-09-13 19:23:28 +00:00
parent 8bd445a1c1
commit 83d409ae59
2 changed files with 108 additions and 82 deletions

View File

@ -103,6 +103,10 @@ work on other platforms. Please report any problems and suggested fixes to
- Two identical log messages for commit_leases() have been disambiguated. - Two identical log messages for commit_leases() have been disambiguated.
[ISC-Bugs #18915] [ISC-Bugs #18915]
- 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.0b2 Changes since 4.2.0b2
- Add declaration for variable in debug code in alloc.c. [ISC-Bugs #21472] - Add declaration for variable in debug code in alloc.c. [ISC-Bugs #21472]

View File

@ -889,9 +889,10 @@ void convert_num (cfile, buf, str, base, size)
/* /*
* date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER * 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 NUMBER SLASH NUMBER SLASH NUMBER
* NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI | * NUMBER COLON NUMBER COLON NUMBER NUMBER |
* EPOCH NUMBER |
* NEVER * NEVER
* *
* Dates are stored in UTC or with a timezone offset; first number is day * 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. * optional.
*/ */
/* just parse the date */ /*
* just parse the date
* any trailing semi must be consumed by the caller of this routine
*/
TIME TIME
parse_date_core(cfile) parse_date_core(cfile)
struct parse *cfile; struct parse *cfile;
@ -909,157 +913,171 @@ parse_date_core(cfile)
int tzoff, wday, year, mon, mday, hour, min, sec; int tzoff, wday, year, mon, mday, hour, min, sec;
const char *val; const char *val;
enum dhcp_token token; enum dhcp_token token;
static int months [11] = { 31, 59, 90, 120, 151, 181, static int months[11] = { 31, 59, 90, 120, 151, 181,
212, 243, 273, 304, 334 }; 212, 243, 273, 304, 334 };
/* Day of week, or "never"... */ /* "never", "epoch" or day of week */
token = next_token (&val, (unsigned *)0, cfile); token = peek_token(&val, NULL, cfile);
if (token == NEVER) { if (token == NEVER) {
if (!parse_semi (cfile)) token = next_token(&val, NULL, cfile); /* consume NEVER */
return 0; return(MAX_TIME);
return MAX_TIME;
} }
/* This indicates 'local' time format. */ /* This indicates 'local' time format. */
if (token == EPOCH) { 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) { if (token != NUMBER) {
parse_warn(cfile, "Seconds since epoch expected.");
if (token != SEMI) if (token != SEMI)
skip_to_semi(cfile); token = next_token(&val, NULL, cfile);
return (TIME)0; parse_warn(cfile, "Seconds since epoch expected.");
return((TIME)0);
} }
token = next_token(&val, NULL, cfile); /* consume number */
guess = atoi(val); guess = atoi(val);
if (!parse_semi(cfile)) return((TIME)guess);
return (TIME)0;
return guess;
} }
if (token != NUMBER) { if (token != NUMBER) {
parse_warn (cfile, "numeric day of week expected.");
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); token = next_token(&val, NULL, cfile);
return (TIME)0; 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... */ /* Year... */
token = next_token (&val, (unsigned *)0, cfile); token = peek_token(&val, NULL, cfile);
if (token != NUMBER) { if (token != NUMBER) {
parse_warn (cfile, "numeric year expected.");
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); token = next_token(&val, NULL, cfile);
return (TIME)0; 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 /* 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 somebody invents a time machine, I think we can safely disregard
it. This actually works around a stupid Y2K bug that was present it. This actually works around a stupid Y2K bug that was present
in a very early beta release of dhcpd. */ in a very early beta release of dhcpd. */
year = atoi (val); year = atoi(val);
if (year > 1900) if (year > 1900)
year -= 1900; year -= 1900;
/* Slash separating year from month... */ /* Slash separating year from month... */
token = next_token (&val, (unsigned *)0, cfile); token = peek_token(&val, NULL, cfile);
if (token != SLASH) { if (token != SLASH) {
parse_warn (cfile,
"expected slash separating year from month.");
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); token = next_token(&val, NULL, cfile);
return (TIME)0; parse_warn(cfile,
"expected slash separating year from month.");
return((TIME)0);
} }
token = next_token(&val, NULL, cfile); /* consume SLASH */
/* Month... */ /* Month... */
token = next_token (&val, (unsigned *)0, cfile); token = peek_token(&val, NULL, cfile);
if (token != NUMBER) { if (token != NUMBER) {
parse_warn (cfile, "numeric month expected.");
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); token = next_token(&val, NULL, cfile);
return (TIME)0; 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... */ /* Slash separating month from day... */
token = next_token (&val, (unsigned *)0, cfile); token = peek_token(&val, NULL, cfile);
if (token != SLASH) { if (token != SLASH) {
parse_warn (cfile,
"expected slash separating month from day.");
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); token = next_token(&val, NULL, cfile);
return (TIME)0; parse_warn(cfile,
"expected slash separating month from day.");
return((TIME)0);
} }
token = next_token(&val, NULL, cfile); /* consume SLASH */
/* Day of month... */ /* Day of month... */
token = next_token (&val, (unsigned *)0, cfile); token = peek_token(&val, NULL, cfile);
if (token != NUMBER) { if (token != NUMBER) {
parse_warn (cfile, "numeric day of month expected.");
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); token = next_token(&val, NULL, cfile);
return (TIME)0; 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... */ /* Hour... */
token = next_token (&val, (unsigned *)0, cfile); token = peek_token(&val, NULL, cfile);
if (token != NUMBER) { if (token != NUMBER) {
parse_warn (cfile, "numeric hour expected.");
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); token = next_token(&val, NULL, cfile);
return (TIME)0; 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... */ /* Colon separating hour from minute... */
token = next_token (&val, (unsigned *)0, cfile); token = peek_token(&val, NULL, cfile);
if (token != COLON) { if (token != COLON) {
parse_warn (cfile,
"expected colon separating hour from minute.");
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); token = next_token(&val, NULL, cfile);
return (TIME)0; parse_warn(cfile,
"expected colon separating hour from minute.");
return((TIME)0);
} }
token = next_token(&val, NULL, cfile); /* consume colon */
/* Minute... */ /* Minute... */
token = next_token (&val, (unsigned *)0, cfile); token = peek_token(&val, NULL, cfile);
if (token != NUMBER) { if (token != NUMBER) {
parse_warn (cfile, "numeric minute expected.");
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); token = next_token(&val, NULL, cfile);
return (TIME)0; 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... */ /* Colon separating minute from second... */
token = next_token (&val, (unsigned *)0, cfile); token = peek_token(&val, NULL, cfile);
if (token != COLON) { if (token != COLON) {
parse_warn (cfile,
"expected colon separating minute from second.");
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); token = next_token(&val, NULL, cfile);
return (TIME)0; parse_warn(cfile,
"expected colon separating minute from second.");
return((TIME)0);
} }
token = next_token(&val, NULL, cfile); /* consume colon */
/* Second... */ /* Second... */
token = next_token (&val, (unsigned *)0, cfile); token = peek_token(&val, NULL, cfile);
if (token != NUMBER) { if (token != NUMBER) {
parse_warn (cfile, "numeric second expected.");
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); token = next_token(&val, NULL, cfile);
return (TIME)0; 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) { if (token == NUMBER) {
token = next_token (&val, (unsigned *)0, cfile); token = next_token(&val, NULL, cfile); /* consume tzoff */
tzoff = atoi (val); tzoff = atoi(val);
} else } else if (token != SEMI) {
tzoff = 0; token = next_token(&val, NULL, cfile);
parse_warn(cfile,
"Time zone offset or semicolon expected.");
return((TIME)0);
}
/* Guess the time value... */ /* Guess the time value... */
guess = ((((((365 * (year - 70) + /* Days in years since '70 */ 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 is reread), the error could accumulate into something
significant. */ 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 TIME
parse_date(cfile) parse_date(cfile)
struct parse *cfile; struct parse *cfile;
{ {
int guess; TIME guess;
guess = parse_date_core(cfile); guess = parse_date_core(cfile);
/* Make sure the date ends in a semicolon... */ /* Make sure the date ends in a semicolon... */
if (!parse_semi(cfile)) if (!parse_semi(cfile))
return 0; return((TIME)0);
return guess; return(guess);
} }