From 526ccef5f427a1f8ce51a7ca4c75270acf710cce Mon Sep 17 00:00:00 2001 From: John Thacker Date: Tue, 8 Nov 2022 07:01:53 -0500 Subject: [PATCH] per: Implement UTF8String properly UTF8String is not a known-multiplier character string, since the characters are variable width. That means that a size constraint in characters doesn't correspond to a fixed number of octets, and thus that constraints are never PER-visible. (X.691 27.6) That includes size constraints, extensions, permitted alphabets, etc. The length determinant is thus the unconstrained type, and always at least an entire octet instead of ever taking up a smaller number of bits. Extract the string as UTF-8 after aligning as necessary, which will deal with illegal encodings. Fix #18600. --- epan/dissectors/packet-per.c | 39 +++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/epan/dissectors/packet-per.c b/epan/dissectors/packet-per.c index a36db40c0c..8a540b8fa3 100644 --- a/epan/dissectors/packet-per.c +++ b/epan/dissectors/packet-per.c @@ -908,10 +908,43 @@ dissect_per_BMPString(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tre return offset; } guint32 -dissect_per_UTF8String(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len, gboolean has_extension _U_) +dissect_per_UTF8String(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len _U_, int max_len _U_, gboolean has_extension _U_) { - offset=dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, - hf_index, min_len, max_len, has_extension, 0, 255, NULL, 256, NULL); + tvbuff_t *val_tvb; + guint32 length; + + /* UTF8String is not a known-multiplier character string (UTF8 + * characters are variable width.) Hence subclause 27.6 applies, + * and "constraints are never PER-visible, and the type can never + * be extensible for PER encoding." + */ + + /* 27.6.3 unconstrained length determinant with "n" in octets */ + offset = dissect_per_length_determinant(tvb, offset, actx, tree, hf_per_octet_string_length, &length, NULL); + + if(length){ + + /* Unnecessary because the length determinant is aligned. */ + if(actx->aligned) { + BYTE_ALIGN_OFFSET(offset); + } + + val_tvb = tvb_new_octet_aligned(tvb, offset, length * 8); + /* Add new data source if the offset was unaligned */ + if ((offset & 7) != 0) { + add_new_data_source(actx->pinfo, val_tvb, "Unaligned UTF8String"); + } + + proto_tree_add_item(tree, hf_index, val_tvb, 0, length, ENC_UTF_8); + } else { + /* tvb_new_octet_aligned doesn't like zero length. + * length zero indicates a present but empty string, so add it + */ + proto_tree_add_item(tree, hf_index, tvb, (offset-1)>>3, length, ENC_UTF_8); + } + + offset+=(length<<3); + return offset; }