From: Vsevolod Stakhov Date: Wed, 19 Sep 2018 10:45:53 +0000 (+0100) Subject: [Feature] Add some recursion protection to lua logger X-Git-Tag: 1.8.0~69 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a133eafedf5d2f117431896b98880a4850a6aced;p=thirdparty%2Frspamd.git [Feature] Add some recursion protection to lua logger --- diff --git a/src/lua/lua_common.h b/src/lua/lua_common.h index 8ccb8bef04..af0b5f8247 100644 --- a/src/lua/lua_common.h +++ b/src/lua/lua_common.h @@ -352,6 +352,14 @@ guint rspamd_lua_table_size (lua_State *L, gint tbl_pos); void lua_push_emails_address_list (lua_State *L, GPtrArray *addrs); + +#define TRACE_POINTS 6 + +struct lua_logger_trace { + gint cur_level; + gconstpointer traces[TRACE_POINTS]; +}; + /** * Log lua object to string * @param L @@ -361,7 +369,7 @@ void lua_push_emails_address_list (lua_State *L, GPtrArray *addrs); * @return */ gsize lua_logger_out_type (lua_State *L, gint pos, gchar *outbuf, - gsize len); + gsize len, struct lua_logger_trace *trace); /** * Safely checks userdata to match specified class diff --git a/src/lua/lua_logger.c b/src/lua/lua_logger.c index 69fa8e420e..abfc3e1fa8 100644 --- a/src/lua/lua_logger.c +++ b/src/lua/lua_logger.c @@ -270,7 +270,8 @@ lua_logger_debug (lua_State *L) } static gsize -lua_logger_out_str (lua_State *L, gint pos, gchar *outbuf, gsize len) +lua_logger_out_str (lua_State *L, gint pos, gchar *outbuf, gsize len, + struct lua_logger_trace *trace) { gsize slen; const gchar *str = lua_tolstring (L, pos, &slen); @@ -284,7 +285,8 @@ lua_logger_out_str (lua_State *L, gint pos, gchar *outbuf, gsize len) } static gsize -lua_logger_out_num (lua_State *L, gint pos, gchar *outbuf, gsize len) +lua_logger_out_num (lua_State *L, gint pos, gchar *outbuf, gsize len, + struct lua_logger_trace *trace) { gdouble num = lua_tonumber (L, pos); glong inum; @@ -302,7 +304,8 @@ lua_logger_out_num (lua_State *L, gint pos, gchar *outbuf, gsize len) } static gsize -lua_logger_out_boolean (lua_State *L, gint pos, gchar *outbuf, gsize len) +lua_logger_out_boolean (lua_State *L, gint pos, gchar *outbuf, gsize len, + struct lua_logger_trace *trace) { gboolean val = lua_toboolean (L, pos); gsize r = 0; @@ -313,7 +316,8 @@ lua_logger_out_boolean (lua_State *L, gint pos, gchar *outbuf, gsize len) } static gsize -lua_logger_out_userdata (lua_State *L, gint pos, gchar *outbuf, gsize len) +lua_logger_out_userdata (lua_State *L, gint pos, gchar *outbuf, gsize len, + struct lua_logger_trace *trace) { gint r, top; const gchar *str = NULL; @@ -383,17 +387,34 @@ lua_logger_out_userdata (lua_State *L, gint pos, gchar *outbuf, gsize len) if ((remain) == 0) { lua_pop (L, 1); break; } static gsize -lua_logger_out_table (lua_State *L, gint pos, gchar *outbuf, gsize len) +lua_logger_out_table (lua_State *L, gint pos, gchar *outbuf, gsize len, + struct lua_logger_trace *trace) { gchar *d = outbuf; gsize remain = len, r; gboolean first = TRUE; - gint i; + gconstpointer self = NULL; + gint i, tpos; if (!lua_istable (L, pos) || remain == 0) { return 0; } + self = lua_topointer (L, pos); + + /* Check if we have seen this pointer */ + for (i = 0; i < TRACE_POINTS; i ++) { + if (trace->traces[i] == self) { + r = rspamd_snprintf (d, remain + 1, "ref(%p)", self); + + d += r; + + return (d - outbuf); + } + } + + trace->traces[trace->cur_level % TRACE_POINTS] = self; + lua_pushvalue (L, pos); r = rspamd_snprintf (d, remain + 1, "{"); remain -= r; @@ -415,7 +436,14 @@ lua_logger_out_table (lua_State *L, gint pos, gchar *outbuf, gsize len) r = rspamd_snprintf (d, remain + 1, "[%d] = ", i); MOVE_BUF(d, remain, r); - r = lua_logger_out_type (L, lua_gettop (L), d, remain); + tpos = lua_gettop (L); + + if (lua_topointer (L, tpos) == self) { + r = rspamd_snprintf (d, remain + 1, "__self"); + } + else { + r = lua_logger_out_type (L, tpos, d, remain, trace); + } MOVE_BUF(d, remain, r); first = FALSE; @@ -438,7 +466,14 @@ lua_logger_out_table (lua_State *L, gint pos, gchar *outbuf, gsize len) r = rspamd_snprintf (d, remain + 1, "[%s] = ", lua_tostring (L, -2)); MOVE_BUF(d, remain, r); - r = lua_logger_out_type (L, lua_gettop (L), d, remain); + tpos = lua_gettop (L); + + if (lua_topointer (L, tpos) == self) { + r = rspamd_snprintf (d, remain + 1, "__self"); + } + else { + r = lua_logger_out_type (L, tpos, d, remain, trace); + } MOVE_BUF(d, remain, r); first = FALSE; @@ -455,7 +490,8 @@ lua_logger_out_table (lua_State *L, gint pos, gchar *outbuf, gsize len) #undef MOVE_BUF gsize -lua_logger_out_type (lua_State *L, gint pos, gchar *outbuf, gsize len) +lua_logger_out_type (lua_State *L, gint pos, gchar *outbuf, gsize len, + struct lua_logger_trace *trace) { gint type; gsize r = 0; @@ -465,19 +501,20 @@ lua_logger_out_type (lua_State *L, gint pos, gchar *outbuf, gsize len) } type = lua_type (L, pos); + trace->cur_level ++; switch (type) { case LUA_TNUMBER: - r = lua_logger_out_num (L, pos, outbuf, len); + r = lua_logger_out_num (L, pos, outbuf, len, trace); break; case LUA_TBOOLEAN: - r = lua_logger_out_boolean (L, pos, outbuf, len); + r = lua_logger_out_boolean (L, pos, outbuf, len, trace); break; case LUA_TTABLE: - r = lua_logger_out_table (L, pos, outbuf, len); + r = lua_logger_out_table (L, pos, outbuf, len, trace); break; case LUA_TUSERDATA: - r = lua_logger_out_userdata (L, pos, outbuf, len); + r = lua_logger_out_userdata (L, pos, outbuf, len, trace); break; case LUA_TFUNCTION: r = rspamd_snprintf (outbuf, len + 1, "function"); @@ -490,10 +527,12 @@ lua_logger_out_type (lua_State *L, gint pos, gchar *outbuf, gsize len) break; default: /* Try to push everything as string using tostring magic */ - r = lua_logger_out_str (L, pos, outbuf, len); + r = lua_logger_out_str (L, pos, outbuf, len, trace); break; } + trace->cur_level --; + return r; } @@ -595,6 +634,7 @@ lua_logger_log_format (lua_State *L, gint fmt_pos, gboolean is_string, gsize r, cpylen = 0; guint arg_num = 0, cur_arg; bool num_arg = false; + struct lua_logger_trace tr; enum { copy_char = 0, got_percent, @@ -663,7 +703,8 @@ lua_logger_log_format (lua_State *L, gint fmt_pos, gboolean is_string, return FALSE; } - r = lua_logger_out_type (L, arg_num + 1, d, remain); + memset (&tr, 0, sizeof (tr)); + r = lua_logger_out_type (L, arg_num + 1, d, remain, &tr); g_assert (r <= remain); remain -= r; d += r; @@ -690,7 +731,8 @@ lua_logger_log_format (lua_State *L, gint fmt_pos, gboolean is_string, return FALSE; } - r = lua_logger_out_type (L, arg_num + 1, d, remain); + memset (&tr, 0, sizeof (tr)); + r = lua_logger_out_type (L, arg_num + 1, d, remain, &tr); g_assert (r <= remain); remain -= r; d += r; diff --git a/src/rspamadm/lua_repl.c b/src/rspamadm/lua_repl.c index c6c5fd0bf1..81dba946ab 100644 --- a/src/rspamadm/lua_repl.c +++ b/src/rspamadm/lua_repl.c @@ -240,6 +240,7 @@ rspamadm_exec_input (lua_State *L, const gchar *input) gint i, cbref; int top = 0; gchar outbuf[8192]; + struct lua_logger_trace tr; struct thread_entry *thread = lua_thread_pool_get_for_config (rspamd_main->cfg); L = thread->lua_state; @@ -279,7 +280,8 @@ rspamadm_exec_input (lua_State *L, const gchar *input) rspamd_printf ("local function: %d\n", cbref); } else { - lua_logger_out_type (L, i, outbuf, sizeof (outbuf)); + memset (&tr, 0, sizeof (tr)); + lua_logger_out_type (L, i, outbuf, sizeof (outbuf), &tr); rspamd_printf ("%s\n", outbuf); } } @@ -396,6 +398,7 @@ rspamadm_lua_message_handler (lua_State *L, gint argc, gchar **argv) gpointer map; gsize len; gchar outbuf[8192]; + struct lua_logger_trace tr; if (argv[1] == NULL) { rspamd_printf ("no callback is specified\n"); @@ -457,7 +460,8 @@ rspamadm_lua_message_handler (lua_State *L, gint argc, gchar **argv) rspamd_printf ("lua callback for %s returned:\n", argv[i]); for (j = old_top + 1; j <= lua_gettop (L); j ++) { - lua_logger_out_type (L, j, outbuf, sizeof (outbuf)); + memset (&tr, 0, sizeof (tr)); + lua_logger_out_type (L, j, outbuf, sizeof (outbuf), &tr); rspamd_printf ("%s\n", outbuf); } }