epan: Make hex_str_to_bytes reject an odd # of hex characters >= 3

hex_str_to_bytes currently allows an odd number of hex characters
after a separator (including no separator). It parses them in an
entirely unexpected way; taking two characters at a time to form
one byte and then using the last leftover character by itself,
thus adding a missing lead zero to the last hex character instead
of the first.

E.g., 3.109.209.43 is parsed as 0x03 0x10 0x09 0x20 0x09 0x43

Since this interpretation has never been correct, just disallow any
odd number of hex characters 3 or greater. Continue to support a
single hex character after a separator (or by itself.)

It's still probably too accepting, as it allows the separator to
change back and forth, including back and forth from no separator
when force_separators is false (thus allowing the number of hex
digits between separators to vary.)

Fix #19449. Fix #19604.
This commit is contained in:
John Thacker 2024-01-23 20:34:15 -05:00 committed by AndersBroman
parent f274be5523
commit ffcf580230
1 changed files with 17 additions and 3 deletions

View File

@ -131,6 +131,10 @@ is_byte_sep(guint8 c)
/* Turn a string of hex digits with optional separators (defined by
* is_byte_sep() into a byte array.
*
* XXX - This function is perhaps too generous in what it accepts.
* It allows the separator to change from one character to another,
* or to and from no separator if force_separators is false.
*/
gboolean
hex_str_to_bytes(const char *hex_str, GByteArray *bytes, gboolean force_separators)
@ -152,9 +156,19 @@ hex_str_to_bytes(const char *hex_str, GByteArray *bytes, gboolean force_separato
r = p+2;
s = p+3;
if (*q && *r && *s
if (*q && *r
&& g_ascii_isxdigit(*p) && g_ascii_isxdigit(*q) &&
g_ascii_isxdigit(*r) && g_ascii_isxdigit(*s)) {
g_ascii_isxdigit(*r)) {
/*
* Three hex bytes in a row, followed by a non hex byte
* (possibly the end of the string). We don't accept an
* odd number of hex digits except for single digits
* by themselves or after a separator.
*/
if (!g_ascii_isxdigit(*s)) {
return FALSE;
}
four_digits_first_half[0] = *p;
four_digits_first_half[1] = *q;
four_digits_first_half[2] = '\0';
@ -174,7 +188,7 @@ hex_str_to_bytes(const char *hex_str, GByteArray *bytes, gboolean force_separato
if (*punct) {
/*
* Make sure the character after
* the forth hex digit is a byte
* the fourth hex digit is a byte
* separator, i.e. that we don't have
* more than four hex digits, or a
* bogus character.