wslua: fix crash when a LUA error is raised in TRY block
The dissect_tcp_pdus function in LUA is passed two LUA functions that get the PDU length and the dissect a PDU. When one of these functions fail, a longjmp is made to the the caller of lua_pcall. This is no problem for the PDU length function, but the PDU dissect function is wrapped in a TRY/CATCH/ENDTRY block which also uses longjmp and need to be fully executed. Without doing so, LUA exceptions will crash on a weird location (except_pop). Fix the crash by not using luaL_error, but throw dissector errors which properly breaks out of the tcp_dissect_pdus C function and then convert it to a LUA error such that the dissector can handle it. Test with `tshark -X lua_script:crash.lua -r ssl.pcap`: trivial_proto = Proto("trivial", "Trivial Protocol") function dissect_foo(tvb, pinfo, tree) error("triggering a LUA error"); end function get_pdu_len(tvb, pinfo, tree) return 5; end function trivial_proto.dissector(tvb, pinfo, tree) dissect_tcp_pdus(tvb, tree, 5, get_pdu_len, dissect_foo) end tcp_table = DissectorTable.get("tcp.port") tcp_table:add(443, trivial_proto) It should not crash and will print this: Lua Error: dissect_tcp_pdus dissect_func: [string "crash.lua"]:3: triggering a LUA error Change-Id: Ibd079cc5eb3a2e4d2e62ea49a512fa2cc8e561ea Reviewed-on: https://code.wireshark.org/review/10685 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Peter Wu <peter@lekensteyn.nl> Reviewed-by: Evan Huus <eapache@gmail.com>
This commit is contained in:
parent
3182fbae51
commit
82b225898b
|
@ -372,6 +372,10 @@
|
||||||
except_throw(XCEPT_GROUP_WIRESHARK, (x), (y)); \
|
except_throw(XCEPT_GROUP_WIRESHARK, (x), (y)); \
|
||||||
} G_STMT_END
|
} G_STMT_END
|
||||||
|
|
||||||
|
/* Throws a formatted message, its memory is cleared after catching it. */
|
||||||
|
#define THROW_FORMATTED(x, ...) \
|
||||||
|
except_throwf(XCEPT_GROUP_WIRESHARK, (x), __VA_ARGS__)
|
||||||
|
|
||||||
#define GET_MESSAGE except_message(exc)
|
#define GET_MESSAGE except_message(exc)
|
||||||
|
|
||||||
#define RETHROW \
|
#define RETHROW \
|
||||||
|
|
|
@ -654,6 +654,26 @@ extern int C##_register(lua_State* L); \
|
||||||
extern gboolean is##C(lua_State* L,int i); \
|
extern gboolean is##C(lua_State* L,int i); \
|
||||||
extern C shift##C(lua_State* L,int i)
|
extern C shift##C(lua_State* L,int i)
|
||||||
|
|
||||||
|
|
||||||
|
/* Throws a Wireshark exception, catchable via normal exceptions.h routines. */
|
||||||
|
#define THROW_LUA_ERROR(...) \
|
||||||
|
THROW_FORMATTED(DissectorError, __VA_ARGS__)
|
||||||
|
|
||||||
|
/* Catches any Wireshark exceptions in code and convert it into a LUA error.
|
||||||
|
* Normal restrictions for TRY/CATCH apply, in particular, do not return! */
|
||||||
|
#define WRAP_NON_LUA_EXCEPTIONS(code) \
|
||||||
|
{ \
|
||||||
|
volatile gboolean has_error = FALSE; \
|
||||||
|
TRY { \
|
||||||
|
code \
|
||||||
|
} CATCH_ALL { \
|
||||||
|
lua_pushstring(L, GET_MESSAGE); \
|
||||||
|
has_error = TRUE; \
|
||||||
|
} ENDTRY; \
|
||||||
|
if (has_error) { lua_error(L); } \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
extern packet_info* lua_pinfo;
|
extern packet_info* lua_pinfo;
|
||||||
extern TreeItem lua_tree;
|
extern TreeItem lua_tree;
|
||||||
extern tvbuff_t* lua_tvb;
|
extern tvbuff_t* lua_tvb;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "wslua.h"
|
#include "wslua.h"
|
||||||
#include <epan/dissectors/packet-tcp.h>
|
#include <epan/dissectors/packet-tcp.h>
|
||||||
|
#include <epan/exceptions.h>
|
||||||
|
|
||||||
/* WSLUA_MODULE Proto Functions for new protocols and dissectors
|
/* WSLUA_MODULE Proto Functions for new protocols and dissectors
|
||||||
|
|
||||||
|
@ -761,6 +762,7 @@ static int
|
||||||
wslua_dissect_tcp_dissector(tvbuff_t *tvb, packet_info *pinfo,
|
wslua_dissect_tcp_dissector(tvbuff_t *tvb, packet_info *pinfo,
|
||||||
proto_tree *tree, void *data)
|
proto_tree *tree, void *data)
|
||||||
{
|
{
|
||||||
|
/* WARNING: called from a TRY block, do not call luaL_error! */
|
||||||
func_saver_t* fs = (func_saver_t*)data;
|
func_saver_t* fs = (func_saver_t*)data;
|
||||||
lua_State* L = fs->state;
|
lua_State* L = fs->state;
|
||||||
int consumed_bytes = 0;
|
int consumed_bytes = 0;
|
||||||
|
@ -776,7 +778,7 @@ wslua_dissect_tcp_dissector(tvbuff_t *tvb, packet_info *pinfo,
|
||||||
push_TreeItem(L, tree, (proto_item*)tree);
|
push_TreeItem(L, tree, (proto_item*)tree);
|
||||||
|
|
||||||
if ( lua_pcall(L,3,1,0) ) {
|
if ( lua_pcall(L,3,1,0) ) {
|
||||||
luaL_error(L, "Lua Error dissect_tcp_pdus dissect_func: %s", lua_tostring(L,-1));
|
THROW_LUA_ERROR("dissect_tcp_pdus dissect_func: %s", lua_tostring(L, -1));
|
||||||
} else {
|
} else {
|
||||||
/* if the Lua dissector reported the consumed bytes, pass it to our caller */
|
/* if the Lua dissector reported the consumed bytes, pass it to our caller */
|
||||||
if (lua_isnumber(L, -1)) {
|
if (lua_isnumber(L, -1)) {
|
||||||
|
@ -787,7 +789,7 @@ wslua_dissect_tcp_dissector(tvbuff_t *tvb, packet_info *pinfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
luaL_error(L,"Lua Error dissect_tcp_pdus: did not find the dissect_func dissector");
|
REPORT_DISSECTOR_BUG("dissect_tcp_pdus: did not find the dissect_func dissector");
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed_bytes;
|
return consumed_bytes;
|
||||||
|
@ -857,9 +859,11 @@ WSLUA_FUNCTION wslua_dissect_tcp_pdus(lua_State* L) {
|
||||||
destroy them before they get invoked */
|
destroy them before they get invoked */
|
||||||
g_ptr_array_add(outstanding_FuncSavers, fs);
|
g_ptr_array_add(outstanding_FuncSavers, fs);
|
||||||
|
|
||||||
tcp_dissect_pdus(tvb->ws_tvb, lua_pinfo, ti->tree, proto_desegment,
|
WRAP_NON_LUA_EXCEPTIONS(
|
||||||
fixed_len, wslua_dissect_tcp_get_pdu_len,
|
tcp_dissect_pdus(tvb->ws_tvb, lua_pinfo, ti->tree, proto_desegment,
|
||||||
wslua_dissect_tcp_dissector, (void*)fs);
|
fixed_len, wslua_dissect_tcp_get_pdu_len,
|
||||||
|
wslua_dissect_tcp_dissector, (void*)fs);
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
luaL_error(L,"The third and fourth arguments need to be Lua functions");
|
luaL_error(L,"The third and fourth arguments need to be Lua functions");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue