commit 87da610: [Feature] Lua_text: Implement flattening of the input tables

Vsevolod Stakhov vsevolod at highsecure.ru
Mon Jan 6 14:56:09 UTC 2020


Author: Vsevolod Stakhov
Date: 2020-01-06 14:42:05 +0000
URL: https://github.com/rspamd/rspamd/commit/87da61048e060581e5753440911c3cd2191eef88

[Feature] Lua_text: Implement flattening of the input tables

---
 src/lua/lua_text.c | 132 +++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 92 insertions(+), 40 deletions(-)

diff --git a/src/lua/lua_text.c b/src/lua/lua_text.c
index 3f024d236..f24416d29 100644
--- a/src/lua/lua_text.c
+++ b/src/lua/lua_text.c
@@ -196,31 +196,24 @@ lua_text_fromstring (lua_State *L)
 	return 1;
 }
 
-static gint
-lua_text_fromtable (lua_State *L)
+#define MAX_REC 10
+
+static void
+lua_text_tbl_length (lua_State *L, gsize dlen, gsize *dest, guint rec)
 {
-	LUA_TRACE_POINT;
-	const gchar *delim = "", *st;
-	struct rspamd_lua_text *t, *elt;
-	gsize textlen = 0, dlen, stlen, tblen;
-	gchar *dest;
+	gsize tblen, stlen;
+	struct rspamd_lua_text *elt;
 
-	if (!lua_istable (L, 1)) {
-		return luaL_error (L, "invalid arguments");
-	}
+	if (rec > MAX_REC) {
+		luaL_error (L, "lua_text_tbl_length: recursion limit exceeded");
 
-	if (lua_type (L, 2) == LUA_TSTRING) {
-		delim = lua_tolstring (L, 2, &dlen);
-	}
-	else {
-		dlen = 0;
+		return;
 	}
 
-	/* Calculate length needed */
-	tblen = rspamd_lua_table_size (L, 1);
+	tblen = rspamd_lua_table_size (L, -1);
 
-	for (guint i = 0; i < tblen; i ++) {
-		lua_rawgeti (L, 1, i + 1);
+	for (gsize i = 0; i < tblen; i ++) {
+		lua_rawgeti (L, -1, i + 1);
 
 		if (lua_type (L, -1) == LUA_TSTRING) {
 #if LUA_VERSION_NUM >= 502
@@ -228,55 +221,114 @@ lua_text_fromtable (lua_State *L)
 #else
 			stlen = lua_objlen (L, -1);
 #endif
-			textlen += stlen;
+			(*dest) += stlen;
 		}
-		else {
-			elt = lua_check_text (L, -1);
+		else if (lua_type (L, -1) == LUA_TUSERDATA){
+			elt = (struct rspamd_lua_text *)lua_touserdata (L, -1);
 
 			if (elt) {
-				textlen += elt->len;
+				(*dest) += elt->len;
 			}
 		}
+		else if (lua_type (L, -1) == LUA_TTABLE) {
+			lua_text_tbl_length (L, dlen, dest, rec + 1);
+		}
 
 		if (i != tblen - 1) {
-			textlen += dlen;
+			(*dest) += dlen;
 		}
 
 		lua_pop (L, 1);
 	}
+}
 
-	/* Allocate new text */
-	t = lua_newuserdata (L, sizeof (*t));
-	dest = g_malloc (textlen);
-	t->start = dest;
-	t->len = textlen;
-	t->flags = RSPAMD_TEXT_FLAG_OWN;
-	rspamd_lua_setclass (L, "rspamd{text}", -1);
+static void
+lua_text_tbl_append (lua_State *L,
+					 const gchar *delim,
+					 gsize dlen,
+					 gchar **dest,
+					 guint rec)
+{
+	const gchar *st;
+	gsize tblen, stlen;
+	struct rspamd_lua_text *elt;
+
+	if (rec > MAX_REC) {
+		luaL_error (L, "lua_text_tbl_length: recursion limit exceeded");
+
+		return;
+	}
+
+	tblen = rspamd_lua_table_size (L, -1);
 
 	for (guint i = 0; i < tblen; i ++) {
-		lua_rawgeti (L, 1, i + 1);
+		lua_rawgeti (L, -1, i + 1);
 
 		if (lua_type (L, -1) == LUA_TSTRING) {
 			st = lua_tolstring (L, -1, &stlen);
-			memcpy (dest, st, stlen);
-			dest += stlen;
+			memcpy ((*dest), st, stlen);
+			(*dest) += stlen;
 		}
-		else {
-			elt = lua_check_text (L, -1);
+		else if (lua_type (L, -1) == LUA_TUSERDATA){
+			elt = (struct rspamd_lua_text *)lua_touserdata (L, -1);
 
 			if (elt) {
-				memcpy (dest, elt->start, elt->len);
-				dest += elt->len;
+				memcpy ((*dest), elt->start, elt->len);
+				(*dest) += elt->len;
 			}
 		}
+		else if (lua_type (L, -1) == LUA_TTABLE) {
+			lua_text_tbl_append (L, delim, dlen, dest, rec + 1);
+		}
 
 		if (dlen && i != tblen - 1) {
-			memcpy (dest, delim, dlen);
-			dest += dlen;
+			memcpy ((*dest), delim, dlen);
+			(*dest) += dlen;
 		}
 
 		lua_pop (L, 1);
 	}
+}
+
+static gint
+lua_text_fromtable (lua_State *L)
+{
+	LUA_TRACE_POINT;
+	const gchar *delim = "";
+	struct rspamd_lua_text *t;
+	gsize textlen = 0, dlen, oldtop = lua_gettop (L);
+	gchar *dest;
+
+	if (!lua_istable (L, 1)) {
+		return luaL_error (L, "invalid arguments");
+	}
+
+	if (lua_type (L, 2) == LUA_TSTRING) {
+		delim = lua_tolstring (L, 2, &dlen);
+	}
+	else {
+		dlen = 0;
+	}
+
+	/* Calculate length needed */
+	lua_pushvalue (L, 1);
+	lua_text_tbl_length (L, dlen, &textlen, 0);
+	lua_pop (L, 1);
+
+	/* Allocate new text */
+	t = lua_newuserdata (L, sizeof (*t));
+	dest = g_malloc (textlen);
+	t->start = dest;
+	t->len = textlen;
+	t->flags = RSPAMD_TEXT_FLAG_OWN;
+	rspamd_lua_setclass (L, "rspamd{text}", -1);
+
+	lua_pushvalue (L, 1);
+	lua_text_tbl_append (L, delim, dlen, &dest, 0);
+	lua_pop (L, 1); /* Table arg */
+
+	gint newtop = lua_gettop (L);
+	g_assert ( newtop== oldtop + 1);
 
 	return 1;
 }


More information about the Commits mailing list