From d0d9c3d71e1fb88557d684c59cf8a920712b16f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20Manchado=20Vel=C3=A1zquez?= Date: Mon, 20 Feb 2012 17:40:37 +0100 Subject: [PATCH 1/6] Fix parse_http_time and add tests * It seems parse_http_time wasn't parsing correctly any date with commas (RFCs 1123 and 850). Fix that. * It seems parse_http_time was reporting the wrong month (they start at 0, not 1). Fix that. * Add some tests for parse_http_time, covering all three formats. --- src/common/util.c | 8 ++++---- src/test/test_util.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/common/util.c b/src/common/util.c index 7d2fc4dea8..391b02f34b 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1416,13 +1416,13 @@ parse_http_time(const char *date, struct tm *tm) /* First, try RFC1123 or RFC850 format: skip the weekday. */ if ((cp = strchr(date, ','))) { - ++cp; - if (tor_sscanf(date, "%2u %3s %4u %2u:%2u:%2u GMT", + cp += 2; + if (tor_sscanf(cp, "%2u %3s %4u %2u:%2u:%2u GMT", &tm_mday, month, &tm_year, &tm_hour, &tm_min, &tm_sec) == 6) { /* rfc1123-date */ tm_year -= 1900; - } else if (tor_sscanf(date, "%2u-%3s-%2u %2u:%2u:%2u GMT", + } else if (tor_sscanf(cp, "%2u-%3s-%2u %2u:%2u:%2u GMT", &tm_mday, month, &tm_year, &tm_hour, &tm_min, &tm_sec) == 6) { /* rfc850-date */ @@ -1449,7 +1449,7 @@ parse_http_time(const char *date, struct tm *tm) /* Okay, now decode the month. */ for (i = 0; i < 12; ++i) { if (!strcasecmp(MONTH_NAMES[i], month)) { - tm->tm_mon = i+1; + tm->tm_mon = i; } } diff --git a/src/test/test_util.c b/src/test/test_util.c index ee745c5cf0..5845d779be 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -86,6 +86,53 @@ test_util_time(void) ; } +static void +test_util_parse_http_time(void *arg) +{ + struct tm a_time; + + (void)arg; + + /* Test parse_http_time */ + + test_eq(-1, parse_http_time("", &a_time)); + test_eq(-1, parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time)); + test_eq(-1, parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time)); + test_eq(-1, parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time)); + test_eq(-1, parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time)); + test_eq(-1, parse_http_time("Sunday, August the third", &a_time)); + + test_eq(0, parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time)); + test_eq((time_t)775961302UL, tor_timegm(&a_time)); + test_eq(0, parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time)); + test_eq((time_t)775961302UL, tor_timegm(&a_time)); + test_eq(0, parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time)); + test_eq((time_t)775961302UL, tor_timegm(&a_time)); + test_eq(0, parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time)); + test_eq((time_t)775961302UL, tor_timegm(&a_time)); + test_eq(0, parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time)); + test_eq((time_t)775961302UL, tor_timegm(&a_time)); + test_eq(0, parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time)); + test_eq((time_t)775961302UL, tor_timegm(&a_time)); + test_eq(0, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time)); + test_eq((time_t)775961302UL, tor_timegm(&a_time)); + test_eq(0, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time)); + test_eq((time_t)775961302UL, tor_timegm(&a_time)); + test_eq(0, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time)); + test_eq((time_t)775961302UL, tor_timegm(&a_time)); + test_eq(-1, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time)); + test_eq(-1, parse_http_time("2011-03-32 00:00:00 GMT", &a_time)); + test_eq(-1, parse_http_time("2011-03-30 24:00:00 GMT", &a_time)); + test_eq(-1, parse_http_time("2011-03-30 23:60:00 GMT", &a_time)); + test_eq(-1, parse_http_time("2011-03-30 23:59:62 GMT", &a_time)); + test_eq(-1, parse_http_time("1969-03-30 23:59:59 GMT", &a_time)); + test_eq(-1, parse_http_time("2011-00-30 23:59:59 GMT", &a_time)); + test_eq(-1, parse_http_time("2011-03-30 23:59", &a_time)); + + done: + ; +} + static void test_util_config_line(void) { @@ -1314,6 +1361,7 @@ test_util_di_ops(void) struct testcase_t util_tests[] = { UTIL_LEGACY(time), + UTIL_TEST(parse_http_time, 0), UTIL_LEGACY(config_line), UTIL_LEGACY(strmisc), UTIL_LEGACY(pow2), From 1abe533b3304619bd8c59f170097ab469af99dc9 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 8 Mar 2012 21:09:34 -0500 Subject: [PATCH 2/6] Reject an additional type of bad date in parse_http_time --- src/common/util.c | 5 ++++- src/test/test_util.c | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/common/util.c b/src/common/util.c index 391b02f34b..c44fe601e7 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1416,7 +1416,10 @@ parse_http_time(const char *date, struct tm *tm) /* First, try RFC1123 or RFC850 format: skip the weekday. */ if ((cp = strchr(date, ','))) { - cp += 2; + ++cp; + if (*cp != ' ') + return -1; + ++cp; if (tor_sscanf(cp, "%2u %3s %4u %2u:%2u:%2u GMT", &tm_mday, month, &tm_year, &tm_hour, &tm_min, &tm_sec) == 6) { diff --git a/src/test/test_util.c b/src/test/test_util.c index 5845d779be..e239326a2d 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -101,6 +101,7 @@ test_util_parse_http_time(void *arg) test_eq(-1, parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time)); test_eq(-1, parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time)); test_eq(-1, parse_http_time("Sunday, August the third", &a_time)); + test_eq(-1, parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time)); test_eq(0, parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time)); test_eq((time_t)775961302UL, tor_timegm(&a_time)); From 7ae798ac3850008942472a0e9ad4f0c691433c8a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 8 Mar 2012 21:26:48 -0500 Subject: [PATCH 3/6] changes file for branch bug5346 --- changes/bug5346 | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 changes/bug5346 diff --git a/changes/bug5346 b/changes/bug5346 new file mode 100644 index 0000000000..490eb35efe --- /dev/null +++ b/changes/bug5346 @@ -0,0 +1,6 @@ + o Minor bugfixes: + - Correct parsing of certain date types in parse_http_time(). + Without this patch, If-Modified-Since would behave + incorrectly. Fix for bug 5346; bugfix on 0.2.0.2-alpha. Patch from + Esteban Manchado Velázques. + From 801923ac2112d1a54eaf4126800724bea90055eb Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 9 Mar 2012 10:24:40 -0500 Subject: [PATCH 4/6] Remove more dubiosity in struct tm handling. related to bug5346 --- changes/bug5346 | 2 ++ src/common/util.c | 15 ++++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/changes/bug5346 b/changes/bug5346 index 490eb35efe..3d21f90144 100644 --- a/changes/bug5346 +++ b/changes/bug5346 @@ -3,4 +3,6 @@ Without this patch, If-Modified-Since would behave incorrectly. Fix for bug 5346; bugfix on 0.2.0.2-alpha. Patch from Esteban Manchado Velázques. + - Reject out-of-range times like 23:59:61. Fix for bug 5346; + bugfix on 0.0.8pre3. diff --git a/src/common/util.c b/src/common/util.c index c44fe601e7..5fa0896ae5 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1268,7 +1268,7 @@ format_rfc1123_time(char *buf, time_t t) tor_assert(tm.tm_wday >= 0); tor_assert(tm.tm_wday <= 6); memcpy(buf, WEEKDAY_NAMES[tm.tm_wday], 3); - tor_assert(tm.tm_wday >= 0); + tor_assert(tm.tm_mon >= 0); tor_assert(tm.tm_mon <= 11); memcpy(buf+8, MONTH_NAMES[tm.tm_mon], 3); } @@ -1298,7 +1298,8 @@ parse_rfc1123_time(const char *buf, time_t *t) tor_free(esc); return -1; } - if (tm_mday > 31 || tm_hour > 23 || tm_min > 59 || tm_sec > 61) { + if (tm_mday < 1 || tm_mday > 31 || tm_hour > 23 || tm_min > 59 || + tm_sec > 60) { char *esc = esc_for_log(buf); log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc); tor_free(esc); @@ -1368,7 +1369,7 @@ int parse_iso_time(const char *cp, time_t *t) { struct tm st_tm; - unsigned int year=0, month=0, day=0, hour=100, minute=100, second=100; + unsigned int year=0, month=0, day=0, hour=0, minute=0, second=0; if (tor_sscanf(cp, "%u-%2u-%2u %2u:%2u:%2u", &year, &month, &day, &hour, &minute, &second) < 6) { char *esc = esc_for_log(cp); @@ -1377,7 +1378,7 @@ parse_iso_time(const char *cp, time_t *t) return -1; } if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || - hour > 23 || minute > 59 || second > 61) { + hour > 23 || minute > 59 || second > 60) { char *esc = esc_for_log(cp); log_warn(LD_GENERAL, "ISO time %s was nonsensical", esc); tor_free(esc); @@ -1457,11 +1458,11 @@ parse_http_time(const char *date, struct tm *tm) } if (tm->tm_year < 0 || - tm->tm_mon < 1 || tm->tm_mon > 12 || - tm->tm_mday < 0 || tm->tm_mday > 31 || + tm->tm_mon < 0 || tm->tm_mon > 11 || + tm->tm_mday < 1 || tm->tm_mday > 31 || tm->tm_hour < 0 || tm->tm_hour > 23 || tm->tm_min < 0 || tm->tm_min > 59 || - tm->tm_sec < 0 || tm->tm_sec > 61) + tm->tm_sec < 0 || tm->tm_sec > 60) return -1; /* Out of range, or bad month. */ return 0; From 679aa93e23f2c7f2e9c195f08834a7fc8c8d8b29 Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Fri, 9 Mar 2012 15:40:44 +0100 Subject: [PATCH 5/6] Fix month check in parse_http_time, add test --- src/common/util.c | 2 ++ src/test/test_util.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/common/util.c b/src/common/util.c index 5fa0896ae5..a03a576321 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1451,6 +1451,8 @@ parse_http_time(const char *date, struct tm *tm) month[3] = '\0'; /* Okay, now decode the month. */ + /* set tm->tm_mon to dummy value so the check below fails. */ + tm->tm_mon = -1; for (i = 0; i < 12; ++i) { if (!strcasecmp(MONTH_NAMES[i], month)) { tm->tm_mon = i; diff --git a/src/test/test_util.c b/src/test/test_util.c index e239326a2d..cc0181c92f 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -121,6 +121,10 @@ test_util_parse_http_time(void *arg) test_eq((time_t)775961302UL, tor_timegm(&a_time)); test_eq(0, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time)); test_eq((time_t)775961302UL, tor_timegm(&a_time)); + test_eq(0, parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time)); + test_eq((time_t)1325376000UL, tor_timegm(&a_time)); + test_eq(0, parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time)); + test_eq((time_t)1356912000UL, tor_timegm(&a_time)); test_eq(-1, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time)); test_eq(-1, parse_http_time("2011-03-32 00:00:00 GMT", &a_time)); test_eq(-1, parse_http_time("2011-03-30 24:00:00 GMT", &a_time)); From 75fc4dbbcabaedc715f0f9e883ccab1c9634e787 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 16 May 2012 12:19:56 -0400 Subject: [PATCH 6/6] Make the succeeding parse_http_time tests more obviously right (When the correct answer is given in terms of seconds since the epoch, it's hard to be sure that it really is the right answer just by reading the code.) --- src/test/test_util.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/test/test_util.c b/src/test/test_util.c index cc0181c92f..f9a83a38a5 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -90,9 +90,15 @@ static void test_util_parse_http_time(void *arg) { struct tm a_time; - + char b[ISO_TIME_LEN+1]; (void)arg; +#define T(s) do { \ + format_iso_time(b, tor_timegm(&a_time)); \ + tt_str_op(b, ==, (s)); \ + b[0]='\0'; \ + } while (0) + /* Test parse_http_time */ test_eq(-1, parse_http_time("", &a_time)); @@ -105,26 +111,37 @@ test_util_parse_http_time(void *arg) test_eq(0, parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time)); test_eq((time_t)775961302UL, tor_timegm(&a_time)); + T("1994-08-04 00:48:22"); test_eq(0, parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time)); test_eq((time_t)775961302UL, tor_timegm(&a_time)); + T("1994-08-04 00:48:22"); test_eq(0, parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time)); test_eq((time_t)775961302UL, tor_timegm(&a_time)); + T("1994-08-04 00:48:22"); test_eq(0, parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time)); test_eq((time_t)775961302UL, tor_timegm(&a_time)); + T("1994-08-04 00:48:22"); test_eq(0, parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time)); test_eq((time_t)775961302UL, tor_timegm(&a_time)); + T("1994-08-04 00:48:22"); test_eq(0, parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time)); test_eq((time_t)775961302UL, tor_timegm(&a_time)); + T("1994-08-04 00:48:22"); test_eq(0, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time)); test_eq((time_t)775961302UL, tor_timegm(&a_time)); + T("1994-08-04 00:48:22"); test_eq(0, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time)); test_eq((time_t)775961302UL, tor_timegm(&a_time)); + T("1994-08-04 00:48:22"); test_eq(0, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time)); test_eq((time_t)775961302UL, tor_timegm(&a_time)); + T("1994-08-04 00:48:22"); test_eq(0, parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time)); test_eq((time_t)1325376000UL, tor_timegm(&a_time)); + T("2012-01-01 00:00:00"); test_eq(0, parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time)); test_eq((time_t)1356912000UL, tor_timegm(&a_time)); + T("2012-12-31 00:00:00"); test_eq(-1, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time)); test_eq(-1, parse_http_time("2011-03-32 00:00:00 GMT", &a_time)); test_eq(-1, parse_http_time("2011-03-30 24:00:00 GMT", &a_time)); @@ -134,6 +151,7 @@ test_util_parse_http_time(void *arg) test_eq(-1, parse_http_time("2011-00-30 23:59:59 GMT", &a_time)); test_eq(-1, parse_http_time("2011-03-30 23:59", &a_time)); +#undef T done: ; }