tvbuff: Fix RFC 822 and 1123 date parsing with non-English locales
Avoid relying on strptime to parse the day of week (%a) and month name (%b) since these are locale-dependent. Fixes test suite failures with tvb.lua and LC_ALL=nl_NL.UTF-8. Additionally it will now reject four-digit years when using ENC_RFC_822 as that requires two digit years. The only user of this API seems to be the Lua tests though, so this should not make much of a difference. Bug: 15437 Change-Id: I75436b93faab23869794d9756b9c3ce6128dd1f4 Reviewed-on: https://code.wireshark.org/review/31698 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot Reviewed-by: Peter Wu <peter@lekensteyn.nl>
This commit is contained in:
parent
4f8b3f3d2a
commit
044a9deeca
|
@ -1648,6 +1648,20 @@ tvb_get_string_bytes(tvbuff_t *tvb, const gint offset, const gint length,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
parse_month_name(const char *name, int *tm_mon)
|
||||||
|
{
|
||||||
|
static const char months[][4] = { "Jan", "Feb", "Mar", "Apr", "May",
|
||||||
|
"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
if (memcmp(months[i], name, 4) == 0) {
|
||||||
|
*tm_mon = i;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* support hex-encoded time values? */
|
/* support hex-encoded time values? */
|
||||||
nstime_t*
|
nstime_t*
|
||||||
tvb_get_string_time(tvbuff_t *tvb, const gint offset, const gint length,
|
tvb_get_string_time(tvbuff_t *tvb, const gint offset, const gint length,
|
||||||
|
@ -1791,19 +1805,42 @@ tvb_get_string_time(tvbuff_t *tvb, const gint offset, const gint length,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (encoding & ENC_RFC_822 || encoding & ENC_RFC_1123) {
|
else if (encoding & ENC_RFC_822 || encoding & ENC_RFC_1123) {
|
||||||
if (encoding & ENC_RFC_822) {
|
/*
|
||||||
/* this will unfortunately match ENC_RFC_1123 style
|
* Match [dow,] day month year hh:mm[:ss] with two-digit
|
||||||
strings too, partially - probably need to do this the long way */
|
* years (RFC 822) or four-digit years (RFC 1123). Skip
|
||||||
end = strptime(ptr, "%a, %d %b %y %H:%M:%S", &tm);
|
* the day of week since it is locale dependent and does
|
||||||
if (!end) end = strptime(ptr, "%a, %d %b %y %H:%M", &tm);
|
* not affect the resulting date anyway.
|
||||||
if (!end) end = strptime(ptr, "%d %b %y %H:%M:%S", &tm);
|
*/
|
||||||
if (!end) end = strptime(ptr, "%d %b %y %H:%M", &tm);
|
if (g_ascii_isalpha(ptr[0]) && g_ascii_isalpha(ptr[1]) && g_ascii_isalpha(ptr[2]) && ptr[3] == ',')
|
||||||
}
|
ptr += 4; /* Skip day of week. */
|
||||||
else if (encoding & ENC_RFC_1123) {
|
char month_name[4] = { 0 };
|
||||||
end = strptime(ptr, "%a, %d %b %Y %H:%M:%S", &tm);
|
if (sscanf(ptr, "%d %3s %d %d:%d%n:%d%n",
|
||||||
if (!end) end = strptime(ptr, "%a, %d %b %Y %H:%M", &tm);
|
&tm.tm_mday,
|
||||||
if (!end) end = strptime(ptr, "%d %b %Y %H:%M:%S", &tm);
|
month_name,
|
||||||
if (!end) end = strptime(ptr, "%d %b %Y %H:%M", &tm);
|
&tm.tm_year,
|
||||||
|
&tm.tm_hour,
|
||||||
|
&tm.tm_min,
|
||||||
|
&num_chars,
|
||||||
|
&tm.tm_sec,
|
||||||
|
&num_chars) >= 5)
|
||||||
|
{
|
||||||
|
if (encoding & ENC_RFC_822) {
|
||||||
|
/* Match strptime behavior: years 00-68
|
||||||
|
* are in the 21th century. */
|
||||||
|
if (tm.tm_year <= 68) {
|
||||||
|
tm.tm_year += 100;
|
||||||
|
matched = TRUE;
|
||||||
|
} else if (tm.tm_year <= 99) {
|
||||||
|
matched = TRUE;
|
||||||
|
}
|
||||||
|
} else if (encoding & ENC_RFC_1123) {
|
||||||
|
tm.tm_year -= 1900;
|
||||||
|
matched = TRUE;
|
||||||
|
}
|
||||||
|
if (!parse_month_name(month_name, &tm.tm_mon))
|
||||||
|
matched = FALSE;
|
||||||
|
if (matched)
|
||||||
|
end = ptr + num_chars;
|
||||||
}
|
}
|
||||||
if (end) {
|
if (end) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
Loading…
Reference in New Issue