commit 422bf8b: [Project] Add routine to call a generic lua function

Vsevolod Stakhov vsevolod at highsecure.ru
Mon Apr 6 17:28:07 UTC 2020


Author: Vsevolod Stakhov
Date: 2020-04-06 14:28:02 +0100
URL: https://github.com/rspamd/rspamd/commit/422bf8b8f4208191ad9818a8b0890721ae4d5cf2

[Project] Add routine to call a generic lua function

---
 src/lua/lua_common.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lua/lua_common.h | 21 +++++++++++++
 2 files changed, 109 insertions(+)

diff --git a/src/lua/lua_common.c b/src/lua/lua_common.c
index ce5fff6c5..8a562f7b3 100644
--- a/src/lua/lua_common.c
+++ b/src/lua/lua_common.c
@@ -2407,4 +2407,92 @@ rspamd_lua_get_module_name (lua_State *L)
 	}
 
 	return NULL;
+}
+
+bool
+rspamd_lua_universal_pcall (lua_State *L, gint cbref, const gchar* strloc,
+								 gint nret, const gchar *args, GError **err, ...)
+{
+	va_list ap;
+	const gchar *argp = args, *classname;
+	gint err_idx, nargs = 0;
+	gpointer *cls_ptr;
+	gsize sz;
+
+	/* Error function */
+	lua_pushcfunction (L, &rspamd_lua_traceback);
+	err_idx = lua_gettop (L);
+
+	va_start (ap, err);
+	/* Called function */
+	lua_rawgeti (L, LUA_REGISTRYINDEX, cbref);
+	/*
+	 * Possible arguments
+	 * - i - lua_integer, argument - gint64
+	 * - n - lua_number, argument - gdouble
+	 * - s - lua_string, argument - const gchar * (zero terminated)
+	 * - l - lua_lstring, argument - (size_t + const gchar *) pair
+	 * - u - lua_userdata, argument - (const char * + void *) - classname + pointer
+	 * - b - lua_boolean, argument - gboolean (not bool due to varargs promotion)
+	 * - f - lua_function, argument - int - position of the function on stack (not lua_registry)
+	 */
+	while (*argp) {
+		switch (*argp) {
+		case 'i':
+			lua_pushinteger (L, va_arg (ap, gint64));
+			nargs ++;
+			break;
+		case 'n':
+			lua_pushnumber (L, va_arg (ap, gdouble));
+			nargs ++;
+			break;
+		case 's':
+			lua_pushstring (L, va_arg (ap, const gchar *));
+			nargs ++;
+			break;
+		case 'l':
+			sz = va_arg (ap, gsize);
+			lua_pushlstring (L, va_arg (ap, const gchar *), sz);
+			nargs ++;
+			break;
+		case 'b':
+			lua_pushboolean (L, va_arg (ap, gboolean));
+			nargs ++;
+			break;
+		case 'u':
+			classname = va_arg (ap, const gchar *);
+			cls_ptr = (gpointer *)lua_newuserdata (L, sizeof (gpointer));
+			*cls_ptr = va_arg (ap, gpointer);
+			rspamd_lua_setclass (L, classname, -1);
+			nargs ++;
+			break;
+		case 'f':
+			lua_pushvalue (L, va_arg (ap, gint));
+			nargs ++;
+			break;
+		default:
+			lua_settop (L, err_idx - 1);
+			g_set_error (err, lua_error_quark (), EINVAL,
+					"invalid argument character: %c at %s",
+					*argp, argp);
+
+			return false;
+		}
+
+		argp ++;
+	}
+
+	if (lua_pcall (L, nargs, nret, err_idx) != 0) {
+		g_set_error (err, lua_error_quark (), EBADF,
+				"error when calling lua function from %s: %s",
+				strloc, lua_tostring (L, -1));
+		lua_settop (L, err_idx - 1);
+
+		return false;
+	}
+
+	lua_remove (L, err_idx);
+	va_end (ap);
+
+	return true;
 }
\ No newline at end of file
diff --git a/src/lua/lua_common.h b/src/lua/lua_common.h
index aea6ebf26..8252da004 100644
--- a/src/lua/lua_common.h
+++ b/src/lua/lua_common.h
@@ -577,6 +577,27 @@ gint rspamd_lua_push_words (lua_State *L, GArray *words,
  */
 gchar *rspamd_lua_get_module_name (lua_State *L);
 
+/**
+ * Call Lua function in a universal way. Arguments string:
+ * - i - lua_integer, argument - gint64
+ * - n - lua_number, argument - gdouble
+ * - s - lua_string, argument - const gchar * (zero terminated)
+ * - l - lua_lstring, argument - (size_t + const gchar *) pair
+ * - u - lua_userdata, argument - (const char * + void *) - classname + pointer
+ * - b - lua_boolean, argument - gboolean (not bool due to varargs promotion)
+ * - f - lua_function, argument - int - position of the function on stack (not lua_registry)
+ * @param L lua state
+ * @param cbref LUA_REGISTRY reference
+ * @param strloc where this function is called from
+ * @param nret number of results (or LUA_MULTRET)
+ * @param args arguments format string
+ * @param err error to promote
+ * @param ... arguments
+ * @return true of pcall returned 0, false + err otherwise
+ */
+bool rspamd_lua_universal_pcall (lua_State *L, gint cbref, const gchar* strloc,
+		gint nret, const gchar *args, GError **err, ...);
+
 /* Paths defs */
 #define RSPAMD_CONFDIR_INDEX "CONFDIR"
 #define RSPAMD_LOCAL_CONFDIR_INDEX "LOCAL_CONFDIR"


More information about the Commits mailing list