summaryrefslogtreecommitdiff
path: root/plugins/opcua/opcua_simpletypes.c
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2009-09-09 00:18:15 +0000
committerGerald Combs <gerald@wireshark.org>2009-09-09 00:18:15 +0000
commitffd3a72374866c1bd2325a788bc4495c4e7704fd (patch)
treed276352de32d3b494eb0ebe3024939215c71086f /plugins/opcua/opcua_simpletypes.c
parent40e2849be87943b67cefbeaa833fa187f31e927d (diff)
downloadwireshark-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.c79
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];