commit 6b80e51: [Minor] Add function to get a lua_reference from a string returning a function

Vsevolod Stakhov vsevolod at highsecure.ru
Wed Sep 1 13:28:04 UTC 2021


Author: Vsevolod Stakhov
Date: 2021-09-01 13:35:13 +0100
URL: https://github.com/rspamd/rspamd/commit/6b80e5120a9edeebee4e266fc17c81e2a5ddaf40

[Minor] Add function to get a lua_reference from a string returning a function

---
 src/libserver/cfg_rcl.c    | 53 ++++++++--------------------------------------
 src/libstat/stat_process.c |  6 +++---
 src/lua/lua_common.c       | 50 +++++++++++++++++++++++++++++++++++++++++++
 src/lua/lua_common.h       |  9 ++++++++
 4 files changed, 71 insertions(+), 47 deletions(-)

diff --git a/src/libserver/cfg_rcl.c b/src/libserver/cfg_rcl.c
index d91ebf3ae..717b16bea 100644
--- a/src/libserver/cfg_rcl.c
+++ b/src/libserver/cfg_rcl.c
@@ -1220,7 +1220,7 @@ rspamd_rcl_classifier_handler (rspamd_mempool_t *pool,
 	gboolean res = TRUE;
 	struct rspamd_rcl_section *stat_section;
 	struct rspamd_tokenizer_config *tkcf = NULL;
-	lua_State *L;
+	lua_State *L = cfg->lua_state;
 
 	g_assert (key != NULL);
 	ccf = rspamd_config_new_classifier (cfg, NULL);
@@ -1303,59 +1303,24 @@ rspamd_rcl_classifier_handler (rspamd_mempool_t *pool,
 
 	if (val) {
 		LL_FOREACH (val, cur) {
-			if (ucl_object_type (cur) == UCL_STRING) {
+			if (ucl_object_type(cur) == UCL_STRING) {
 				const gchar *lua_script;
 				gsize slen;
-				gint err_idx, ref_idx;
-
-				lua_script = ucl_object_tolstring (cur, &slen);
-				L = cfg->lua_state;
-				lua_pushcfunction (L, &rspamd_lua_traceback);
-				err_idx = lua_gettop (L);
-
+				gint ref_idx;
 
-				/* Load file */
-				if (luaL_loadbuffer (L, lua_script, slen, "learn_condition") != 0) {
-					g_set_error (err,
-							CFG_RCL_ERROR,
-							EINVAL,
-							"cannot load lua condition script: %s",
-							lua_tostring (L, -1));
-					lua_settop (L, 0); /* Error function */
+				lua_script = ucl_object_tolstring(cur, &slen);
+				ref_idx = rspamd_lua_function_ref_from_str(L,
+						lua_script, slen, err);
 
+				if (ref_idx == LUA_NOREF) {
 					return FALSE;
 				}
 
-				/* Now do it */
-				if (lua_pcall (L, 0, 1, err_idx) != 0) {
-					g_set_error (err,
-							CFG_RCL_ERROR,
-							EINVAL,
-							"cannot init lua condition script: %s",
-							lua_tostring (L, -1));
-					lua_settop (L, 0);
-
-					return FALSE;
-				}
-
-				if (!lua_isfunction (L, -1)) {
-					g_set_error (err,
-							CFG_RCL_ERROR,
-							EINVAL,
-							"cannot init lua condition script: "
-							"must return function");
-					lua_settop (L, 0);
-
-					return FALSE;
-				}
-
-				ref_idx = luaL_ref (L, LUA_REGISTRYINDEX);
-				rspamd_lua_add_ref_dtor (L, cfg->cfg_pool, ref_idx);
-				ccf->learn_conditions = rspamd_mempool_glist_append (
+				rspamd_lua_add_ref_dtor(L, cfg->cfg_pool, ref_idx);
+				ccf->learn_conditions = rspamd_mempool_glist_append(
 						cfg->cfg_pool,
 						ccf->learn_conditions,
 						GINT_TO_POINTER (ref_idx));
-				lua_settop (L, 0);
 			}
 		}
 	}
diff --git a/src/libstat/stat_process.c b/src/libstat/stat_process.c
index d8b0a3349..8ac4e499e 100644
--- a/src/libstat/stat_process.c
+++ b/src/libstat/stat_process.c
@@ -551,7 +551,7 @@ rspamd_stat_classifiers_learn (struct rspamd_stat_ctx *st_ctx,
 		while (cur) {
 			cb_ref = GPOINTER_TO_INT (cur->data);
 
-			lua_settop (L, 0);
+			gint old_top = lua_gettop (L);
 			lua_rawgeti (L, LUA_REGISTRYINDEX, cb_ref);
 			/* Push task and two booleans: is_spam and is_unlearn */
 			ptask = lua_newuserdata (L, sizeof (*ptask));
@@ -576,13 +576,13 @@ rspamd_stat_classifiers_learn (struct rspamd_stat_ctx *st_ctx,
 									lua_tostring (L, 2));
 						}
 
-						lua_settop (L, 0);
+						lua_settop (L, old_top);
 						break;
 					}
 				}
 			}
 
-			lua_settop (L, 0);
+			lua_settop (L, old_top);
 			cur = g_list_next (cur);
 		}
 
diff --git a/src/lua/lua_common.c b/src/lua/lua_common.c
index 06720c9f2..5d874d507 100644
--- a/src/lua/lua_common.c
+++ b/src/lua/lua_common.c
@@ -2292,6 +2292,56 @@ rspamd_lua_require_function (lua_State *L, const gchar *modname,
 	return FALSE;
 }
 
+gint
+rspamd_lua_function_ref_from_str (lua_State *L, const gchar *str, gsize slen,
+								  GError **err)
+{
+	gint err_idx, ref_idx;
+
+	lua_pushcfunction (L, &rspamd_lua_traceback);
+	err_idx = lua_gettop (L);
+
+	/* Load file */
+	if (luaL_loadbuffer (L, str, slen, "lua_embedded_str") != 0) {
+		g_set_error (err,
+				lua_error_quark(),
+				EINVAL,
+				"cannot load lua script: %s",
+				lua_tostring (L, -1));
+		lua_settop (L, err_idx - 1); /* Error function */
+
+		return LUA_NOREF;
+	}
+
+	/* Now call it */
+	if (lua_pcall (L, 0, 1, err_idx) != 0) {
+		g_set_error (err,
+				lua_error_quark(),
+				EINVAL,
+				"cannot init lua script: %s",
+				lua_tostring (L, -1));
+		lua_settop (L, err_idx - 1);
+
+		return LUA_NOREF;
+	}
+
+	if (!lua_isfunction (L, -1)) {
+		g_set_error (err,
+				lua_error_quark(),
+				EINVAL,
+				"cannot init lua script: "
+				"must return function");
+		lua_settop (L, err_idx - 1);
+
+		return LUA_NOREF;
+	}
+
+	ref_idx = luaL_ref (L, LUA_REGISTRYINDEX);
+	lua_settop (L, err_idx - 1);
+
+	return ref_idx;
+}
+
 
 gboolean
 rspamd_lua_try_load_redis (lua_State *L, const ucl_object_t *obj,
diff --git a/src/lua/lua_common.h b/src/lua/lua_common.h
index d9e4fcaec..b929ab864 100644
--- a/src/lua/lua_common.h
+++ b/src/lua/lua_common.h
@@ -565,6 +565,15 @@ void rspamd_lua_run_config_unload (lua_State *L, struct rspamd_config *cfg);
 void rspamd_lua_add_ref_dtor (lua_State *L, rspamd_mempool_t *pool,
 							  gint ref);
 
+/**
+ * Returns a lua reference from a function like string, e.g. `return function(...) end`
+ * @param L
+ * @param str
+ * @return
+ */
+gint rspamd_lua_function_ref_from_str (lua_State *L, const gchar *str, gsize slen,
+									   GError **err);
+
 /**
 * Tries to load some module using `require` and get some method from it
 * @param L


More information about the Commits mailing list