diff options
author | Gerald Combs <gerald@wireshark.org> | 2009-09-09 00:18:15 +0000 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2009-09-09 00:18:15 +0000 |
commit | ffd3a72374866c1bd2325a788bc4495c4e7704fd (patch) | |
tree | d276352de32d3b494eb0ebe3024939215c71086f /plugins/opcua/opcua_simpletypes.c | |
parent | 40e2849be87943b67cefbeaa833fa187f31e927d (diff) | |
download | wireshark-ffd3a72374866c1bd2325a788bc4495c4e7704fd.tar.gz |
Check our array lengths and refuse to process them if they're too large.
Fixes bug 3986. Use tvb_memeql and proto_tree_add_item instead of
digging around in tvb->real_data.
svn path=/trunk/; revision=29813
Diffstat (limited to 'plugins/opcua/opcua_simpletypes.c')
-rw-r--r-- | plugins/opcua/opcua_simpletypes.c | 79 |
1 files changed, 49 insertions, 30 deletions
diff --git a/plugins/opcua/opcua_simpletypes.c b/plugins/opcua/opcua_simpletypes.c index 777a842e8c..45a7a10640 100644 --- a/plugins/opcua/opcua_simpletypes.c +++ b/plugins/opcua/opcua_simpletypes.c @@ -34,9 +34,6 @@ #include <string.h> #include <epan/emem.h> -/* string buffer */ -#define MAX_BUFFER 256 - #define DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID_FLAG 0x01 #define DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE_FLAG 0x02 #define DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT_FLAG 0x04 @@ -56,6 +53,9 @@ #define EXTOBJ_ENCODINGMASK_BINBODY_FLAG 0x01 #define EXTOBJ_ENCODINGMASK_XMLBODY_FLAG 0x02 +/* Chosen arbitrarily */ +#define MAX_ARRAY_LEN 10000 + static int hf_opcua_diag_mask_symbolicflag = -1; static int hf_opcua_diag_mask_namespaceflag = -1; static int hf_opcua_diag_mask_localizedtextflag = -1; @@ -338,35 +338,28 @@ void parseInt64(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int hfIndex) void parseString(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int hfIndex) { - char *szValue = ep_alloc(MAX_BUFFER); + char *szValue; gint iOffset = *pOffset; gint32 iLen = tvb_get_letohl(tvb, *pOffset); iOffset+=4; - if (szValue) + if (iLen == -1) { - if (iLen == -1) - { - g_snprintf(szValue, MAX_BUFFER, "[OpcUa Null String]"); - } - else if (iLen >= 0) - { - int iStrLen = iLen; - if (iStrLen > (MAX_BUFFER-1)) iStrLen = MAX_BUFFER - 1; - /* copy non null terminated string of length iStrlen */ - strncpy(szValue, (char*)&tvb->real_data[iOffset], iStrLen); - /* set null terminator */ - szValue[iStrLen] = 0; - iOffset += iLen; /* eat the whole string */ - } - else - { - g_snprintf(szValue, MAX_BUFFER, "[Invalid String] Ups, something is wrong with this message."); - } - + proto_tree_add_string(tree, hfIndex, tvb, *pOffset, (iOffset - *pOffset), + "[OpcUa Null String]"); + } + else if (iLen >= 0) + { + iOffset += iLen; /* eat the whole string */ + proto_tree_add_item(tree, hfIndex, tvb, *pOffset, (iOffset - *pOffset), TRUE); + } + else + { + szValue = ep_strdup_printf("[Invalid String] Invalid length: %d", iLen); proto_tree_add_string(tree, hfIndex, tvb, *pOffset, (iOffset - *pOffset), szValue); - *pOffset = iOffset; } + + *pOffset = iOffset; } void parseStatusCode(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int hfIndex) @@ -644,9 +637,17 @@ void parseVariant(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, char *szFieldN proto_tree *subtree = proto_item_add_subtree(ti, ett_opcua_array); int i; - for (i=0; i<ArrayLength; i++) + if (ArrayLength < MAX_ARRAY_LEN) { - parseInt32(subtree, tvb, pOffset, hf_opcua_Int32); + for (i=0; i<ArrayLength; i++) + { + parseInt32(subtree, tvb, pOffset, hf_opcua_Int32); + } + } + else + { + /* XXX - This should be expert_add_info_format, but we need pinfo for that */ + PROTO_ITEM_SET_GENERATED(proto_tree_add_text(tree, tvb, iOffset, 4, "Array length %d too large to process", ArrayLength)); } } @@ -668,11 +669,17 @@ void parseArraySimple(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int hfInde /* read array length */ iLen = tvb_get_letohl(tvb, *pOffset); proto_tree_add_item(subtree, hf_opcua_ArraySize, tvb, *pOffset, 4, TRUE); - *pOffset += 4; if (iLen == -1) return; /* no array */ if (iLen == 0) return; /* array with zero elements*/ + if (iLen > MAX_ARRAY_LEN) + { + PROTO_ITEM_SET_GENERATED(proto_tree_add_text(tree, tvb, *pOffset, 4, "Array length %d too large to process", iLen)); + return; + } + + *pOffset += 4; for (i=0; i<iLen; i++) { (*pParserFunction)(subtree, tvb, pOffset, hfIndex); @@ -694,11 +701,17 @@ void parseArrayEnum(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, fctEnumParse /* read array length */ iLen = tvb_get_letohl(tvb, *pOffset); proto_tree_add_item(subtree, hf_opcua_ArraySize, tvb, *pOffset, 4, TRUE); - *pOffset += 4; if (iLen == -1) return; /* no array */ if (iLen == 0) return; /* array with zero elements*/ + if (iLen > MAX_ARRAY_LEN) + { + PROTO_ITEM_SET_GENERATED(proto_tree_add_text(tree, tvb, *pOffset, 4, "Array length %d too large to process", iLen)); + return; + } + + *pOffset += 4; for (i=0; i<iLen; i++) { (*pParserFunction)(subtree, tvb, pOffset); @@ -719,11 +732,17 @@ void parseArrayComplex(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, char *szF /* read array length */ iLen = tvb_get_letohl(tvb, *pOffset); proto_tree_add_item(subtree, hf_opcua_ArraySize, tvb, *pOffset, 4, TRUE); - *pOffset += 4; if (iLen == -1) return; /* no array */ if (iLen == 0) return; /* array with zero elements*/ + if (iLen > MAX_ARRAY_LEN) + { + PROTO_ITEM_SET_GENERATED(proto_tree_add_text(tree, tvb, *pOffset, 4, "Array length %d too large to process", iLen)); + return; + } + + *pOffset += 4; for (i=0; i<iLen; i++) { char szNum[20]; |