diff options
author | Guy Harris <guy@alum.mit.edu> | 2019-06-12 17:26:52 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2019-06-13 01:44:02 +0000 |
commit | ce4a2816ff66ae5a7cf45fec10ac85fcbb66cef9 (patch) | |
tree | 532dc1858fc8f4553be2c47b96615fd828568b4a /epan/dissectors/packet-smb.c | |
parent | fb0d1ee24edeed29baac1bdb053d1553580d431c (diff) |
Pull get_unicode_or_ascii_string() into packet-smb.c.
Nobody else needs its extra stuff, as they're not pulling data out of an
SMB byte buffer, so they don't need the extra length check, and nobody
else uses it - or should use it, as we now have support for string
encodings in the tvbuff and protocol-tree code.
Change-Id: I8d249ea2c89a744eef12a05ad755811c07ca463a
Reviewed-on: https://code.wireshark.org/review/33581
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot
Reviewed-by: Guy Harris <guy@alum.mit.edu>
Diffstat (limited to 'epan/dissectors/packet-smb.c')
-rw-r--r-- | epan/dissectors/packet-smb.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/epan/dissectors/packet-smb.c b/epan/dissectors/packet-smb.c index b2a9c98c88..6d0fc69f63 100644 --- a/epan/dissectors/packet-smb.c +++ b/epan/dissectors/packet-smb.c @@ -1718,7 +1718,164 @@ static GSList *conv_tables = NULL; End of request/response matching functions XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ +/* Max string length for displaying Unicode strings. */ +#define MAX_UNICODE_STR_LEN 256 + +/* Turn a little-endian Unicode '\0'-terminated string into a string we + can display. + XXX - for now, we just handle the ISO 8859-1 characters. + If exactlen==TRUE then us_lenp contains the exact len of the string in + bytes. It might not be null terminated ! + bc specifies the number of bytes in the byte parameters; Windows 2000, + at least, appears, in some cases, to put only 1 byte of 0 at the end + of a Unicode string if the byte count +*/ +static gchar * +unicode_to_str(tvbuff_t *tvb, int offset, int *us_lenp, gboolean exactlen, + guint16 bc) +{ + gchar *cur; + gchar *p; + guint16 uchar; + int len; + int us_len; + gboolean overflow = FALSE; + + cur=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_UNICODE_STR_LEN+3+1); + p = cur; + len = MAX_UNICODE_STR_LEN; + us_len = 0; + for (;;) { + if (bc == 0) + break; + + if (bc == 1) { + /* XXX - explain this */ + if (!exactlen) + us_len += 1; /* this is a one-byte null terminator */ + break; + } + + uchar = tvb_get_letohs(tvb, offset); + if (uchar == 0) { + us_len += 2; /* this is a two-byte null terminator */ + break; + } + if (len > 0) { + if ((uchar & 0xFF00) == 0) + *p++ = (gchar) uchar; /* ISO 8859-1 */ + else + *p++ = '?'; /* not 8859-1 */ + len--; + } else + overflow = TRUE; + + offset += 2; + bc -= 2; + us_len += 2; + + if(exactlen){ + if(us_len>= *us_lenp){ + break; + } + } + } + if (overflow) { + /* Note that we're not showing the full string. */ + *p++ = '.'; + *p++ = '.'; + *p++ = '.'; + } + + *p = '\0'; + *us_lenp = us_len; + + return cur; +} + +/* nopad == TRUE : Do not add any padding before this string + * exactlen == TRUE : len contains the exact len of the string in bytes. + * bc: pointer to variable with amount of data left in the byte parameters + * region + */ +const gchar * +get_unicode_or_ascii_string(tvbuff_t *tvb, int *offsetp, + gboolean useunicode, int *len, gboolean nopad, gboolean exactlen, + guint16 *bcp) +{ + gchar *cur; + const gchar *string; + int string_len = 0; + int copylen; + gboolean overflow = FALSE; + + if (*bcp == 0) { + /* Not enough data in buffer */ + return NULL; + } + + if (useunicode) { + if ((!nopad) && (*offsetp % 2)) { + (*offsetp)++; /* Looks like a pad byte there sometimes */ + (*bcp)--; + + if (*bcp == 0) { + /* Not enough data in buffer */ + return NULL; + } + } + + if(exactlen){ + string_len = *len; + if (string_len < 0) { + /* This probably means it's a very large unsigned number; just set + it to the largest signed number, so that we throw the appropriate + exception. */ + string_len = INT_MAX; + } + } + + string = unicode_to_str(tvb, *offsetp, &string_len, exactlen, *bcp); + + } else { + if(exactlen){ + /* + * The string we return must be null-terminated. + */ + cur=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_UNICODE_STR_LEN+3+1); + copylen = *len; + + if (copylen < 0) { + /* This probably means it's a very large unsigned number; just set + it to the largest signed number, so that we throw the appropriate + exception. */ + copylen = INT_MAX; + } + + tvb_ensure_bytes_exist(tvb, *offsetp, copylen); + + if (copylen > MAX_UNICODE_STR_LEN) { + copylen = MAX_UNICODE_STR_LEN; + overflow = TRUE; + } + + tvb_memcpy(tvb, (guint8 *)cur, *offsetp, copylen); + cur[copylen] = '\0'; + + if (overflow) + g_strlcat(cur, "...",MAX_UNICODE_STR_LEN+3+1); + + string_len = *len; + string = cur; + } else { + string = tvb_get_const_stringz(tvb, *offsetp, &string_len); + } + } + + *len = string_len; + return string; +} typedef struct _smb_uid_t { char *domain; |