diff options
Diffstat (limited to 'epan/wslua/wslua_proto.c')
-rw-r--r-- | epan/wslua/wslua_proto.c | 261 |
1 files changed, 184 insertions, 77 deletions
diff --git a/epan/wslua/wslua_proto.c b/epan/wslua/wslua_proto.c index b7f170d7..6b91e1ca 100644 --- a/epan/wslua/wslua_proto.c +++ b/epan/wslua/wslua_proto.c @@ -40,7 +40,7 @@ typedef struct _func_saver { int dissect_ref; } func_saver_t; -static GPtrArray* outstanding_FuncSavers = NULL; +static GPtrArray* outstanding_FuncSavers; void clear_outstanding_FuncSavers(void) { while (outstanding_FuncSavers->len) { @@ -70,11 +70,11 @@ static int protocols_table_ref = LUA_NOREF; WSLUA_CONSTRUCTOR Proto_new(lua_State* L) { /* Creates a new <<lua_class_Proto,`Proto`>> object. */ #define WSLUA_ARG_Proto_new_NAME 1 /* The name of the protocol. */ -#define WSLUA_ARG_Proto_new_DESC 2 /* A Long Text description of the protocol (usually lowercase). */ - const gchar* name = luaL_checkstring(L,WSLUA_ARG_Proto_new_NAME); - const gchar* desc = luaL_checkstring(L,WSLUA_ARG_Proto_new_DESC); +#define WSLUA_ARG_Proto_new_DESCRIPTION 2 /* A Long Text description of the protocol (usually lowercase). */ + const char* name = luaL_checkstring(L,WSLUA_ARG_Proto_new_NAME); + const char* desc = luaL_checkstring(L,WSLUA_ARG_Proto_new_DESCRIPTION); Proto proto; - gchar *loname, *hiname; + char *loname, *hiname; /* TODO: should really make a common function for all of wslua that does checkstring and non-empty at same time */ if (!name[0]) { @@ -83,12 +83,12 @@ WSLUA_CONSTRUCTOR Proto_new(lua_State* L) { /* Creates a new <<lua_class_Proto,` } if (!desc[0]) { - WSLUA_ARG_ERROR(Proto_new,DESC,"must not be an empty string"); + WSLUA_ARG_ERROR(Proto_new,DESCRIPTION,"must not be an empty string"); return 0; } if (proto_name_already_registered(desc)) { - WSLUA_ARG_ERROR(Proto_new,DESC,"there cannot be two protocols with the same description"); + WSLUA_ARG_ERROR(Proto_new,DESCRIPTION,"there cannot be two protocols with the same description"); return 0; } @@ -116,8 +116,8 @@ WSLUA_CONSTRUCTOR Proto_new(lua_State* L) { /* Creates a new <<lua_class_Proto,` proto->desc = g_strdup(desc); proto->hfid = proto_register_protocol(proto->desc,hiname,loname); proto->ett = -1; - proto->is_postdissector = FALSE; - proto->expired = FALSE; + proto->is_postdissector = false; + proto->expired = false; lua_newtable (L); proto->fields = luaL_ref(L, LUA_REGISTRYINDEX); @@ -150,7 +150,7 @@ WSLUA_CONSTRUCTOR Proto_new(lua_State* L) { /* Creates a new <<lua_class_Proto,` WSLUA_METAMETHOD Proto__call(lua_State* L) { /* Creates a <<lua_class_Proto,`Proto`>> object. */ #define WSLUA_ARG_Proto__call_NAME 1 /* The name of the protocol. */ -#define WSLUA_ARG_Proto__call_DESC 2 /* A Long Text description of the protocol (usually lowercase). */ +#define WSLUA_ARG_Proto__call_DESCRIPTION 2 /* A Long Text description of the protocol (usually lowercase). */ lua_remove(L,1); /* remove the table */ WSLUA_RETURN(Proto_new(L)); /* The new <<lua_class_Proto,`Proto`>> object. */ } @@ -171,7 +171,7 @@ WSLUA_FUNCTION wslua_register_postdissector(lua_State* L) { Note: This impacts performance (default=false). */ Proto proto = checkProto(L,WSLUA_ARG_register_postdissector_PROTO); - const gboolean all_fields = wslua_optbool(L, WSLUA_OPTARG_register_postdissector_ALLFIELDS, FALSE); + const bool all_fields = wslua_optbool(L, WSLUA_OPTARG_register_postdissector_ALLFIELDS, false); if(!proto->is_postdissector) { if (! proto->handle) { @@ -179,7 +179,7 @@ WSLUA_FUNCTION wslua_register_postdissector(lua_State* L) { } register_postdissector(proto->handle); - proto->is_postdissector = TRUE; + proto->is_postdissector = true; } else { luaL_argerror(L,1,"this protocol is already registered as postdissector"); } @@ -195,7 +195,7 @@ WSLUA_FUNCTION wslua_register_postdissector(lua_State* L) { * * If not, this is overkill. */ - epan_set_always_visible(TRUE); + epan_set_always_visible(true); } return 0; @@ -222,8 +222,6 @@ WSLUA_METHOD Proto_register_heuristic(lua_State* L) { it will be treated the same as a `false` return for the heuristic; if a positive or negative number is returned, then the it will be treated the same as a `true` return for the heuristic, meaning the packet is for this protocol and no other heuristic will be tried. - - @since 1.11.3 */ #define WSLUA_ARG_Proto_register_heuristic_LISTNAME 2 /* The heuristic list name this function is a heuristic for (e.g., "udp" or @@ -231,11 +229,11 @@ WSLUA_METHOD Proto_register_heuristic(lua_State* L) { #define WSLUA_ARG_Proto_register_heuristic_FUNC 3 /* A Lua function that will be invoked for heuristic dissection. */ Proto proto = checkProto(L,1); - const gchar *listname = luaL_checkstring(L, WSLUA_ARG_Proto_register_heuristic_LISTNAME); - const gchar *proto_name = proto->name; + const char *listname = luaL_checkstring(L, WSLUA_ARG_Proto_register_heuristic_LISTNAME); + const char *proto_name = proto->name; const int top _U_ = lua_gettop(L); - gchar *short_name; + char *short_name; if (!proto_name || proto->hfid == -1) { /* this shouldn't happen - internal bug if it does */ @@ -432,18 +430,78 @@ static int Proto_get_fields(lua_State* L) { return 1; } +static bool Proto_append_ProtoField(Proto proto, ProtoField f) { + + if (f->hfid != -2) { + // Already registered + return false; + } + hf_register_info hfri = { NULL, { NULL, NULL, FT_NONE, 0, NULL, 0, NULL, HFILL } }; + int* ettp = NULL; + ettp = &(f->ett); + + hfri.p_id = &(f->hfid); + hfri.hfinfo.name = f->name; + hfri.hfinfo.abbrev = f->abbrev; + hfri.hfinfo.type = f->type; + hfri.hfinfo.display = f->base; + hfri.hfinfo.strings = VALS(f->vs); + hfri.hfinfo.bitmask = f->mask; + hfri.hfinfo.blurb = f->blob; + + f->hfid = -1; + g_array_append_val(proto->hfa,hfri); + g_array_append_val(proto->etta,ettp); + + return true; +} + static int Proto_set_fields(lua_State* L) { Proto proto = checkProto(L,1); #define FIELDS_TABLE 2 #define NEW_TABLE 3 #define NEW_FIELD 3 + /* + * XXX - This is a "setter", but it really appends any ProtoFields to + * the Lua Table without removing any existing ones. + */ + + if (proto->hfa) { + /* This Proto's ProtoFields were already registered in Proto_commit. + * Deregister the existing array with epan so we can add new ones. + * (Appending to the GArray and registering only the new ones would + * have a use-after-free, for reasons mentioned in proto.c ) + * XXX - What is the reason for waiting and registering all + * at once in Proto_commit instead of doing it here every time? + */ + if (proto->hfa->len) { + proto_add_deregistered_data(g_array_free(proto->hfa,false)); + } else { + g_array_free(proto->hfa,true); + } + /* No need for deferred deletion of subtree indexes */ + g_array_free(proto->etta,true); + proto->hfa = g_array_new(true,true,sizeof(hf_register_info)); + proto->etta = g_array_new(true,true,sizeof(int*)); + } + lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields); lua_insert(L,FIELDS_TABLE); if( lua_istable(L,NEW_TABLE)) { for (lua_pushnil(L); lua_next(L, NEW_TABLE); ) { if (isProtoField(L,5)) { + if (proto->hfa) { + ProtoField f = toProtoField(L,5); + // XXX this will leak resources on error + // If this continued and registered the field array, it + // wouldn't leak. We could perhaps print a warning or even + // err after registration. + if (!Proto_append_ProtoField(proto, f)) { + return luaL_error(L,"%s is already registered; fields can be registered only once", f->abbrev); + } + } /* luaL_ref returns a reference. lua_next will return not * just occupied entries in the table, but also references * used to store unused/deleted entries in the hash table @@ -476,6 +534,16 @@ static int Proto_set_fields(lua_State* L) { } } } else if (isProtoField(L,NEW_FIELD)){ + if (proto->hfa) { + ProtoField f = toProtoField(L,NEW_FIELD); + // XXX this will leak resources on error + // If this continued and registered the field array, it wouldn't + // leak. We could perhaps print a warning or even err after + // registration. + if (!Proto_append_ProtoField(proto, f)) { + return luaL_error(L,"%s is already registered; fields can be registered only once", f->abbrev); + } + } lua_pushvalue(L, NEW_FIELD); luaL_ref(L,FIELDS_TABLE); @@ -483,40 +551,94 @@ static int Proto_set_fields(lua_State* L) { return luaL_error(L,"either a ProtoField or an array of protofields"); } - /* XXX - I don't think this is necessary. */ + if (proto->hfa && proto->hfa->len) { + /* register the proto fields */ + proto_register_field_array(proto->hfid,&g_array_index(proto->hfa, hf_register_info, 0),proto->hfa->len); + proto_register_subtree_array(&g_array_index(proto->etta, int*, 0),proto->etta->len); + } + lua_pushvalue(L, 3); return 1; } -/* WSLUA_ATTRIBUTE Proto_experts RW The expert info Lua table of this `Proto`. - - @since 1.11.3 - */ +/* WSLUA_ATTRIBUTE Proto_experts RW The expert info Lua table of this `Proto`. */ static int Proto_get_experts(lua_State* L) { Proto proto = checkProto(L,1); lua_rawgeti(L, LUA_REGISTRYINDEX, proto->expert_info_table_ref); return 1; } +static bool Proto_append_ProtoExpert(Proto proto, ProtoExpert e) { + + if (e->ids.ei != EI_INIT_EI || e->ids.hf != -2) { + return false; + } + ei_register_info eiri = { NULL, { NULL, 0, 0, NULL, EXPFILL } }; + + eiri.ids = &(e->ids); + eiri.eiinfo.name = e->abbrev; + eiri.eiinfo.group = e->group; + eiri.eiinfo.severity = e->severity; + eiri.eiinfo.summary = e->text; + + e->ids.hf = -1; + g_array_append_val(proto->eia,eiri); + + return true; +} + static int Proto_set_experts(lua_State* L) { Proto proto = checkProto(L,1); #define EI_TABLE 2 #define NEW_TABLE 3 #define NEW_FIELD 3 + /* + * XXX - This is a "setter", but it really appends any ProtoExperts to + * the Lua Table without removing any existing ones. + */ + + if (proto->eia) { + /* This Proto's ProtoExperts were already registered in Proto_commit. + * Deregister the existing array with epan so we can add new ones. + * XXX - What is the reason for waiting and registering all at + * at once in Proto_commit instead of doing it here every time? + */ + if (proto->eia && proto->eia->len) { + proto_add_deregistered_data(g_array_free(proto->eia,false)); + } else { + g_array_free(proto->eia,true); + } + proto->eia = g_array_new(true,true,sizeof(ei_register_info)); + } + lua_rawgeti(L, LUA_REGISTRYINDEX, proto->expert_info_table_ref); lua_insert(L,EI_TABLE); if( lua_istable(L,NEW_TABLE)) { for (lua_pushnil(L); lua_next(L, NEW_TABLE); ) { if (isProtoExpert(L,5)) { + if (proto->eia) { + ProtoExpert e = toProtoExpert(L, NEW_FIELD); + + if (!Proto_append_ProtoExpert(proto, e)) { + return luaL_error(L,"%s is already registered; expert fields can be registered only once", e->abbrev); + } + } luaL_ref(L,EI_TABLE); } else if (! lua_isnil(L,5) ) { return luaL_error(L,"only ProtoExperts should be in the table"); } } } else if (isProtoExpert(L,NEW_FIELD)){ + if (proto->eia) { + ProtoExpert e = toProtoExpert(L, NEW_FIELD); + + if (!Proto_append_ProtoExpert(proto, e)) { + return luaL_error(L,"%s is already registered; expert fields can be registered only once", e->abbrev); + } + } lua_pushvalue(L, NEW_FIELD); luaL_ref(L,EI_TABLE); @@ -537,7 +659,7 @@ static int Proto__gc(lua_State* L) { Proto proto = toProto(L,1); if (!proto->expired) { - proto->expired = TRUE; + proto->expired = true; } else if (proto->hfid == -2) { /* Only free deregistered Proto */ g_free(proto); @@ -577,6 +699,9 @@ WSLUA_META Proto_meta[] = { int Proto_register(lua_State* L) { WSLUA_REGISTER_CLASS_WITH_ATTRS(Proto); + if (outstanding_FuncSavers != NULL) { + g_ptr_array_unref(outstanding_FuncSavers); + } outstanding_FuncSavers = g_ptr_array_new(); lua_newtable(L); @@ -624,9 +749,9 @@ int wslua_deregister_heur_dissectors(lua_State* L) { /* for each registered heur dissector do... */ lua_rawgeti(L, LUA_REGISTRYINDEX, lua_heur_dissectors_table_ref); for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { - const gchar *listname = luaL_checkstring(L, -2); + const char *listname = luaL_checkstring(L, -2); for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { - const gchar *proto_name = luaL_checkstring(L, -2); + const char *proto_name = luaL_checkstring(L, -2); int proto_id = proto_get_id_by_short_name(proto_name); heur_dissector_delete(listname, heur_dissect_lua, proto_id); } @@ -698,18 +823,18 @@ int wslua_deregister_protocols(lua_State* L) { lua_pop(L, 1); if (proto->hfa && proto->hfa->len) { - proto_add_deregistered_data(g_array_free(proto->hfa,FALSE)); + proto_add_deregistered_data(g_array_free(proto->hfa,false)); } else { - g_array_free(proto->hfa,TRUE); + g_array_free(proto->hfa,true); } /* No need for deferred deletion of subtree indexes */ - g_array_free(proto->etta,TRUE); + g_array_free(proto->etta,true); if (proto->eia && proto->eia->len) { - proto_add_deregistered_data(g_array_free(proto->eia,FALSE)); + proto_add_deregistered_data(g_array_free(proto->eia,false)); } else { - g_array_free(proto->eia,TRUE); + g_array_free(proto->eia,true); } proto->hfid = -2; /* Deregister Proto, freed in Proto__gc */ @@ -726,19 +851,24 @@ int Proto_commit(lua_State* L) { lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref); /* for each registered Proto protocol do... */ - for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 2)) { + for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) { /* lua_next() pop'ed the nil, pushed a table entry key at index=2, with value at index=3. In our case, the key is the Proto's name, and the value is the Proto object. - At next iteration, the value (Proto object) and ProtoExperts table will be pop'ed due - to lua_pop(L, 2), and when lua_next() returns 0 (no more table entries), it will have + At next iteration, the value (Proto object) will be pop'ed due + to lua_pop(L, 1), and when lua_next() returns 0 (no more table entries), it will have pop'ed the final key itself, leaving just the protocols_table_ref table on the stack. */ Proto proto = checkProto(L,3); - gint* ettp = NULL; + int* ettp = NULL; - proto->hfa = g_array_new(TRUE,TRUE,sizeof(hf_register_info)); - proto->etta = g_array_new(TRUE,TRUE,sizeof(gint*)); - proto->eia = g_array_new(TRUE,TRUE,sizeof(ei_register_info)); + if (proto->hfa) { + /* This proto's ProtoFields were already registered. */ + continue; + } + + proto->hfa = g_array_new(true,true,sizeof(hf_register_info)); + proto->etta = g_array_new(true,true,sizeof(int*)); + proto->eia = g_array_new(true,true,sizeof(ei_register_info)); ettp = &(proto->ett); g_array_append_val(proto->etta,ettp); @@ -753,31 +883,19 @@ int Proto_commit(lua_State* L) { continue; } ProtoField f = checkProtoField(L,6); - hf_register_info hfri = { NULL, { NULL, NULL, FT_NONE, 0, NULL, 0, NULL, HFILL } }; - ettp = &(f->ett); - - hfri.p_id = &(f->hfid); - hfri.hfinfo.name = f->name; - hfri.hfinfo.abbrev = f->abbrev; - hfri.hfinfo.type = f->type; - hfri.hfinfo.display = f->base; - hfri.hfinfo.strings = VALS(f->vs); - hfri.hfinfo.bitmask = f->mask; - hfri.hfinfo.blurb = f->blob; - - // XXX this will leak resources. - if (f->hfid != -2) { + + // XXX this will leak resources on error + // If this continued and registered the field array, it wouldn't + // leak. We could perhaps print a warning or even err after + // registration. + if (!Proto_append_ProtoField(proto, f)) { return luaL_error(L,"%s is already registered; fields can be registered only once", f->abbrev); } - - f->hfid = -1; - g_array_append_val(proto->hfa,hfri); - g_array_append_val(proto->etta,ettp); } /* register the proto fields */ proto_register_field_array(proto->hfid,(hf_register_info*)(void*)proto->hfa->data,proto->hfa->len); - proto_register_subtree_array((gint**)(void*)proto->etta->data,proto->etta->len); + proto_register_subtree_array((int**)(void*)proto->etta->data,proto->etta->len); lua_pop(L,1); /* pop the table of ProtoFields */ @@ -793,25 +911,16 @@ int Proto_commit(lua_State* L) { continue; } ProtoExpert e = checkProtoExpert(L,6); - ei_register_info eiri = { NULL, { NULL, 0, 0, NULL, EXPFILL } }; - - eiri.ids = &(e->ids); - eiri.eiinfo.name = e->abbrev; - eiri.eiinfo.group = e->group; - eiri.eiinfo.severity = e->severity; - eiri.eiinfo.summary = e->text; - - if (e->ids.ei != EI_INIT_EI || e->ids.hf != -2) { + if (!Proto_append_ProtoExpert(proto, e)) { return luaL_error(L,"%s is already registered; expert fields can be registered only once", e->abbrev); } - - e->ids.hf = -1; - g_array_append_val(proto->eia,eiri); } expert_register_field_array(proto->expert_module, (ei_register_info*)(void*)proto->eia->data, proto->eia->len); - /* Proto object and ProtoFields table will be pop'ed by lua_pop(L, 2) in for statement */ + lua_pop(L,1); /* pop the table of ProtoExperts */ + + /* Proto object will be pop'ed by lua_pop(L, 1) in for statement */ } lua_pop(L,1); /* pop the protocols_table_ref */ @@ -819,7 +928,7 @@ int Proto_commit(lua_State* L) { return 0; } -static guint +static unsigned wslua_dissect_tcp_get_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset, void *data) { @@ -843,7 +952,7 @@ wslua_dissect_tcp_get_pdu_len(packet_info *pinfo, tvbuff_t *tvb, /* if the Lua dissector reported the consumed bytes, pass it to our caller */ if (lua_isnumber(L, -1)) { /* we got the pdu_len */ - pdu_len = wslua_togint(L, -1); + pdu_len = wslua_toint(L, -1); lua_pop(L, 1); } else { THROW_LUA_ERROR("Lua Error dissect_tcp_pdus: get_len_func did not return a Lua number of the PDU length"); @@ -882,7 +991,7 @@ wslua_dissect_tcp_dissector(tvbuff_t *tvb, packet_info *pinfo, /* if the Lua dissector reported the consumed bytes, pass it to our caller */ if (lua_isnumber(L, -1)) { /* we got the consumed bytes or the missing bytes as a negative number */ - consumed_bytes = wslua_togint(L, -1); + consumed_bytes = wslua_toint(L, -1); lua_pop(L, 1); } } @@ -908,8 +1017,6 @@ WSLUA_FUNCTION wslua_dissect_tcp_pdus(lua_State* L) { their protocol's messages (i.e., their protocol data unit (PDU)). This function shouild not be used for protocols whose PDU length cannot be determined from a fixed minimum portion, such as HTTP or Telnet. - - @since 1.99.2 */ #define WSLUA_ARG_dissect_tcp_pdus_TVB 1 /* The Tvb buffer to dissect PDUs from. */ #define WSLUA_ARG_dissect_tcp_pdus_TREE 2 /* The Tvb buffer to dissect PDUs from. */ @@ -933,8 +1040,8 @@ WSLUA_FUNCTION wslua_dissect_tcp_pdus(lua_State* L) { crossing TCP segment boundaries or not. (default=true) */ Tvb tvb = checkTvb(L,WSLUA_ARG_dissect_tcp_pdus_TVB); TreeItem ti = checkTreeItem(L,WSLUA_ARG_dissect_tcp_pdus_TREE); - guint fixed_len = (guint)luaL_checkinteger(L,WSLUA_ARG_dissect_tcp_pdus_MIN_HEADER_SIZE); - gboolean proto_desegment = wslua_optbool(L, WSLUA_OPTARG_dissect_tcp_pdus_DESEGMENT, TRUE); + unsigned fixed_len = (unsigned)luaL_checkinteger(L,WSLUA_ARG_dissect_tcp_pdus_MIN_HEADER_SIZE); + bool proto_desegment = wslua_optbool(L, WSLUA_OPTARG_dissect_tcp_pdus_DESEGMENT, true); if (!lua_pinfo) { luaL_error(L,"dissect_tcp_pdus can only be invoked while in a dissect function"); |