aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2018-01-08 13:54:00 -0800
committerMichael Mann <mmann78@netscape.net>2018-01-08 23:55:13 +0000
commit94479aded162aecce6289bdf26f95073bed0dc55 (patch)
tree3d2089eec8d14c3da82f8df88402c4d79f780c0c
parent7ec5dead2ffc03f009398a0a30217052e6749ad0 (diff)
Limit tvbparse recursion.
Add a recursion check to tvbparse so that we don't overflow our stack. Bug: 14253 Change-Id: I0f667c3720311318267a1184b33e33253f8ff729 Reviewed-on: https://code.wireshark.org/review/25202 Reviewed-by: Gerald Combs <gerald@wireshark.org> Petri-Dish: Gerald Combs <gerald@wireshark.org> Tested-by: Petri Dish Buildbot Reviewed-by: Michael Mann <mmann78@netscape.net>
-rw-r--r--epan/tvbparse.c23
-rw-r--r--epan/tvbparse.h1
2 files changed, 22 insertions, 2 deletions
diff --git a/epan/tvbparse.c b/epan/tvbparse.c
index ec233c3d06..cc9cbcf46f 100644
--- a/epan/tvbparse.c
+++ b/epan/tvbparse.c
@@ -80,6 +80,8 @@
#define TVBPARSE_DEBUG (TVBPARSE_DEBUG_SOME)
*/
+#define TVBPARSE_MAX_RECURSION_DEPTH 100 // Arbitrary. Matches DAAP and PNIO.
+
static tvbparse_elem_t* new_tok(tvbparse_t* tt,
int id,
int offset,
@@ -410,6 +412,9 @@ static int cond_one_of(tvbparse_t* tt, const int offset, const tvbparse_wanted_t
if ( offset > tt->end_offset )
return -1;
+ if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
+ return -1;
+
for(i=0; i < wanted->control.elems->len; i++) {
tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_ptr_array_index(wanted->control.elems,i);
tvbparse_elem_t* new_elem = NULL;
@@ -486,6 +491,9 @@ static int cond_hash(tvbparse_t* tt, const int offset, const tvbparse_wanted_t*
if ( offset > tt->end_offset )
return -1;
+ if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
+ return -1;
+
key_len = wanted->control.hash.key->condition(tt, offset, wanted->control.hash.key, &key_elem);
if (key_len < 0)
@@ -574,12 +582,16 @@ static int cond_seq(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted
int start = offset;
tvbparse_elem_t* ret_tok = NULL;
- if ( offset > tt->end_offset )
- return -1;
#ifdef TVBPARSE_DEBUG
if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) ws_g_warning("cond_seq: START");
#endif
+ if ( offset > tt->end_offset )
+ return -1;
+
+ if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
+ return -1;
+
for(i=0; i < wanted->control.elems->len; i++) {
tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_ptr_array_index(wanted->control.elems,i);
tvbparse_elem_t* new_elem = NULL;
@@ -657,6 +669,9 @@ static int cond_some(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wante
if ( offset > tt->end_offset )
return -1;
+ if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
+ return -1;
+
if ( wanted->min == 0 ) {
ret_tok = new_tok(tt,wanted->id,offset,0,wanted);
}
@@ -744,6 +759,9 @@ static int cond_until(tvbparse_t* tt, const int offset, const tvbparse_wanted_t
if ( offset + wanted->control.until.subelem->len > tt->end_offset )
return -1;
+ if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
+ return -1;
+
do {
len = wanted->control.until.subelem->condition(tt, target_offset++, wanted->control.until.subelem, &new_elem);
} while(len < 0 && target_offset+1 < tt->end_offset);
@@ -1202,6 +1220,7 @@ tvbparse_t* tvbparse_init(tvbuff_t* tvb,
tt->end_offset = offset + len;
tt->data = data;
tt->ignore = ignore;
+ tt->recursion_depth = 0;
return tt;
}
diff --git a/epan/tvbparse.h b/epan/tvbparse.h
index 6128b8bbca..863e909668 100644
--- a/epan/tvbparse.h
+++ b/epan/tvbparse.h
@@ -148,6 +148,7 @@ struct _tvbparse_t {
int end_offset;
void* data;
const tvbparse_wanted_t* ignore;
+ int recursion_depth;
};