[gmime/gmime-2-6] Fixed parse_broken_date() to always return 0 on garbage input



commit d4724d3518f2fcfccda36a08432a058980869ead
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Sun Mar 12 08:10:45 2017 -0400

    Fixed parse_broken_date() to always return 0 on garbage input
    
    Fixes bug #779923

 gmime/gmime-utils.c |   42 +++++++++++++++++++++++++++---------------
 tests/test-mime.c   |   16 +++++++++++-----
 2 files changed, 38 insertions(+), 20 deletions(-)
---
diff --git a/gmime/gmime-utils.c b/gmime/gmime-utils.c
index 229bd9f..aec30bb 100644
--- a/gmime/gmime-utils.c
+++ b/gmime/gmime-utils.c
@@ -523,8 +523,6 @@ parse_rfc822_date (date_token *tokens, int *tzone)
        struct tm tm;
        time_t t;
        
-       g_return_val_if_fail (tokens != NULL, (time_t) 0);
-       
        token = tokens;
        
        memset ((void *) &tm, 0, sizeof (struct tm));
@@ -596,34 +594,41 @@ parse_rfc822_date (date_token *tokens, int *tzone)
 #define is_tzone_numeric(t) (((date_token_mask (t) & DATE_TOKEN_NON_TIMEZONE_NUMERIC) == 0) && 
(date_token_mask (t) & DATE_TOKEN_HAS_SIGN))
 #define is_tzone(t)         (is_tzone_alpha (t) || is_tzone_numeric (t))
 
+#define YEAR    (1 << 0)
+#define MONTH   (1 << 1)
+#define DAY     (1 << 2)
+#define WEEKDAY (1 << 3)
+#define TIME    (1 << 4)
+#define TZONE   (1 << 5)
+
 static time_t
 parse_broken_date (date_token *tokens, int *tzone)
 {
-       gboolean got_wday, got_month, got_tzone;
        int hour, min, sec, offset, n;
        date_token *token;
        struct tm tm;
        time_t t;
+       int mask;
        
        memset ((void *) &tm, 0, sizeof (struct tm));
-       got_wday = got_month = got_tzone = FALSE;
        offset = 0;
+       mask = 0;
        
        token = tokens;
        while (token) {
-               if (is_weekday (token) && !got_wday) {
+               if (is_weekday (token) && !(mask & WEEKDAY)) {
                        if ((n = get_wday (token->start, token->len)) != -1) {
                                d(printf ("weekday; "));
-                               got_wday = TRUE;
+                               mask |= WEEKDAY;
                                tm.tm_wday = n;
                                goto next;
                        }
                }
                
-               if (is_month (token) && !got_month) {
+               if (is_month (token) && !(mask & MONTH)) {
                        if ((n = get_month (token->start, token->len)) != -1) {
                                d(printf ("month; "));
-                               got_month = TRUE;
+                               mask |= MONTH;
                                tm.tm_mon = n;
                                goto next;
                        }
@@ -635,48 +640,52 @@ parse_broken_date (date_token *tokens, int *tzone)
                                tm.tm_hour = hour;
                                tm.tm_min = min;
                                tm.tm_sec = sec;
+                               mask |= TIME;
                                goto next;
                        }
                }
                
-               if (is_tzone (token) && !got_tzone) {
+               if (is_tzone (token) && !(mask & TZONE)) {
                        date_token *t = token;
                        
                        if ((n = get_tzone (&t)) != -1) {
                                d(printf ("tzone; "));
-                               got_tzone = TRUE;
+                               mask |= TZONE;
                                offset = n;
                                goto next;
                        }
                }
                
                if (is_numeric (token)) {
-                       if (token->len == 4 && !tm.tm_year) {
+                       if (token->len == 4 && !(mask & YEAR)) {
                                if ((n = get_year (token->start, token->len)) != -1) {
                                        d(printf ("year; "));
                                        tm.tm_year = n - 1900;
+                                       mask |= YEAR;
                                        goto next;
                                }
                        } else {
                                /* Note: assumes MM-DD-YY ordering if '0 < MM < 12' holds true */
-                               if (!got_month && token->next && is_numeric (token->next)) {
+                               if (!(mask & MONTH) && token->next && is_numeric (token->next)) {
                                        if ((n = decode_int (token->start, token->len)) > 12) {
                                                goto mday;
                                        } else if (n > 0) {
                                                d(printf ("mon; "));
-                                               got_month = TRUE;
                                                tm.tm_mon = n - 1;
+                                               mask |= MONTH;
                                        }
                                        goto next;
-                               } else if (!tm.tm_mday && (n = get_mday (token->start, token->len)) != -1) {
+                               } else if (!(mask & DAY) && (n = get_mday (token->start, token->len)) != -1) {
                                mday:
                                        d(printf ("mday; "));
                                        tm.tm_mday = n;
+                                       mask |= DAY;
                                        goto next;
-                               } else if (!tm.tm_year) {
+                               } else if (!(mask & YEAR)) {
                                        if ((n = get_year (token->start, token->len)) != -1) {
                                                d(printf ("2-digit year; "));
                                                tm.tm_year = n - 1900;
+                                               mask |= YEAR;
                                        }
                                        goto next;
                                }
@@ -692,6 +701,9 @@ parse_broken_date (date_token *tokens, int *tzone)
        
        d(printf ("\n"));
        
+       if (!(mask & (YEAR | MONTH | DAY | TIME)))
+               return 0;
+       
        t = mktime_utc (&tm);
        
        /* t is now GMT of the time we want, but not offset by the timezone ... */
diff --git a/tests/test-mime.c b/tests/test-mime.c
index 98ecc21..cabec07 100644
--- a/tests/test-mime.c
+++ b/tests/test-mime.c
@@ -320,18 +320,21 @@ static struct {
        { "17-6-2008 17:10:08",
          "Tue, 17 Jun 2008 17:10:08 +0000",
          1213722608, 0 },
+       { "nonsense",
+         "Thu, 01 Jan 1970 00:00:00 +0000",
+         0, 0 }
 };
 
 static void
 test_date_parser (void)
 {
+       Exception *ex;
        time_t date;
        int tzone;
        char *buf;
        guint i;
        
        for (i = 0; i < G_N_ELEMENTS (dates); i++) {
-               buf = NULL;
                testsuite_check ("Date: '%s'", dates[i].in);
                try {
                        date = g_mime_utils_header_decode_date (dates[i].in, &tzone);
@@ -343,16 +346,19 @@ test_date_parser (void)
                                throw (exception_new ("timezones do not match"));
                        
                        buf = g_mime_utils_header_format_date (date, tzone);
-                       if (strcmp (dates[i].out, buf) != 0)
-                               throw (exception_new ("date strings do not match"));
+                       if (strcmp (dates[i].out, buf) != 0) {
+                               ex = exception_new ("date strings do not match: %s", buf);
+                               g_free (buf);
+                               throw (ex);
+                       }
+                       
+                       g_free (buf);
                        
                        testsuite_check_passed ();
                } catch (ex) {
                        testsuite_check_failed ("Date: '%s': %s", dates[i].in,
                                                ex->message);
                } finally;
-               
-               g_free (buf);
        }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]