There is no guarantee that a buffer obtained using "tvb_get_ptr()" is

neatly aligned on a 2-byte or a 4-byte boundary, and there is no
guarantee that a misaligned pointer can be dereferenced without getting
a fault.

Furthermore, there is no guarantee that, even if you *can* dereference a
pointer to a 2-byte or 4-byte quantity in a packet, the resulting number
you get back is in the right byte order; the data in the packet might
have a different byte order from the machine on which you're running.

Therefore, we change "prs_uint8s()", "prs_uint16s()", and
"prs_uint32s()" to return the starting offset, in the tvbuff, of the
collection of 8-bit, 16-bit, or 32-bit integral values, rather than a
pointer to the raw packet data, and change their callers to fetch the
data using "tvb_get_guint8()", "tvb_get_letohs()", and
"tvb_get_letohl()" (the stuff in all the NT protocols is presumed to be
little-endian here).  We also change "fake_unicode()" to take a tvbuff
and an offset, rather than a data pointer, as arguments, and to use
"tvb_get_letohs()" to fetch the Unicode characters (again, we assume
little-endian Unicode).

This requires "fake_unicode()" to establish a cleanup handler, so we
don't leak memory if it throws an exception.

We also make "fake_unicode()" use "g_malloc()" to allocate its buffer
(we weren't checking for allocation failures in any case; with
"g_malloc()", we'll abort on an allocation failure - if we can come up
with a cleverer way of handling them, fine), and the matching frees to
use "g_free()".  (We also insert some missing frees....)

Fix some formats to print unsigned quantities with "%u", not "%d".

Don't append text to items in the tree for non-string values in
"dissect_ndr_nt_STRING_string()".

svn path=/trunk/; revision=4986
This commit is contained in:
Guy Harris 2002-03-19 22:09:23 +00:00
parent 3795d7d240
commit ad8b000445
4 changed files with 106 additions and 117 deletions

View File

@ -2,7 +2,7 @@
* Routines for SMB \PIPE\lsarpc packet disassembly
* Copyright 2001, Tim Potter <tpot@samba.org>
*
* $Id: packet-dcerpc-lsa.c,v 1.7 2002/01/21 07:36:33 guy Exp $
* $Id: packet-dcerpc-lsa.c,v 1.8 2002/03/19 22:09:23 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -80,7 +80,7 @@ static int prs_UNISTR(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *subtree;
guint32 max_len, stroffset, actual_count, i;
int old_offset;
guint16 *string;
int string_offset;
char *astring;
/* Parse data */
@ -97,33 +97,33 @@ static int prs_UNISTR(tvbuff_t *tvb, int offset, packet_info *pinfo,
&actual_count, "Actual length");
offset = prs_uint16s(tvb, offset, pinfo, NULL,
actual_count, &string, "Data");
actual_count, &string_offset, "Data");
/* Insert into display */
astring = fake_unicode(string, actual_count);
astring = fake_unicode(tvb, string_offset, actual_count);
if (!astring || !astring[0])
astring = strdup("(NULL)");
astring = g_strdup("(NULL)");
item = proto_tree_add_text(tree, tvb, old_offset,
offset - old_offset, "String: %s",
astring);
free(astring);
g_free(astring);
subtree = proto_item_add_subtree(item, ett_UNISTR);
proto_tree_add_text(subtree, tvb, old_offset, 4,
"Max length: %d", max_len);
"Max length: %u", max_len);
old_offset += 4;
proto_tree_add_text(subtree, tvb, old_offset, 4,
"Offset: %d", stroffset);
"Offset: %u", stroffset);
old_offset += 4;
proto_tree_add_text(subtree, tvb, old_offset, 4,
"Actual length: %d", actual_count);
"Actual length: %u", actual_count);
old_offset += 4;
if (prs_pop_ptr(ptr_list, "Data"))
@ -159,7 +159,8 @@ static int prs_SID(tvbuff_t *tvb, int offset, packet_info *pinfo,
int old_offset, i;
proto_item *item;
proto_tree *subtree;
guint32 ia, *subauths, subauth_max;
guint32 ia, subauth_max;
int subauths_offset;
guint8 revision;
char sid_str[128];
@ -183,13 +184,14 @@ static int prs_SID(tvbuff_t *tvb, int offset, packet_info *pinfo,
sprintf(sid_str, "S-%u-%u", revision, ia);
offset = prs_uint32s(tvb, offset, pinfo, NULL, subauth_count,
&subauths, "Subauth count");
&subauths_offset, "Subauth count");
for (i = 0; i < subauth_count; i++) {
char sa[16];
sprintf(sa, "-%u", subauths[i]);
sprintf(sa, "-%u", tvb_get_letohl(tvb, subauths_offset));
strcat(sid_str, sa);
subauths_offset += 4;
}
/* Insert into display */
@ -197,17 +199,17 @@ static int prs_SID(tvbuff_t *tvb, int offset, packet_info *pinfo,
item = proto_tree_add_text(tree, tvb, offset, 0, "SID: %s", sid_str);
subtree = proto_item_add_subtree(item, ett_SID);
proto_tree_add_text(subtree, tvb, old_offset, 4,
"Subauth array max count: %d", subauth_max);
proto_tree_add_text(subtree, tvb, old_offset, 4,
"Subauth array max count: %u", subauth_max);
old_offset += 4;
proto_tree_add_text(subtree, tvb, old_offset, 1, "Revision: %d",
proto_tree_add_text(subtree, tvb, old_offset, 1, "Revision: %u",
revision);
old_offset++;
proto_tree_add_text(subtree, tvb, old_offset, 1, "Subauth count: %d",
proto_tree_add_text(subtree, tvb, old_offset, 1, "Subauth count: %u",
subauth_count);
old_offset++;

View File

@ -2,7 +2,7 @@
* Routines for DCERPC over SMB packet disassembly
* Copyright 2001, Tim Potter <tpot@samba.org>
*
* $Id: packet-dcerpc-nt.c,v 1.18 2002/03/15 20:46:04 sharpe Exp $
* $Id: packet-dcerpc-nt.c,v 1.19 2002/03/19 22:09:23 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -63,7 +63,7 @@ int prs_uint8(tvbuff_t *tvb, int offset, packet_info *pinfo,
if (name && tree)
proto_tree_add_text(tree, tvb, offset - 1, 1,
"%s: %d", name, i);
"%s: %u", name, i);
if (data)
*data = i;
@ -72,24 +72,15 @@ int prs_uint8(tvbuff_t *tvb, int offset, packet_info *pinfo,
}
int prs_uint8s(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int count, guint8 **data, char *name)
proto_tree *tree, int count, int *data_offset, char *name)
{
const guint8 *ptr;
/* The tvb_get_ptr() function fails an assertion if count < -1 */
if (count < -1)
THROW(BoundsError);
/* No alignment required */
ptr = tvb_get_ptr(tvb, offset, count);
if (name && tree)
proto_tree_add_text(tree, tvb, offset, count, "%s", name);
if (data)
*data = (guint8 *)ptr;
if (data_offset)
*data_offset = offset;
offset += count;
@ -110,7 +101,7 @@ int prs_uint16(tvbuff_t *tvb, int offset, packet_info *pinfo,
if (name && tree)
proto_tree_add_text(tree, tvb, offset - 2, 2,
"%s: %d", name, i);
"%s: %u", name, i);
if (data)
*data = i;
@ -120,24 +111,15 @@ int prs_uint16(tvbuff_t *tvb, int offset, packet_info *pinfo,
/* Parse a number of uint16's */
int prs_uint16s(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int count, guint16 **data, char *name)
proto_tree *tree, int count, int *data_offset, char *name)
{
const guint8 *ptr;
/* The tvb_get_ptr() function fails an assertion if count < -1 */
if (count < -1)
THROW(BoundsError);
offset = prs_align(offset, 2);
ptr = tvb_get_ptr(tvb, offset, count * 2);
if (name && tree)
proto_tree_add_text(tree, tvb, offset, count * 2,
"%s", name);
if (data)
*data = (guint16 *)ptr;
if (data_offset)
*data_offset = offset;
offset += count * 2;
@ -158,7 +140,7 @@ int prs_uint32(tvbuff_t *tvb, int offset, packet_info *pinfo,
if (name && tree)
proto_tree_add_text(tree, tvb, offset - 4, 4,
"%s: %d", name, i);
"%s: %u", name, i);
if (data)
*data = i;
@ -169,24 +151,15 @@ int prs_uint32(tvbuff_t *tvb, int offset, packet_info *pinfo,
/* Parse a number of 32-bit integers */
int prs_uint32s(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int count, guint32 **data, char *name)
proto_tree *tree, int count, int *data_offset, char *name)
{
const guint8 *ptr;
/* The tvb_get_ptr() function fails an assertion if count < -1 */
if (count < -1)
THROW(BoundsError);
offset = prs_align(offset, 4);
ptr = tvb_get_ptr(tvb, offset, count * 4);
if (name && tree)
proto_tree_add_text(tree, tvb, offset - 4, 4,
"%s", name);
if (data)
*data = (guint32 *)ptr;
if (data_offset)
*data_offset = offset;
offset += count * 4;
@ -330,18 +303,33 @@ guint32 prs_pop_ptr(GList **ptr_list, char *name)
fake it by taking every odd byte. )-: The caller must free the
result returned. */
char *fake_unicode(guint16 *data, int len)
char *fake_unicode(tvbuff_t *tvb, int offset, int len)
{
char *buffer;
int i;
guint16 character;
buffer = malloc(len + 1);
buffer = g_malloc(len + 1);
for (i = 0; i < len; i++)
buffer[i] = data[i] & 0xff;
/*
* Register a cleanup function in case on of our tvbuff accesses
* throws an exception. We need to clean up buffer.
*/
CLEANUP_PUSH(g_free, buffer);
for (i = 0; i < len; i++) {
character = tvb_get_letohs(tvb, offset);
buffer[i] = character & 0xff;
offset += 2;
}
buffer[len] = 0;
/*
* Pop the cleanup function, but don't free the buffer.
*/
CLEANUP_POP;
return buffer;
}
@ -361,13 +349,13 @@ int prs_UNISTR2(tvbuff_t *tvb, int offset, packet_info *pinfo,
}
if (flags & PARSE_BUFFERS) {
guint16 *data16;
int data16_offset;
offset = prs_uint16s(tvb, offset, pinfo, tree, max_len,
&data16, "Buffer");
&data16_offset, "Buffer");
if (data)
*data = fake_unicode(data16, max_len);
*data = fake_unicode(tvb, data16_offset, max_len);
}
return offset;
@ -440,7 +428,7 @@ dissect_ndr_nt_UNICODE_STRING_str(tvbuff_t *tvb, int offset,
char *drep)
{
guint32 len, off, max_len;
guint16 *data16;
int data16_offset;
char *text;
int old_offset;
dcerpc_info *di;
@ -459,8 +447,9 @@ dissect_ndr_nt_UNICODE_STRING_str(tvbuff_t *tvb, int offset,
hf_nt_str_max_len, &max_len);
old_offset=offset;
offset = prs_uint16s(tvb, offset, pinfo, tree, max_len, &data16, NULL);
text = fake_unicode(data16, max_len);
offset = prs_uint16s(tvb, offset, pinfo, tree, max_len, &data16_offset,
NULL);
text = fake_unicode(tvb, data16_offset, max_len);
proto_tree_add_string(tree, di->hf_index, tvb, old_offset,
offset-old_offset, text);
@ -480,6 +469,7 @@ dissect_ndr_nt_UNICODE_STRING_str(tvbuff_t *tvb, int offset,
}
}
}
g_free(text);
return offset;
}
@ -549,7 +539,8 @@ dissect_ndr_nt_STRING_string (tvbuff_t *tvb, int offset,
char *drep)
{
guint32 len, off, max_len;
guint8 *text;
int text_offset;
const guint8 *text;
int old_offset;
header_field_info *hfi;
dcerpc_info *di;
@ -572,21 +563,24 @@ dissect_ndr_nt_STRING_string (tvbuff_t *tvb, int offset,
switch(hfi->type){
case FT_STRING:
offset = prs_uint8s(tvb, offset, pinfo, tree, max_len, &text, NULL);
offset = prs_uint8s(tvb, offset, pinfo, tree, max_len,
&text_offset, NULL);
text = tvb_get_ptr(tvb, text_offset, max_len);
proto_tree_add_string_format(tree, di->hf_index,
tvb, old_offset, offset-old_offset,
text, "%s: %s", hfi->name, text);
break;
case FT_BYTES:
text="";
text = NULL;
proto_tree_add_item(tree, di->hf_index, tvb, offset, max_len, FALSE);
offset += max_len;
break;
default:
text = NULL;
g_assert_not_reached();
}
if(tree && (di->levels>-1)){
if(tree && text && (di->levels>-1)){
proto_item_append_text(tree, ": %s", text);
if(di->levels>-1){
tree=tree->parent;

View File

@ -2,7 +2,7 @@
* Routines for DCERPC over SMB packet disassembly
* Copyright 2001, Tim Potter <tpot@samba.org>
*
* $Id: packet-dcerpc-nt.h,v 1.13 2002/03/15 08:59:52 sahlberg Exp $
* $Id: packet-dcerpc-nt.h,v 1.14 2002/03/19 22:09:23 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -34,19 +34,19 @@ int prs_uint8(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint8 *data, char *name);
int prs_uint8s(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int count, guint8 **data, char *name);
proto_tree *tree, int count, int *data_offset, char *name);
int prs_uint16(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint16 *data, char *name);
int prs_uint16s(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int count, guint16 **data, char *name);
proto_tree *tree, int count, int *data_offset, char *name);
int prs_uint32(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 *data, char *name);
int prs_uint32s(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int count, guint32 **data, char *name);
proto_tree *tree, int count, int *data_offset, char *name);
/* Parse NT status code */
@ -55,7 +55,7 @@ int prs_ntstatus(tvbuff_t *tvb, int offset, packet_info *pinfo,
/* Parse some common RPC structures */
char *fake_unicode(guint16 *data, int len);
char *fake_unicode(tvbuff_t *tvb, int offset, int len);
int prs_UNISTR2(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int flags, char **data, char *name);

View File

@ -2,7 +2,7 @@
* Routines for SMB \PIPE\spoolss packet disassembly
* Copyright 2001, Tim Potter <tpot@samba.org>
*
* $Id: packet-dcerpc-spoolss.c,v 1.4 2002/01/21 07:36:33 guy Exp $
* $Id: packet-dcerpc-spoolss.c,v 1.5 2002/03/19 22:09:23 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -578,16 +578,17 @@ static int prs_UNISTR2_dp(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *subtree;
guint32 length, the_offset, max_len;
int old_offset = offset;
guint16 *data16;
int data16_offset;
char *text;
offset = prs_uint32(tvb, offset, pinfo, tree, &length, NULL);
offset = prs_uint32(tvb, offset, pinfo, tree, &the_offset, NULL);
offset = prs_uint32(tvb, offset, pinfo, tree, &max_len, NULL);
offset = prs_uint16s(tvb, offset, pinfo, tree, max_len, &data16, NULL);
offset = prs_uint16s(tvb, offset, pinfo, tree, max_len, &data16_offset,
NULL);
text = fake_unicode(data16, max_len);
text = fake_unicode(tvb, data16_offset, max_len);
item = proto_tree_add_text(tree, tvb, old_offset, offset - old_offset,
"UNISTR2: %s", text);
@ -597,18 +598,18 @@ static int prs_UNISTR2_dp(tvbuff_t *tvb, int offset, packet_info *pinfo,
if (data)
*data = text;
else
free(text);
g_free(text);
proto_tree_add_text(subtree, tvb, old_offset, 4, "Length: %d", length);
proto_tree_add_text(subtree, tvb, old_offset, 4, "Length: %u", length);
old_offset += 4;
proto_tree_add_text(subtree, tvb, old_offset, 4, "Offset: %d",
proto_tree_add_text(subtree, tvb, old_offset, 4, "Offset: %u",
the_offset);
old_offset += 4;
proto_tree_add_text(subtree, tvb, old_offset, 4, "Max length: %d",
proto_tree_add_text(subtree, tvb, old_offset, 4, "Max length: %u",
max_len);
old_offset += 4;
@ -653,7 +654,7 @@ static int SpoolssGetPrinterData_q(tvbuff_t *tvb, int offset,
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value_name);
free(value_name);
g_free(value_name);
offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Size");
@ -749,8 +750,8 @@ static int SpoolssGetPrinterDataEx_q(tvbuff_t *tvb, int offset,
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s/%s",
key_name, value_name);
free(key_name);
free(value_name);
g_free(key_name);
g_free(value_name);
offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Size");
@ -841,7 +842,7 @@ static int SpoolssSetPrinterData_q(tvbuff_t *tvb, int offset,
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value_name);
free(value_name);
g_free(value_name);
offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
@ -937,8 +938,8 @@ static int SpoolssSetPrinterDataEx_q(tvbuff_t *tvb, int offset,
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s/%s",
key_name, value_name);
free(key_name);
free(value_name);
g_free(key_name);
g_free(value_name);
offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
@ -998,23 +999,15 @@ static int prs_uint16uni(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, void **data, char *name)
{
gint len = 0, remaining, i;
guint16 *ptr;
char *text;
offset = prs_align(offset, 2);
/* Get a pointer to remaining data in buffer */
/* Get remaining data in buffer as a string */
remaining = tvb_length_remaining(tvb, offset);
ptr = (guint16 *)tvb_get_ptr(tvb, offset, remaining);
for (i = 0; i < remaining / 2; i++) {
if (ptr[i] == 0)
break;
len++;
}
text = fake_unicode(ptr, len);
text = fake_unicode(tvb, offset, remaining);
len = strlen(text);
if (name)
proto_tree_add_text(tree, tvb, offset, (len + 1) * 2,
@ -1024,7 +1017,7 @@ static int prs_uint16uni(tvbuff_t *tvb, int offset, packet_info *pinfo,
if (data)
*data = text;
else
free(text);
g_free(text);
return offset + (len + 1) * 2;
}
@ -1137,7 +1130,7 @@ static int prs_relstr(tvbuff_t *tvb, int offset, packet_info *pinfo,
if (data)
*data = text;
else
free(text);
g_free(text);
proto_tree_add_text(subtree, tvb, offset - 4, 4,
"Relative offset: %d", relstr_offset);
@ -1464,7 +1457,7 @@ static int SpoolssOpenPrinterEx_q(tvbuff_t *tvb, int offset,
printer_name);
}
free(printer_name);
g_free(printer_name);
}
offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
@ -1707,6 +1700,7 @@ static int SpoolssRFFPCNEX_q(tvbuff_t *tvb, int offset,
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
printer_name);
g_free(printer_name);
}
offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Printer local");
@ -1848,7 +1842,6 @@ static gint ett_BUFFER_DATA = -1;
static gint ett_BUFFER_DATA_BUFFER = -1;
struct BUFFER_DATA {
guint8 *data8; /* Pointer to buffer data */
proto_item *item; /* proto_item holding proto_tree */
proto_tree *tree; /* proto_tree holding buffer data */
tvbuff_t *tvb;
@ -1861,7 +1854,7 @@ static int prs_BUFFER_DATA(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_item *item, *subitem;
proto_tree *subtree, *subsubtree;
guint32 ptr = 0, size;
guint8 *data8;
int data8_offset;
item = proto_tree_add_text(tree, tvb, offset, 0, "BUFFER_DATA");
@ -1873,8 +1866,8 @@ static int prs_BUFFER_DATA(tvbuff_t *tvb, int offset, packet_info *pinfo,
subsubtree = proto_item_add_subtree(subitem, ett_BUFFER_DATA_BUFFER);
offset = prs_uint8s(tvb, offset, pinfo, subsubtree, size, &data8,
NULL);
offset = prs_uint8s(tvb, offset, pinfo, subsubtree, size,
&data8_offset, NULL);
/* Return some info which will help the caller "cast" the buffer
data and dissect it further. */
@ -1884,11 +1877,10 @@ static int prs_BUFFER_DATA(tvbuff_t *tvb, int offset, packet_info *pinfo,
bd = (struct BUFFER_DATA *)malloc(sizeof(struct BUFFER_DATA));
bd->data8 = data8;
bd->item = subitem;
bd->tree = subsubtree;
bd->tvb = tvb;
bd->offset = offset - size;
bd->offset = data8_offset;
*data = bd;
}
@ -2341,6 +2333,7 @@ static int SpoolssAddPrinterEx_q(tvbuff_t *tvb, int offset,
offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
prs_UNISTR2_dp,
(void *)&printer_name, NULL);
g_free(printer_name);
}
offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Level");
@ -2397,7 +2390,7 @@ static int SpoolssAddPrinterEx_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
policy_hnd = tvb_get_ptr(tvb, start_offset, 20);
printer_name = strdup("<printer name here>");
printer_name = g_strdup("<printer name here>");
store_printer_name(policy_hnd, printer_name);
@ -2405,7 +2398,7 @@ static int SpoolssAddPrinterEx_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
printer_name);
free(printer_name);
g_free(printer_name);
}
if (tvb_length_remaining(tvb, offset) != 0)
@ -2467,7 +2460,7 @@ static int SpoolssEnumPrinterData_r(tvbuff_t *tvb, int offset,
dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
request_hash_value *request_info;
guint32 data_size, type, value_size;
guint16 *uint16s;
int uint16s_offset;
char *text;
/* Update informational fields */
@ -2487,18 +2480,18 @@ static int SpoolssEnumPrinterData_r(tvbuff_t *tvb, int offset,
offset = prs_uint32(tvb, offset, pinfo, tree, &value_size,
"Value size");
offset = prs_uint16s(tvb, offset, pinfo, tree, value_size, &uint16s,
NULL);
offset = prs_uint16s(tvb, offset, pinfo, tree, value_size,
&uint16s_offset, NULL);
text = fake_unicode(uint16s, value_size);
text = fake_unicode(tvb, uint16s_offset, value_size);
proto_tree_add_text(tree, tvb, offset - value_size * 2,
proto_tree_add_text(tree, tvb, uint16s_offset,
value_size * 2, "Value: %s", text);
if (text[0] && check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", text);
free(text);
g_free(text);
offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Real value size");