soup_date_new_from_string: fix an out-of-bounds memory access
authorDan Winship <danw@gnome.org>
Thu, 10 Jun 2010 00:06:51 +0000 (20:06 -0400)
committerDan Winship <danw@gnome.org>
Thu, 10 Jun 2010 00:10:59 +0000 (20:10 -0400)
soup_date_new_from_string() would sometimes read off the end of the
string, but tests/date didn't catch this even under valgrind, because
all of the strings were compile-time constants and they got laid out
in a way that never triggered a read of invalid memory. So tweak the
test to g_strdup each string before parsing it, which will let
valgrind notice if we read outside its bounds in the future.

https://bugzilla.gnome.org/show_bug.cgi?id=620288

libsoup/soup-date.c
tests/date.c

index ce99ec5..25bb761 100644 (file)
@@ -355,7 +355,10 @@ parse_time (SoupDate *date, const char **date_string)
 static inline gboolean
 parse_timezone (SoupDate *date, const char **date_string)
 {
-       if (**date_string == '+' || **date_string == '-') {
+       if (!**date_string) {
+               date->utc = FALSE;
+               date->offset = 0;
+       } else if (**date_string == '+' || **date_string == '-') {
                gulong val;
                int sign = (**date_string == '+') ? -1 : 1;
                val = strtoul (*date_string + 1, (char **)date_string, 10);
@@ -381,9 +384,6 @@ parse_timezone (SoupDate *date, const char **date_string)
                if ((*date_string)[1] == 'D')
                        date->offset += 60;
                date->utc = FALSE;
-       } else if (!**date_string) {
-               date->utc = FALSE;
-               date->offset = 0;
        } else
                return FALSE;
        return TRUE;
index 4e97d8a..aef9c66 100644 (file)
 
 static gboolean check_ok (const char *strdate, SoupDate *date);
 
+static SoupDate *
+make_date (const char *strdate)
+{
+       char *dup;
+       SoupDate *date;
+
+       /* We do it this way so that if soup_date_new_from_string()
+        * reads off the end of the string, it will trigger an error
+        * when valgrinding, rather than just reading the start of the
+        * next const string.
+        */
+       dup = g_strdup (strdate);
+       date = soup_date_new_from_string (dup);
+       g_free (dup);
+       return date;
+}
+
 static const struct {
        SoupDateFormat format;
        const char *date;
@@ -31,7 +48,7 @@ check_good (SoupDateFormat format, const char *strdate)
        SoupDate *date;
        char *strdate2;
 
-       date = soup_date_new_from_string (strdate);
+       date = make_date (strdate);
        if (date)
                strdate2 = soup_date_to_string (date, format);
        if (!check_ok (strdate, date))
@@ -282,7 +299,7 @@ check_conversion (const struct conversion *conv)
        char *str;
 
        debug_printf (2, "%s\n", conv->source);
-       date = soup_date_new_from_string (conv->source);
+       date = make_date (conv->source);
        if (!date) {
                debug_printf (1, "  date parsing failed for '%s'.\n", conv->source);
                errors++;
@@ -359,12 +376,12 @@ main (int argc, char **argv)
 
        debug_printf (1, "\nOK dates:\n");
        for (i = 0; i < G_N_ELEMENTS (ok_dates); i++)
-               check_ok (ok_dates[i], soup_date_new_from_string (ok_dates[i]));
+               check_ok (ok_dates[i], make_date (ok_dates[i]));
        check_ok (TIME_T_STRING, soup_date_new_from_time_t (TIME_T));
 
        debug_printf (1, "\nBad dates:\n");
        for (i = 0; i < G_N_ELEMENTS (bad_dates); i++)
-               check_bad (bad_dates[i], soup_date_new_from_string (bad_dates[i]));
+               check_bad (bad_dates[i], make_date (bad_dates[i]));
 
        debug_printf (1, "\nConversions:\n");
        for (i = 0; i < G_N_ELEMENTS (conversions); i++)