ftype-time: parse the month independent of the locale

Do not rely on strptime("%b") to parse the month, it does not correctly
recognize English month abbreviations on non-English systems. While at
it, do not try to parse milliseconds if seconds are missing.

Change-Id: Ia049bf362195eef1eba2f04ff7217049fa6a7d9d
Reviewed-on: https://code.wireshark.org/review/31707
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: João Valverde <j@v6e.pt>
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
This commit is contained in:
Peter Wu 2019-01-23 19:21:59 +01:00
parent 044a9deeca
commit a946eb3141
2 changed files with 50 additions and 4 deletions

View File

@ -221,20 +221,48 @@ fail:
}
/* Returns TRUE if 's' starts with an abbreviated month name. */
static gboolean
parse_month_name(const char *s, int *tm_mon)
{
const char *months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
for (int i = 0; i < 12; i++) {
if (g_ascii_strncasecmp(s, months[i], 3) == 0) {
*tm_mon = i;
return TRUE;
}
}
return FALSE;
}
static gboolean
absolute_val_from_string(fvalue_t *fv, const char *s, gchar **err_msg)
{
struct tm tm;
char *curptr;
char *curptr = NULL;
gboolean has_seconds = TRUE;
memset(&tm, 0, sizeof(tm));
curptr = strptime(s,"%b %d, %Y %H:%M:%S", &tm);
if (strlen(s) < sizeof("2000-1-1") - 1)
goto fail;
/* Do not use '%b' to parse the month name, it is locale-specific. */
if (s[3] == ' ' && parse_month_name(s, &tm.tm_mon))
curptr = strptime(s + 4, "%d, %Y %H:%M:%S", &tm);
if (curptr == NULL)
curptr = strptime(s,"%Y-%m-%dT%H:%M:%S", &tm);
if (curptr == NULL)
curptr = strptime(s,"%Y-%m-%d %H:%M:%S", &tm);
if (curptr == NULL)
if (curptr == NULL) {
has_seconds = FALSE;
curptr = strptime(s,"%Y-%m-%d %H:%M", &tm);
}
if (curptr == NULL)
curptr = strptime(s,"%Y-%m-%d %H", &tm);
if (curptr == NULL)
@ -248,7 +276,7 @@ absolute_val_from_string(fvalue_t *fv, const char *s, gchar **err_msg)
* Something came after the seconds field; it must be
* a nanoseconds field.
*/
if (*curptr != '.')
if (*curptr != '.' || !has_seconds)
goto fail; /* it's not */
curptr++; /* skip the "." */
if (!g_ascii_isdigit((unsigned char)*curptr))

View File

@ -19,6 +19,10 @@ class case_time(unittest.TestCase):
dfilter = 'frame.time == "Jan 31, 2002 13:55:31.3"'
checkDFilterCount(dfilter, 0)
def test_eq_3(self, checkDFilterCount):
dfilter = 'frame.time == "2002-12-31 13:55:31.3"'
checkDFilterCount(dfilter, 1)
def test_ne_1(self, checkDFilterCount):
dfilter = 'frame.time != "Dec 31, 2002 13:55:31.3"'
checkDFilterCount(dfilter, 0)
@ -75,3 +79,17 @@ class case_time(unittest.TestCase):
dfilter = 'frame.time <= "Dec 31, 2002 13:56:31.3"'
checkDFilterCount(dfilter, 1)
def test_bad_time_1(self, checkDFilterFail):
# No text is permitted after the time.
dfilter = 'frame.time == "Dec 31, 2002 13:56:31.3 UTC"'
checkDFilterFail(dfilter)
def test_bad_time_2(self, checkDFilterFail):
# Miliseconds can only occur after seconds.
dfilter = 'frame.time == "2002-12-31 13:55.3"'
checkDFilterFail(dfilter)
def test_bad_time_3(self, checkDFilterFail):
# Reject months in a different locale (mrt is March in nl_NL.UTF-8).
dfilter = 'frame.time == "mrt 1, 2000 00:00:00"'
checkDFilterFail(dfilter)