]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Add some recursion protection to lua logger
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 19 Sep 2018 10:45:53 +0000 (11:45 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 19 Sep 2018 13:33:53 +0000 (14:33 +0100)
src/lua/lua_common.h
src/lua/lua_logger.c
src/rspamadm/lua_repl.c

index 8ccb8bef047e1c93bcc0b3345f09632b7566136c..af0b5f824704d43ad777f157d822ffebab37e648 100644 (file)
@@ -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
index 69fa8e420e418e986664c5045b57470b694934bc..abfc3e1fa85b08154688296c9a94802b659981c4 100644 (file)
@@ -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;
index c6c5fd0bf16edabce18f4d7de23fbbe85c8ce0fb..81dba946abd4f609e770f146e221270499f7e68d 100644 (file)
@@ -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);
                                }
                        }