aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2015-09-29 12:20:07 +0200
committerEvan Huus <eapache@gmail.com>2015-10-05 02:30:16 +0000
commit82b225898b677e7a7e0176941ef73c824d761a98 (patch)
treea60b5e682deaf2a6b1075a099c3ed71a08102a8b
parent3182fbae51d51cf4417226d9e16ca82df1bdbc71 (diff)
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>
-rw-r--r--epan/exceptions.h4
-rw-r--r--epan/wslua/wslua.h20
-rw-r--r--epan/wslua/wslua_proto.c14
3 files changed, 33 insertions, 5 deletions
diff --git a/epan/exceptions.h b/epan/exceptions.h
index e6ed6f5a96..5106852bca 100644
--- a/epan/exceptions.h
+++ b/epan/exceptions.h
@@ -372,6 +372,10 @@
except_throw(XCEPT_GROUP_WIRESHARK, (x), (y)); \
} 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 RETHROW \
diff --git a/epan/wslua/wslua.h b/epan/wslua/wslua.h
index 7ad7926db6..4d0ca22b60 100644
--- a/epan/wslua/wslua.h
+++ b/epan/wslua/wslua.h
@@ -654,6 +654,26 @@ extern int C##_register(lua_State* L); \
extern gboolean is##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 TreeItem lua_tree;
extern tvbuff_t* lua_tvb;
diff --git a/epan/wslua/wslua_proto.c b/epan/wslua/wslua_proto.c
index 155d0fe194..4cfe734683 100644
--- a/epan/wslua/wslua_proto.c
+++ b/epan/wslua/wslua_proto.c
@@ -30,6 +30,7 @@
#include "wslua.h"
#include <epan/dissectors/packet-tcp.h>
+#include <epan/exceptions.h>
/* 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,
proto_tree *tree, void *data)
{
+ /* WARNING: called from a TRY block, do not call luaL_error! */
func_saver_t* fs = (func_saver_t*)data;
lua_State* L = fs->state;
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);
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 {
/* if the Lua dissector reported the consumed bytes, pass it to our caller */
if (lua_isnumber(L, -1)) {
@@ -787,7 +789,7 @@ wslua_dissect_tcp_dissector(tvbuff_t *tvb, packet_info *pinfo,
}
} 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;
@@ -857,9 +859,11 @@ WSLUA_FUNCTION wslua_dissect_tcp_pdus(lua_State* L) {
destroy them before they get invoked */
g_ptr_array_add(outstanding_FuncSavers, fs);
- tcp_dissect_pdus(tvb->ws_tvb, lua_pinfo, ti->tree, proto_desegment,
- fixed_len, wslua_dissect_tcp_get_pdu_len,
- wslua_dissect_tcp_dissector, (void*)fs);
+ WRAP_NON_LUA_EXCEPTIONS(
+ tcp_dissect_pdus(tvb->ws_tvb, lua_pinfo, ti->tree, proto_desegment,
+ fixed_len, wslua_dissect_tcp_get_pdu_len,
+ wslua_dissect_tcp_dissector, (void*)fs);
+ )
} else {
luaL_error(L,"The third and fourth arguments need to be Lua functions");
}