QUIC: Update IETF draft URL (draft-08)
[metze/wireshark/wip.git] / epan / tvbparse.c
index 8ae2aba12aaad8134c049099f0a71467f7b121bc..d9d2349840545d54a3da651cb2dacdf683403b76 100644 (file)
 #include <string.h>
 #include <glib.h>
 
-#include <epan/emem.h>
 #include <epan/wmem/wmem.h>
 #include <epan/proto.h>
 #include <epan/packet_info.h>
 #include <epan/tvbparse.h>
+#include <wsutil/ws_printf.h> /* ws_g_warning */
 
 
 #define TVBPARSE_DEBUG_ALL 0xffffffff
@@ -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,
@@ -88,7 +90,7 @@ static tvbparse_elem_t* new_tok(tvbparse_t* tt,
     tvbparse_elem_t* tok;
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NEWTOK) g_warning("new_tok: id=%i offset=%u len=%u",id,offset,len);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NEWTOK) ws_g_warning("new_tok: id=%i offset=%u len=%u",id,offset,len);
 #endif
 
     tok = (tvbparse_elem_t *)wmem_new(wmem_packet_scope(), tvbparse_elem_t);
@@ -114,20 +116,20 @@ static int ignore_fcn(tvbparse_t* tt, int offset) {
     if (!tt->ignore) return 0;
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: enter");
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) ws_g_warning("ignore: enter");
 #endif
 
     while ((consumed = tt->ignore->condition(tt,offset,tt->ignore,&ignored)) > 0) {
         len += consumed;
         offset += consumed;
 #ifdef TVBPARSE_DEBUG
-        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: consumed=%i",consumed);
+        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) ws_g_warning("ignore: consumed=%i",consumed);
 #endif
 
     }
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: len=%i",len);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) ws_g_warning("ignore: len=%i",len);
 #endif
 
     return len;
@@ -139,7 +141,7 @@ static int cond_char (tvbparse_t* tt, const int offset, const tvbparse_wanted_t
     guint i;
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) g_warning("cond_char: control='%s'",wanted->control.str);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) ws_g_warning("cond_char: control='%s'",wanted->control.str);
 #endif
 
     if ( offset + 1 > tt->end_offset )
@@ -151,7 +153,7 @@ static int cond_char (tvbparse_t* tt, const int offset, const tvbparse_wanted_t
         if ( c == t ) {
             *tok =  new_tok(tt,wanted->id,offset,1,wanted);
 #ifdef TVBPARSE_DEBUG
-            if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) g_warning("cond_char: GOT: '%c'",c);
+            if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) ws_g_warning("cond_char: GOT: '%c'",c);
 #endif
             return 1;
         }
@@ -165,7 +167,7 @@ tvbparse_wanted_t* tvbparse_char(const int id,
                                  const void* data,
                                  tvbparse_action_t before_cb,
                                  tvbparse_action_t after_cb) {
-    tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
+    tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t);
 
     w->condition = cond_char;
     w->id = id;
@@ -184,7 +186,7 @@ static int cond_chars_common(tvbparse_t* tt, int offset, const tvbparse_wanted_t
     int left = tt->end_offset - offset;
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) g_warning("cond_chars_common: control='%s'",wanted->control.str);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) ws_g_warning("cond_chars_common: control='%s'",wanted->control.str);
 #endif
 
     if ( offset + (int)wanted->min > tt->end_offset )
@@ -207,7 +209,7 @@ static int cond_chars_common(tvbparse_t* tt, int offset, const tvbparse_wanted_t
     } else {
         *tok = new_tok(tt,wanted->id,start,length,wanted);
 #ifdef TVBPARSE_DEBUG
-        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) g_warning("cond_chars_common: GOT len=%i",length);
+        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) ws_g_warning("cond_chars_common: GOT len=%i",length);
 #endif
         return length;
     }
@@ -221,14 +223,14 @@ tvbparse_wanted_t* tvbparse_chars(const int id,
                                   tvbparse_action_t before_cb,
                                   tvbparse_action_t after_cb)
 {
-    tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
+    tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
     char *accept_str;
     gsize i;
 
-    accept_str = g_malloc(256);
+    accept_str = (char *)wmem_alloc(wmem_epan_scope(), 256);
     memset(accept_str, 0x00, 256);
     for (i = 0; chr[i]; i++)
-        accept_str[(unsigned) chr[i]] = 0xFF;
+        accept_str[(unsigned)chr[i]] = (char)0xFF;
 
     w->condition = cond_chars_common;
     w->id = id;
@@ -249,10 +251,10 @@ static int cond_not_char(tvbparse_t* tt, const int offset, const tvbparse_wanted
     gboolean not_matched = FALSE;
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) g_warning("cond_not_char: control='%s'",wanted->control.str);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) ws_g_warning("cond_not_char: control='%s'",wanted->control.str);
 #endif
 
-    if (! offset < tt->end_offset ) {
+    if ( offset >= tt->end_offset ) {
         return -1;
     }
 
@@ -269,7 +271,7 @@ static int cond_not_char(tvbparse_t* tt, const int offset, const tvbparse_wanted
     } else {
         *tok =  new_tok(tt,wanted->id,offset,1,wanted);
 #ifdef TVBPARSE_DEBUG
-        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) g_warning("cond_not_char: GOT='%c'",t);
+        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) ws_g_warning("cond_not_char: GOT='%c'",t);
 #endif
         return 1;
     }
@@ -280,7 +282,7 @@ tvbparse_wanted_t* tvbparse_not_char(const int id,
                                      const void* data,
                                      tvbparse_action_t before_cb,
                                      tvbparse_action_t after_cb) {
-    tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
+    tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
 
     w->condition = cond_not_char;
     w->id = id;
@@ -300,12 +302,12 @@ tvbparse_wanted_t* tvbparse_not_chars(const int id,
                                       tvbparse_action_t before_cb,
                                       tvbparse_action_t after_cb)
 {
-    tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
+    tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
     char *accept_str;
     gsize i;
 
     /* cond_chars_common() use accept string, so mark all elements with, and later unset from reject */
-    accept_str = g_malloc(256);
+    accept_str = (char *)wmem_alloc(wmem_epan_scope(), 256);
     memset(accept_str, 0xFF, 256);
     for (i = 0; chr[i]; i++)
         accept_str[(unsigned) chr[i]] = '\0';
@@ -327,7 +329,7 @@ tvbparse_wanted_t* tvbparse_not_chars(const int id,
 static int cond_string(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
     int len = wanted->len;
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: control='%s'",wanted->control.str);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) ws_g_warning("cond_string: control='%s'",wanted->control.str);
 #endif
 
     if ( offset + wanted->len > tt->end_offset )
@@ -336,7 +338,7 @@ static int cond_string(tvbparse_t* tt, const int offset, const tvbparse_wanted_t
     if ( tvb_strneql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
         *tok = new_tok(tt,wanted->id,offset,len,wanted);
 #ifdef TVBPARSE_DEBUG
-        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: GOT len=%i",len);
+        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) ws_g_warning("cond_string: GOT len=%i",len);
 #endif
         return len;
     } else {
@@ -349,7 +351,7 @@ tvbparse_wanted_t* tvbparse_string(const int id,
                                    const void* data,
                                    tvbparse_action_t before_cb,
                                    tvbparse_action_t after_cb) {
-    tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
+    tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
 
     w->condition = cond_string;
     w->id = id;
@@ -365,7 +367,7 @@ tvbparse_wanted_t* tvbparse_string(const int id,
 static int cond_casestring(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
     int len = wanted->len;
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: control='%s'",wanted->control.str);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) ws_g_warning("cond_casestring: control='%s'",wanted->control.str);
 #endif
 
     if ( offset + len > tt->end_offset )
@@ -374,7 +376,7 @@ static int cond_casestring(tvbparse_t* tt, const int offset, const tvbparse_want
     if ( tvb_strncaseeql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
         *tok = new_tok(tt,wanted->id,offset,len,wanted);
 #ifdef TVBPARSE_DEBUG
-        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: GOT len=%i",len);
+        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) ws_g_warning("cond_casestring: GOT len=%i",len);
 #endif
         return len;
     } else {
@@ -388,7 +390,7 @@ tvbparse_wanted_t* tvbparse_casestring(const int id,
                                        const void* data,
                                        tvbparse_action_t before_cb,
                                        tvbparse_action_t after_cb) {
-    tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
+    tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
 
     w->condition = cond_casestring;
     w->id = id;
@@ -404,12 +406,15 @@ tvbparse_wanted_t* tvbparse_casestring(const int id,
 static int cond_one_of(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
     guint i;
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) g_warning("cond_one_of: START");
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) ws_g_warning("cond_one_of: 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;
@@ -424,21 +429,31 @@ static int cond_one_of(tvbparse_t* tt, const int offset, const tvbparse_wanted_t
             *tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted);
             (*tok)->sub = new_elem;
 #ifdef TVBPARSE_DEBUG
-            if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) g_warning("cond_one_of: GOT len=%i",curr_len);
+            if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) ws_g_warning("cond_one_of: GOT len=%i",curr_len);
 #endif
+            tt->recursion_depth--;
             return curr_len;
         }
     }
 
+    tt->recursion_depth--;
     return -1;
 }
 
+static gboolean
+tvbparse_wanted_cleanup_cb(wmem_allocator_t* allocator _U_, wmem_cb_event_t event _U_, void *user_data)
+{
+    tvbparse_wanted_t* w = (tvbparse_wanted_t *)user_data;
+    g_ptr_array_free(w->control.elems, TRUE);
+    return FALSE;
+}
+
 tvbparse_wanted_t* tvbparse_set_oneof(const int id,
                                       const void* data,
                                       tvbparse_action_t before_cb,
                                       tvbparse_action_t after_cb,
                                       ...) {
-    tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
+    tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
     tvbparse_t* el;
     va_list ap;
 
@@ -448,6 +463,7 @@ tvbparse_wanted_t* tvbparse_set_oneof(const int id,
     w->before = before_cb;
     w->after = after_cb;
     w->control.elems = g_ptr_array_new();
+    wmem_register_callback(wmem_epan_scope(), tvbparse_wanted_cleanup_cb, w);
 
     va_start(ap,after_cb);
 
@@ -471,32 +487,42 @@ static int cond_hash(tvbparse_t* tt, const int offset, const tvbparse_wanted_t*
     tvbparse_elem_t* ret_tok;
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: START");
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) ws_g_warning("cond_hash: START");
 #endif
 
     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)
+    if (key_len < 0) {
+        tt->recursion_depth--;
         return -1;
+    }
 
-    key = tvb_get_string(wmem_packet_scope(),key_elem->tvb,key_elem->offset,key_elem->len);
+    key = tvb_get_string_enc(wmem_packet_scope(),key_elem->tvb,key_elem->offset,key_elem->len, ENC_ASCII);
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: got key='%s'",key);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) ws_g_warning("cond_hash: got key='%s'",key);
 #endif
 
-    if ((value_wanted = (tvbparse_wanted_t *)g_hash_table_lookup(wanted->control.hash.table,key))) {
+    if ((value_wanted = (tvbparse_wanted_t *)wmem_map_lookup(wanted->control.hash.table,key))) {
         value_len = value_wanted->condition(tt, offset + key_len, value_wanted,  &value_elem);
     } else if (wanted->control.hash.other) {
         value_len = wanted->control.hash.other->condition(tt, offset+key_len, wanted->control.hash.other,  &value_elem);
-        if (value_len < 0)
+        if (value_len < 0) {
+            tt->recursion_depth--;
             return -1;
+        }
     } else {
+        tt->recursion_depth--;
         return -1;
     }
 
+    tt->recursion_depth--;
+
     tot_len = key_len + value_len;
 
     ret_tok = new_tok(tt, value_elem->id, offset, tot_len, wanted);
@@ -505,7 +531,7 @@ static int cond_hash(tvbparse_t* tt, const int offset, const tvbparse_wanted_t*
 
     *tok = ret_tok;
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: GOT len=%i",tot_len);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) ws_g_warning("cond_hash: GOT len=%i",tot_len);
 #endif
 
     return tot_len;
@@ -518,7 +544,7 @@ tvbparse_wanted_t* tvbparse_hashed(const int id,
                                    tvbparse_wanted_t* key,
                                    tvbparse_wanted_t* other,
                                    ...) {
-    tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
+    tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
     gchar* name;
     tvbparse_wanted_t* el;
     va_list ap;
@@ -528,7 +554,7 @@ tvbparse_wanted_t* tvbparse_hashed(const int id,
     w->data = data;
     w->before = before_cb;
     w->after = after_cb;
-    w->control.hash.table = g_hash_table_new(g_str_hash,g_str_equal);
+    w->control.hash.table = wmem_map_new(wmem_epan_scope(), g_str_hash,g_str_equal);
     w->control.hash.key = key;
     w->control.hash.other = other;
 
@@ -536,7 +562,7 @@ tvbparse_wanted_t* tvbparse_hashed(const int id,
 
     while(( name = va_arg(ap,gchar*) )) {
         el = va_arg(ap,tvbparse_wanted_t*);
-        g_hash_table_insert(w->control.hash.table,name,el);
+        wmem_map_insert(w->control.hash.table,name,el);
     }
 
     va_end(ap);
@@ -553,7 +579,7 @@ void tvbparse_hashed_add(tvbparse_wanted_t* w, ...) {
 
     while (( name = va_arg(ap,gchar*) )) {
         el = va_arg(ap,tvbparse_wanted_t*);
-        g_hash_table_insert(w->control.hash.table,name,el);
+        wmem_map_insert(w->control.hash.table,name,el);
     }
 
     va_end(ap);
@@ -565,25 +591,31 @@ 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) g_warning("cond_seq: START");
+    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;
 
-        if ( offset + w->len > tt->end_offset )
+        if ( offset + w->len > tt->end_offset ) {
+            tt->recursion_depth--;
             return -1;
-
+        }
 
         len = w->condition(tt, offset, w, &new_elem);
 
         if (len >= 0) {
             if (ret_tok) {
-                ret_tok->len = (new_elem->offset - ret_tok->offset) + new_elem->len;
+                if (new_elem->len)
+                    ret_tok->len = (new_elem->offset - ret_tok->offset) + new_elem->len;
                 ret_tok->sub->last->next = new_elem;
                 ret_tok->sub->last = new_elem;
             } else {
@@ -592,6 +624,7 @@ static int cond_seq(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted
                 new_elem->last = new_elem;
             }
         } else {
+            tt->recursion_depth--;
             return -1;
         }
 
@@ -599,10 +632,12 @@ static int cond_seq(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted
         offset += ignore_fcn(tt,offset);
     }
 
+    tt->recursion_depth--;
+
     *tok = ret_tok;
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) g_warning("cond_seq: GOT len=%i",offset - start);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) ws_g_warning("cond_seq: GOT len=%i",offset - start);
 #endif
 
     return offset - start;
@@ -614,7 +649,7 @@ tvbparse_wanted_t* tvbparse_set_seq(const int id,
                                     tvbparse_action_t before_cb,
                                     tvbparse_action_t after_cb,
                                     ...) {
-    tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
+    tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
     tvbparse_wanted_t*  el = NULL;
     va_list ap;
 
@@ -624,6 +659,7 @@ tvbparse_wanted_t* tvbparse_set_seq(const int id,
     w->before = before_cb;
     w->after = after_cb;
     w->control.elems = g_ptr_array_new();
+    wmem_register_callback(wmem_epan_scope(), tvbparse_wanted_cleanup_cb, w);
 
     va_start(ap,after_cb);
 
@@ -640,12 +676,15 @@ static int cond_some(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wante
     int start = offset;
     tvbparse_elem_t* ret_tok = NULL;
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: START");
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) ws_g_warning("cond_some: START");
 #endif
 
     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);
     }
@@ -654,14 +693,17 @@ static int cond_some(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wante
         tvbparse_elem_t* new_elem = NULL;
         int consumed;
 
-        if ( offset > tt->end_offset )
+        if ( offset > tt->end_offset ) {
+            tt->recursion_depth--;
             return -1;
+        }
 
         consumed = wanted->control.subelem->condition(tt, offset, wanted->control.subelem, &new_elem);
 
         if(consumed >= 0) {
             if (ret_tok) {
-                ret_tok->len = (new_elem->offset - ret_tok->offset) + new_elem->len;
+                if (new_elem->len)
+                    ret_tok->len = (new_elem->offset - ret_tok->offset) + new_elem->len;
 
                 if (ret_tok->sub) {
                     ret_tok->sub->last->next = new_elem;
@@ -681,8 +723,10 @@ static int cond_some(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wante
         got_so_far++;
     }
 
+    tt->recursion_depth--;
+
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: got num=%u",got_so_far);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) ws_g_warning("cond_some: got num=%u",got_so_far);
 #endif
 
     if(got_so_far < wanted->min) {
@@ -691,7 +735,7 @@ static int cond_some(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wante
 
     *tok = ret_tok;
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: GOT len=%i",offset - start);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) ws_g_warning("cond_some: GOT len=%i",offset - start);
 #endif
     return offset - start;
 }
@@ -704,7 +748,7 @@ tvbparse_wanted_t* tvbparse_some(const int id,
                                  tvbparse_action_t after_cb,
                                  const tvbparse_wanted_t* el) {
 
-    tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
+    tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
 
     g_assert(from <= to);
 
@@ -726,16 +770,21 @@ static int cond_until(tvbparse_t* tt, const int offset, const tvbparse_wanted_t
     int len = 0;
     int target_offset = offset;
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: START");
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) ws_g_warning("cond_until: START");
 #endif
 
     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);
 
+    tt->recursion_depth--;
+
     if (len >= 0) {
 
         new_elem->id = wanted->id;
@@ -750,19 +799,19 @@ static int cond_until(tvbparse_t* tt, const int offset, const tvbparse_wanted_t
             case TP_UNTIL_INCLUDE:
                 new_elem->len = target_offset - offset - 1 + len;
 #ifdef TVBPARSE_DEBUG
-                if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
+                if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) ws_g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
 #endif
                 return target_offset - offset -1 + len;
             case TP_UNTIL_SPEND:
                 new_elem->len = target_offset - offset - 1;
 #ifdef TVBPARSE_DEBUG
-                if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
+                if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) ws_g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
 #endif
                 return target_offset - offset - 1 + len;
             case TP_UNTIL_LEAVE:
                 new_elem->len = target_offset - offset - 1;
 #ifdef TVBPARSE_DEBUG
-                if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1);
+                if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) ws_g_warning("cond_until: GOT len=%i",target_offset - offset -1);
 #endif
                 return target_offset - offset -1;
             default:
@@ -781,7 +830,7 @@ tvbparse_wanted_t* tvbparse_until(const int id,
                                   tvbparse_action_t after_cb,
                                   const tvbparse_wanted_t* el,
                                   until_mode_t until_mode) {
-    tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
+    tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
 
     w->condition = cond_until;
     w->control.until.mode = until_mode;
@@ -862,7 +911,7 @@ static int cond_ft(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted,
     }
 }
 
-gint ft_lens[] = {-1,-1,-1, 1, 2, 3, 4, 8, 1, 2, 3, 4, 8, 4, 8,-1,-1,-1, 0, -1, 6, -1, -1, 4, sizeof(struct e_in6_addr), -1, -1, -1, -1 };
+gint ft_lens[] = {-1,-1,-1, 1, 2, 3, 4, 8, 1, 2, 3, 4, 8, 4, 8,-1,-1,-1, 0, -1, 6, -1, -1, 4, sizeof(ws_in6_addr), -1, -1, -1, -1 };
 
 tvbparse_wanted_t* tvbparse_ft(int id,
                                const void* data,
@@ -926,127 +975,127 @@ static gboolean comp_le_f(void* lp, const void* rp) { return ( *((gdouble*)lp) <
 static gboolean comp_lt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) < *((gdouble*)rp) ); }
 
 static void* extract_u8(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_guint8(tvb,offset);
     return p;
 }
 
 static void* extract_uns(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_ntohs(tvb,offset);
     return p;
 }
 
 static void* extract_un24(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_ntoh24(tvb,offset);
     return p;
 }
 
 static void* extract_unl(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_ntohl(tvb,offset);
     return p;
 }
 
 static void* extract_un64(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_ntoh64(tvb,offset);
     return p;
 }
 
 static void* extract_ules(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_letohs(tvb,offset);
     return p;
 }
 
 static void* extract_ule24(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_letoh24(tvb,offset);
     return p;
 }
 
 static void* extract_ulel(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_letohl(tvb,offset);
     return p;
 }
 
 static void* extract_ule64(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_letoh64(tvb,offset);
     return p;
 }
 
 static void* extract_ins(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_ntohs(tvb,offset);
     return p;
 }
 
 static void* extract_in24(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_ntoh24(tvb,offset);
     return p;
 }
 
 static void* extract_inl(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_ntohl(tvb,offset);
     return p;
 }
 
 static void* extract_in64(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_ntoh64(tvb,offset);
     return p;
 }
 
 static void* extract_iles(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_letohs(tvb,offset);
     return p;
 }
 
 static void* extract_ile24(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_letoh24(tvb,offset);
     return p;
 }
 
 static void* extract_ilel(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_letohl(tvb,offset);
     return p;
 }
 
 static void* extract_ile64(tvbuff_t* tvb, guint offset) {
-    guint64* p = ep_new(guint64);
+    guint64* p = wmem_new(wmem_packet_scope(), guint64);
     *p = tvb_get_letoh64(tvb,offset);
     return p;
 }
 
 static void* extract_inf(tvbuff_t* tvb, guint offset) {
-    gdouble* p = ep_new(gdouble);
+    gdouble* p = wmem_new(wmem_packet_scope(), gdouble);
     *p = tvb_get_ntohieee_float(tvb,offset);
     return p;
 }
 
 static void* extract_ind(tvbuff_t* tvb, guint offset) {
-    gdouble* p = ep_new(gdouble);
+    gdouble* p = wmem_new(wmem_packet_scope(), gdouble);
     *p = tvb_get_ntohieee_double(tvb,offset);
     return p;
 }
 
 static void* extract_ilef(tvbuff_t* tvb, guint offset) {
-    gdouble* p = ep_new(gdouble);
+    gdouble* p = wmem_new(wmem_packet_scope(), gdouble);
     *p = tvb_get_letohieee_float(tvb,offset);
     return p;
 }
 
 static void* extract_iled(tvbuff_t* tvb, guint offset) {
-    gdouble* p = ep_new(gdouble);
+    gdouble* p = wmem_new(wmem_packet_scope(), gdouble);
     *p = tvb_get_letohieee_double(tvb,offset);
     return p;
 }
@@ -1143,8 +1192,8 @@ tvbparse_wanted_t* tvbparse_quoted(const int id,
                                    const char quote,
                                    const char esc) {
 
-    gchar* esc_quot = g_strdup_printf("%c%c",esc,quote);
-    gchar* quot = g_strdup_printf("%c",quote);
+    gchar* esc_quot = wmem_strdup_printf(wmem_epan_scope(), "%c%c",esc,quote);
+    gchar* quot = wmem_strdup_printf(wmem_epan_scope(), "%c",quote);
     tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL);
 
     return tvbparse_set_oneof(id, data, before_cb, after_cb,
@@ -1180,7 +1229,7 @@ tvbparse_t* tvbparse_init(tvbuff_t* tvb,
     tvbparse_t* tt = (tvbparse_t *)wmem_new(wmem_packet_scope(), tvbparse_t);
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) g_warning("tvbparse_init: offset=%i len=%i",offset,len);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) ws_g_warning("tvbparse_init: offset=%i len=%i",offset,len);
 #endif
 
 
@@ -1190,6 +1239,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;
 }
 
@@ -1198,7 +1248,7 @@ gboolean tvbparse_reset(tvbparse_t* tt,
                         int len) {
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) g_warning("tvbparse_init: offset=%i len=%i",offset,len);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) ws_g_warning("tvbparse_init: offset=%i len=%i",offset,len);
 #endif
 
     len = (len == -1) ? (int) tvb_captured_length(tt->tvb) : len;
@@ -1222,7 +1272,7 @@ static void execute_callbacks(tvbparse_t* tt, tvbparse_elem_t* curr) {
     while (curr) {
         if(curr->wanted->before) {
 #ifdef TVBPARSE_DEBUG
-            if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: BEFORE: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
+            if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) ws_g_warning("execute_callbacks: BEFORE: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
 #endif
             curr->wanted->before(tt->data, curr->wanted->data, curr);
         }
@@ -1233,7 +1283,7 @@ static void execute_callbacks(tvbparse_t* tt, tvbparse_elem_t* curr) {
             continue;
         } else {
 #ifdef TVBPARSE_DEBUG
-            if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
+            if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) ws_g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
 #endif
             if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr);
         }
@@ -1243,7 +1293,7 @@ static void execute_callbacks(tvbparse_t* tt, tvbparse_elem_t* curr) {
         while( !curr && wmem_stack_count(stack) > 0 ) {
             curr = (tvbparse_elem_t *)wmem_stack_pop(stack);
 #ifdef TVBPARSE_DEBUG
-            if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
+            if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) ws_g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
 #endif
             if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr);
             curr = curr->next;
@@ -1259,25 +1309,25 @@ gboolean tvbparse_peek(tvbparse_t* tt,
     int offset = tt->offset;
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: ENTER offset=%i",offset);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) ws_g_warning("tvbparse_peek: ENTER offset=%i",offset);
 #endif
 
     offset += ignore_fcn(tt,offset);
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: after ignore offset=%i",offset);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) ws_g_warning("tvbparse_peek: after ignore offset=%i",offset);
 #endif
 
     consumed = wanted->condition(tt,offset,wanted,&tok);
 
     if (consumed >= 0) {
 #ifdef TVBPARSE_DEBUG
-        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: GOT len=%i",consumed);
+        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) ws_g_warning("tvbparse_peek: GOT len=%i",consumed);
 #endif
         return TRUE;
     } else {
 #ifdef TVBPARSE_DEBUG
-        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: NOT GOT");
+        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) ws_g_warning("tvbparse_peek: NOT GOT");
 #endif
         return FALSE;
     }
@@ -1291,25 +1341,25 @@ tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
     int offset = tt->offset;
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: ENTER offset=%i",offset);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) ws_g_warning("tvbparse_get: ENTER offset=%i",offset);
 #endif
 
     offset += ignore_fcn(tt,offset);
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: after ignore offset=%i",offset);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) ws_g_warning("tvbparse_get: after ignore offset=%i",offset);
 #endif
 
     consumed = wanted->condition(tt,offset,wanted,&tok);
 
     if (consumed >= 0) {
 #ifdef TVBPARSE_DEBUG
-        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: GOT len=%i",consumed);
+        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) ws_g_warning("tvbparse_get: GOT len=%i",consumed);
 #endif
         execute_callbacks(tt,tok);
         tt->offset = offset + consumed;
 #ifdef TVBPARSE_DEBUG
-        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: DONE offset=%i", tt->offset);
+        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) ws_g_warning("tvbparse_get: DONE offset=%i", tt->offset);
 #endif
         return tok;
     } else {
@@ -1326,7 +1376,7 @@ tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted)
     int target_offset = offset -1;
 
 #ifdef TVBPARSE_DEBUG
-    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: ENTER offset=%i", tt->offset);
+    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) ws_g_warning("tvbparse_get: ENTER offset=%i", tt->offset);
 #endif
 
     do {
@@ -1335,18 +1385,18 @@ tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted)
 
     if (len >= 0) {
 #ifdef TVBPARSE_DEBUG
-        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: FOUND offset=%i len=%i", target_offset,len);
+        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) ws_g_warning("tvbparse_get: FOUND offset=%i len=%i", target_offset,len);
 #endif
         execute_callbacks(tt,tok);
         tt->offset = target_offset + len;
 
 #ifdef TVBPARSE_DEBUG
-        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: DONE offset=%i", tt->offset);
+        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) ws_g_warning("tvbparse_get: DONE offset=%i", tt->offset);
 #endif
         return tok;
     } else {
 #ifdef TVBPARSE_DEBUG
-        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: NOT FOUND");
+        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) ws_g_warning("tvbparse_get: NOT FOUND");
 #endif
         return NULL;
     }
@@ -1365,7 +1415,7 @@ void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr) {
     frame->elem = curr;
 
     while (curr) {
-        pi = proto_tree_add_text(frame->tree,curr->tvb,curr->offset,curr->len,"%s",tvb_format_text(curr->tvb,curr->offset,curr->len));
+        pi = proto_tree_add_format_text(frame->tree,curr->tvb,curr->offset,curr->len);
 
         if(curr->sub) {
             frame->elem = curr;
@@ -1386,3 +1436,15 @@ void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr) {
     }
 }
 
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */