From 16b811d4ac38358ee5656fbe74f3eeac9755dbe0 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 7 Apr 2008 20:20:13 +0200 Subject: [PATCH] Work around strptime() lossage Some losing implementations of strptime() such as FreeBSD's happily succeed when they fully consumed the first argument, regardless of whether they matched the full second argument or not. This causes lines without directives to be interpreted as "next Sunday". Work around the lossage in parse_time(). --- src/lib/common/rdsched.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/lib/common/rdsched.c b/src/lib/common/rdsched.c index d3750901..8faf16ef 100644 --- a/src/lib/common/rdsched.c +++ b/src/lib/common/rdsched.c @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -169,9 +170,17 @@ static char * parse_time(time_t *t, char *s, time_t *anchor) { static char *fmt[] = { + /* + * Absolute time formats + * Must set tm_year, tm_mon, tm_mday, tm_hour, tm_min. + */ "%Y-%m-%d %H:%M ", /* ISO 8601 */ "%b %d %H:%M %Y ", /* like ctime(): Dec 22 15:35 2006 */ - "%d %b %Y %H:%M ", /* 22 Dec 2006 15:35 */ + "%d %b %Y %H:%M ", /* like RFC 2822: 22 Dec 2006 15:35 */ + /* + * Relative to anchor formats + * Must set tm_wday, may set tm_hour and tm_min + */ "next %a %H:%M ", /* next Fri 15:35 */ "next %a ", /* next Fri */ NULL @@ -185,10 +194,26 @@ parse_time(time_t *t, char *s, time_t *anchor) for (i = 0; ; i++) { if (!fmt[i]) return NULL; + /* + * Carefully initialize tm so we can tell what strptime() + * actually set. + * + * Beware: some losing implementations of strptime() happily + * succeed when they fully consumed the first argument, + * regardless of whether they matched the full second argument + * or not. Observed on FreeBSD 6.2. + */ memset(&tm, 0, sizeof(tm)); - tm.tm_hour = -1; + tm.tm_hour = -1; /* to recognize anchor-relat. w/o time */ + tm.tm_year = INT_MIN; /* strptime() lossage work-around */ + tm.tm_mon = tm.tm_mday = tm.tm_min = tm.tm_wday = -1; /* ditto */ endp = strptime(p, fmt[i], &tm); - if (endp) + if (endp + /* strptime() lossage work-around: */ + && ((tm.tm_year != INT_MIN && tm.tm_mon != -1 + && tm.tm_mday != -1 && tm.tm_hour != -1 && tm.tm_min != -1) + || (tm.tm_wday != -1 + && (tm.tm_hour == -1 || tm.tm_min != -1)))) break; }