From b26756f88d338174cdada0b618a657ada0bd3819 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Thu, 15 May 2025 07:59:14 +0200 Subject: [PATCH] soup-date-utils: Add value checks for date/time parsing Reject date/time when it does not represent a valid value. Closes https://gitlab.gnome.org/GNOME/libsoup/-/issues/448 --- libsoup/soup-date-utils.c | 23 +++++++++++++++-------- tests/cookies-test.c | 10 ++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/libsoup/soup-date-utils.c b/libsoup/soup-date-utils.c index fd785f509..34ca99503 100644 --- a/libsoup/soup-date-utils.c +++ b/libsoup/soup-date-utils.c @@ -129,7 +129,7 @@ parse_day (int *day, const char **date_string) while (*end == ' ' || *end == '-') end++; *date_string = end; - return TRUE; + return *day >= 1 && *day <= 31; } static inline gboolean @@ -169,7 +169,7 @@ parse_year (int *year, const char **date_string) while (*end == ' ' || *end == '-') end++; *date_string = end; - return TRUE; + return *year > 0 && *year < 9999; } static inline gboolean @@ -193,7 +193,7 @@ parse_time (int *hour, int *minute, int *second, const char **date_string) while (*p == ' ') p++; *date_string = p; - return TRUE; + return *hour >= 0 && *hour < 24 && *minute >= 0 && *minute < 60 && *second >= 0 && *second < 60; } static inline gboolean @@ -209,9 +209,14 @@ parse_timezone (GTimeZone **timezone, const char **date_string) gulong val; int sign = (**date_string == '+') ? 1 : -1; val = strtoul (*date_string + 1, (char **)date_string, 10); - if (**date_string == ':') - val = 60 * val + strtoul (*date_string + 1, (char **)date_string, 10); - else + if (val > 9999) + return FALSE; + if (**date_string == ':') { + gulong val2 = strtoul (*date_string + 1, (char **)date_string, 10); + if (val > 99 || val2 > 99) + return FALSE; + val = 60 * val + val2; + } else val = 60 * (val / 100) + (val % 100); offset_minutes = sign * val; utc = (sign == -1) && !val; @@ -264,7 +269,8 @@ parse_textual_date (const char *date_string) if (!parse_month (&month, &date_string) || !parse_day (&day, &date_string) || !parse_time (&hour, &minute, &second, &date_string) || - !parse_year (&year, &date_string)) + !parse_year (&year, &date_string) || + !g_date_valid_dmy (day, month, year)) return NULL; /* There shouldn't be a timezone, but check anyway */ @@ -276,7 +282,8 @@ parse_textual_date (const char *date_string) if (!parse_day (&day, &date_string) || !parse_month (&month, &date_string) || !parse_year (&year, &date_string) || - !parse_time (&hour, &minute, &second, &date_string)) + !parse_time (&hour, &minute, &second, &date_string) || + !g_date_valid_dmy (day, month, year)) return NULL; /* This time there *should* be a timezone, but we diff --git a/tests/cookies-test.c b/tests/cookies-test.c index 1d2d45630..ff809a400 100644 --- a/tests/cookies-test.c +++ b/tests/cookies-test.c @@ -460,6 +460,15 @@ do_cookies_parsing_max_age_long_overflow (void) soup_cookie_free (cookie); } +static void +do_cookies_parsing_int32_overflow (void) +{ + SoupCookie *cookie = soup_cookie_parse ("Age=1;expires=3Mar9 999:9:9+ 999999999-age=main=gne=", NULL); + g_assert_nonnull (cookie); + g_assert_null (soup_cookie_get_expires (cookie)); + soup_cookie_free (cookie); +} + static void do_cookies_equal_nullpath (void) { @@ -718,6 +727,7 @@ main (int argc, char **argv) g_test_add_func ("/cookies/parsing/no-path-null-origin", do_cookies_parsing_nopath_nullorigin); g_test_add_func ("/cookies/parsing/max-age-int32-overflow", do_cookies_parsing_max_age_int32_overflow); g_test_add_func ("/cookies/parsing/max-age-long-overflow", do_cookies_parsing_max_age_long_overflow); + g_test_add_func ("/cookies/parsing/int32-overflow", do_cookies_parsing_int32_overflow); g_test_add_func ("/cookies/parsing/equal-nullpath", do_cookies_equal_nullpath); g_test_add_func ("/cookies/parsing/control-characters", do_cookies_parsing_control_characters); g_test_add_func ("/cookies/parsing/name-value-max-size", do_cookies_parsing_name_value_max_size); -- GitLab