diff options
author | Gerald Combs <gerald@wireshark.org> | 2018-01-08 13:54:00 -0800 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2018-01-08 23:55:13 +0000 |
commit | 94479aded162aecce6289bdf26f95073bed0dc55 (patch) | |
tree | 3d2089eec8d14c3da82f8df88402c4d79f780c0c /epan | |
parent | 7ec5dead2ffc03f009398a0a30217052e6749ad0 (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>
Diffstat (limited to 'epan')
-rw-r--r-- | epan/tvbparse.c | 23 | ||||
-rw-r--r-- | epan/tvbparse.h | 1 |
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; }; |