packet_xml: detect and handle UTF-16 BOM

In the main dissector, check the first 2/3 bytes for recognized
Byte-Order Marks (BOM) and decode if detected.

In the heuristic check, when unicode heuristics are enabled, check the
first 2 bytes for a recognized BOM instead of assuming UCS-2LE. (Still
falls back on that if no BOM detected.)

Bug: 9069
Change-Id: I7c6510221ef9257a9c3030715906e07b88af6aa7
Reviewed-on: https://code.wireshark.org/review/38076
Reviewed-by: Michael Mann <mmann78@netscape.net>
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
David Perry 2020-08-06 13:42:26 -04:00 committed by Anders Broman
parent dae7f769e8
commit 2ce378f8ab
1 changed files with 50 additions and 5 deletions

View File

@ -231,6 +231,9 @@ dissect_xml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
static GPtrArray *stack;
xml_frame_t *current_frame;
const char *colinfo_str;
tvbuff_t *decoded;
guint16 try_bom;
int start_offset = 0;
if (stack != NULL)
g_ptr_array_free(stack, TRUE);
@ -245,9 +248,36 @@ dissect_xml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
insert_xml_frame(NULL, current_frame);
g_ptr_array_add(stack, current_frame);
tt = tvbparse_init(tvb, 0, -1, stack, want_ignore);
/* Detect and act on possible byte-order mark (BOM) */
try_bom = tvb_get_ntohs(tvb, start_offset);
if (try_bom == 0xFEFF) {
/* UTF-16BE */
const guint8 *data_str = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), ENC_UTF_16|ENC_BIG_ENDIAN);
size_t l = strlen(data_str);
decoded = tvb_new_child_real_data(tvb, data_str, (guint)l, (gint)l);
add_new_data_source(pinfo, decoded, "Decoded UTF-16BE text");
}
else if(try_bom == 0xFFFE) {
/* UTF-16LE (or possibly UTF-32LE, but Wireshark doesn't support UTF-32) */
const guint8 *data_str = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), ENC_UTF_16|ENC_LITTLE_ENDIAN);
size_t l = strlen(data_str);
decoded = tvb_new_child_real_data(tvb, data_str, (guint)l, (gint)l);
add_new_data_source(pinfo, decoded, "Decoded UTF-16LE text");
}
/* Could also test if try_bom is 0xnn00 or 0x00nn to guess endianness if we wanted */
else if(tvb_get_ntoh24(tvb, start_offset) == 0xEFBBBF) {
/* UTF-8 BOM; just skip over it */
decoded = tvb;
start_offset += 3;
}
else {
/* Assume it's UTF-8 */
decoded = tvb;
}
tt = tvbparse_init(decoded, start_offset, -1, stack, want_ignore);
current_frame->start_offset = 0;
current_frame->length = tvb_captured_length(tvb);
current_frame->length = tvb_captured_length(decoded) - start_offset;
root_ns = NULL;
@ -268,7 +298,7 @@ dissect_xml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
current_frame->ns = root_ns;
current_frame->item = proto_tree_add_item(tree, current_frame->ns->hf_tag, tvb, 0, -1, ENC_UTF_8|ENC_NA);
current_frame->item = proto_tree_add_item(tree, current_frame->ns->hf_tag, decoded, start_offset, -1, ENC_UTF_8|ENC_NA);
current_frame->tree = proto_item_add_subtree(current_frame->item, current_frame->ns->ett);
current_frame->last_item = current_frame->item;
@ -286,9 +316,24 @@ static gboolean dissect_xml_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
dissect_xml(tvb, pinfo, tree, data);
return TRUE;
} else if (pref_heuristic_unicode) {
const guint8 *data_str;
tvbuff_t *unicode_tvb;
guint16 try_bom;
/* XXX - UCS-2, or UTF-16? */
const guint8 *data_str = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), ENC_UCS_2|ENC_LITTLE_ENDIAN);
tvbuff_t *unicode_tvb = tvb_new_child_real_data(tvb, data_str, tvb_captured_length(tvb)/2, tvb_captured_length(tvb)/2);
gint enc = ENC_UCS_2|ENC_LITTLE_ENDIAN;
size_t l;
try_bom = tvb_get_ntohs(tvb, 0);
if (try_bom == 0xFEFF) {
enc = ENC_UTF_16|ENC_BIG_ENDIAN;
}
else if(try_bom == 0xFFFE) {
enc = ENC_UTF_16|ENC_LITTLE_ENDIAN;
}
data_str = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), enc);
l = strlen(data_str);
unicode_tvb = tvb_new_child_real_data(tvb, data_str, (guint)l, (gint)l);
if (tvbparse_peek(tvbparse_init(unicode_tvb, 0, -1, NULL, want_ignore), want_heur)) {
add_new_data_source(pinfo, unicode_tvb, "UTF8");
dissect_xml(unicode_tvb, pinfo, tree, data);