From c0aebb4b3b38caca64ae190f1d523edf46f03969 Mon Sep 17 00:00:00 2001 From: Douglas Christman Date: Tue, 20 Dec 2016 16:42:12 -0500 Subject: calendarspec: improve overflow handling Check if the parsed seconds value fits in an integer *after* multiplying by USEC_PER_SEC, otherwise a large value can trigger modulo by zero during normalization. --- src/basic/calendarspec.c | 13 +++++++------ src/test/test-calendarspec.c | 2 ++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c index 3e249505a5..1b1acd3e0b 100644 --- a/src/basic/calendarspec.c +++ b/src/basic/calendarspec.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -96,7 +97,7 @@ static void normalize_chain(CalendarComponent **c) { * While we're counting the chain, also normalize `stop` * so the length of the range is a multiple of `repeat` */ - if (i->stop > i->start) + if (i->stop > i->start && i->repeat > 0) i->stop -= (i->stop - i->start) % i->repeat; } @@ -487,7 +488,7 @@ static int parse_weekdays(const char **p, CalendarSpec *c) { } } -static int parse_component_decimal(const char **p, bool usec, unsigned long *res) { +static int parse_component_decimal(const char **p, bool usec, int *res) { unsigned long value; const char *e = NULL; char *ee = NULL; @@ -502,8 +503,6 @@ static int parse_component_decimal(const char **p, bool usec, unsigned long *res return -errno; if (ee == *p) return -EINVAL; - if ((unsigned long) (int) value != value) - return -ERANGE; e = ee; if (usec) { @@ -530,6 +529,9 @@ static int parse_component_decimal(const char **p, bool usec, unsigned long *res } finish: + if (value > INT_MAX) + return -ERANGE; + *p = e; *res = value; @@ -556,9 +558,8 @@ static int const_chain(int value, CalendarComponent **c) { } static int prepend_component(const char **p, bool usec, CalendarComponent **c) { - unsigned long start, stop = -1, repeat = 0; + int r, start, stop = -1, repeat = 0; CalendarComponent *cc; - int r; const char *e; assert(p); diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c index 5fd749a6a8..1f34a91b10 100644 --- a/src/test/test-calendarspec.c +++ b/src/test/test-calendarspec.c @@ -238,6 +238,8 @@ int main(int argc, char* argv[]) { assert_se(calendar_spec_from_string("*:05..10/6", &c) < 0); assert_se(calendar_spec_from_string("20/4:00", &c) < 0); assert_se(calendar_spec_from_string("00:00/60", &c) < 0); + assert_se(calendar_spec_from_string("00:00:2300", &c) < 0); + assert_se(calendar_spec_from_string("00:00:18446744073709551615", &c) < 0); test_timestamp(); test_hourly_bug_4031(); -- cgit v1.2.3-54-g00ecf From 60bf5836a0d0796bc4acb818826148411d4b379f Mon Sep 17 00:00:00 2001 From: Douglas Christman Date: Tue, 20 Dec 2016 16:44:01 -0500 Subject: calendarspec: minor refactoring and style fix --- src/basic/calendarspec.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c index 1b1acd3e0b..2e5622699d 100644 --- a/src/basic/calendarspec.c +++ b/src/basic/calendarspec.c @@ -510,12 +510,10 @@ static int parse_component_decimal(const char **p, bool usec, int *res) { return -ERANGE; value *= USEC_PER_SEC; - if (*e == '.') { - unsigned add; - /* This is the start of a range, not a fractional part */ - if (e[1] == '.') - goto finish; + /* One "." is a decimal point, but ".." is a range separator */ + if (e[0] == '.' && e[1] != '.') { + unsigned add; e++; r = parse_fractional_part_u(&e, 6, &add); @@ -528,7 +526,6 @@ static int parse_component_decimal(const char **p, bool usec, int *res) { } } -finish: if (value > INT_MAX) return -ERANGE; @@ -1017,8 +1014,7 @@ fail: return r; } -static int find_end_of_month(struct tm *tm, bool utc, int day) -{ +static int find_end_of_month(struct tm *tm, bool utc, int day) { struct tm t = *tm; t.tm_mon++; -- cgit v1.2.3-54-g00ecf