aboutsummaryrefslogtreecommitdiffstats
path: root/src/lua
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2018-09-19 11:45:53 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2018-09-19 14:33:53 +0100
commita133eafedf5d2f117431896b98880a4850a6aced (patch)
treef126919bf2749962867e54d8c024357eab770760 /src/lua
parent95df15919326182a588ed339733d71d74fc7a591 (diff)
downloadrspamd-a133eafedf5d2f117431896b98880a4850a6aced.tar.gz
rspamd-a133eafedf5d2f117431896b98880a4850a6aced.zip
[Feature] Add some recursion protection to lua logger
Diffstat (limited to 'src/lua')
-rw-r--r--src/lua/lua_common.h10
-rw-r--r--src/lua/lua_logger.c74
2 files changed, 67 insertions, 17 deletions
diff --git a/src/lua/lua_common.h b/src/lua/lua_common.h
index 8ccb8bef0..af0b5f824 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 69fa8e420..abfc3e1fa 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;