From fa7dcbab1fb25fe90048a73c62cd23a918a55805 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 26 Apr 2019 15:24:00 +0100 Subject: [PATCH] [Minor] Move rspamd_text to a sepatate unit --- doc/Makefile | 6 +- src/lua/CMakeLists.txt | 3 +- src/lua/lua_task.c | 319 ------------------------------- src/lua/lua_text.c | 417 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 423 insertions(+), 322 deletions(-) create mode 100644 src/lua/lua_text.c diff --git a/doc/Makefile b/doc/Makefile index e77bca045..1a57f7a3b 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -21,7 +21,7 @@ lua-dirs: lua-doc: lua-dirs rspamd_regexp rspamd_ip rspamd_config rspamd_task ucl rspamd_http rspamd_trie \ rspamd_resolver rspamd_redis rspamd_upstream_list rspamd_expression rspamd_mimepart rspamd_logger rspamd_url \ rspamd_tcp rspamd_mempool rspamd_html rspamd_util rspamd_fann rspamd_sqlite3 rspamd_cryptobox rspamd_map \ - lua_redis lua_util lua_maps lua_clickhouse lua_selectors rspamd_udp + lua_redis lua_util lua_maps lua_clickhouse lua_selectors rspamd_udp rspamd_text lua_redis: $(LLUADOC) < ../lualib/lua_redis.lua > markdown/lua/lua_redis.md @@ -83,4 +83,6 @@ rspamd_cryptobox: ../src/lua/lua_cryptobox.c rspamd_map: ../src/lua/lua_map.c $(LUADOC) < ../src/lua/lua_map.c > markdown/lua/rspamd_map.md rspamd_udp: ../src/lua/lua_udp.c - $(LUADOC) < ../src/lua/lua_udp.c > markdown/lua/rspamd_udp.md \ No newline at end of file + $(LUADOC) < ../src/lua/lua_udp.c > markdown/lua/rspamd_udp.md +rspamd_text: ../src/lua/lua_text.c + $(LUADOC) < ../src/lua/lua_text.c > markdown/lua/rspamd_text.md \ No newline at end of file diff --git a/src/lua/CMakeLists.txt b/src/lua/CMakeLists.txt index 0df179c52..4e20008c6 100644 --- a/src/lua/CMakeLists.txt +++ b/src/lua/CMakeLists.txt @@ -28,6 +28,7 @@ SET(LUASRC ${CMAKE_CURRENT_SOURCE_DIR}/lua_common.c ${CMAKE_CURRENT_SOURCE_DIR}/lua_map.c ${CMAKE_CURRENT_SOURCE_DIR}/lua_thread_pool.c ${CMAKE_CURRENT_SOURCE_DIR}/lua_dns.c - ${CMAKE_CURRENT_SOURCE_DIR}/lua_udp.c) + ${CMAKE_CURRENT_SOURCE_DIR}/lua_udp.c + ${CMAKE_CURRENT_SOURCE_DIR}/lua_text.c) SET(RSPAMD_LUA ${LUASRC} PARENT_SCOPE) \ No newline at end of file diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c index 50e35434c..945e06e08 100644 --- a/src/lua/lua_task.c +++ b/src/lua/lua_task.c @@ -1185,35 +1185,6 @@ static const struct luaL_reg archivelib_m[] = { {NULL, NULL} }; -/* Blob methods */ -LUA_FUNCTION_DEF (text, fromstring); -LUA_FUNCTION_DEF (text, fromtable); -LUA_FUNCTION_DEF (text, len); -LUA_FUNCTION_DEF (text, str); -LUA_FUNCTION_DEF (text, ptr); -LUA_FUNCTION_DEF (text, save_in_file); -LUA_FUNCTION_DEF (text, take_ownership); -LUA_FUNCTION_DEF (text, gc); - -static const struct luaL_reg textlib_f[] = { - LUA_INTERFACE_DEF (text, fromstring), - LUA_INTERFACE_DEF (text, fromtable), - {NULL, NULL} -}; - -static const struct luaL_reg textlib_m[] = { - LUA_INTERFACE_DEF (text, len), - LUA_INTERFACE_DEF (text, str), - LUA_INTERFACE_DEF (text, ptr), - LUA_INTERFACE_DEF (text, take_ownership), - LUA_INTERFACE_DEF (text, save_in_file), - {"write", lua_text_save_in_file}, - {"__len", lua_text_len}, - {"__tostring", lua_text_str}, - {"__gc", lua_text_gc}, - {NULL, NULL} -}; - /* Utility functions */ struct rspamd_task * lua_check_task (lua_State * L, gint pos) @@ -5978,277 +5949,6 @@ lua_archive_get_filename (lua_State *L) return 1; } -/* Text methods */ -static gint -lua_text_fromstring (lua_State *L) -{ - LUA_TRACE_POINT; - const gchar *str; - gsize l = 0; - struct rspamd_lua_text *t; - - str = luaL_checklstring (L, 1, &l); - - if (str) { - t = lua_newuserdata (L, sizeof (*t)); - t->start = g_malloc (l + 1); - rspamd_strlcpy ((char *)t->start, str, l + 1); - t->len = l; - t->flags = RSPAMD_TEXT_FLAG_OWN; - rspamd_lua_setclass (L, "rspamd{text}", -1); - } - else { - return luaL_error (L, "invalid arguments"); - } - - - return 1; -} - -static gint -lua_text_fromtable (lua_State *L) -{ - LUA_TRACE_POINT; - const gchar *delim = "", *st; - struct rspamd_lua_text *t, *elt; - gsize textlen = 0, dlen, stlen, tblen; - 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 = strlen (delim); - } - - /* Calculate length needed */ - tblen = rspamd_lua_table_size (L, 1); - - for (guint i = 0; i < tblen; i ++) { - lua_rawgeti (L, 1, i + 1); - - if (lua_type (L, -1) == LUA_TSTRING) { -#if LUA_VERSION_NUM >= 502 - stlen = lua_rawlen (L, -1); -#else - stlen = lua_objlen (L, -1); -#endif - textlen += stlen; - } - else { - elt = lua_check_text (L, -1); - - if (elt) { - textlen += elt->len; - } - } - - lua_pop (L, 1); - textlen += dlen; - } - - /* 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); - - for (guint i = 0; i < tblen; i ++) { - 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; - } - else { - elt = lua_check_text (L, -1); - - if (elt) { - memcpy (dest, elt->start, elt->len); - } - } - - memcpy (dest, delim, dlen); - lua_pop (L, 1); - } - - return 1; -} - -static gint -lua_text_len (lua_State *L) -{ - LUA_TRACE_POINT; - struct rspamd_lua_text *t = lua_check_text (L, 1); - gsize l = 0; - - if (t != NULL) { - l = t->len; - } - else { - return luaL_error (L, "invalid arguments"); - } - - lua_pushinteger (L, l); - - return 1; -} - -static gint -lua_text_str (lua_State *L) -{ - LUA_TRACE_POINT; - struct rspamd_lua_text *t = lua_check_text (L, 1); - - if (t != NULL) { - lua_pushlstring (L, t->start, t->len); - } - else { - return luaL_error (L, "invalid arguments"); - } - - return 1; -} - -static gint -lua_text_ptr (lua_State *L) -{ - LUA_TRACE_POINT; - struct rspamd_lua_text *t = lua_check_text (L, 1); - - if (t != NULL) { - lua_pushlightuserdata (L, (gpointer)t->start); - } - else { - return luaL_error (L, "invalid arguments"); - } - - return 1; -} - -static gint -lua_text_take_ownership (lua_State *L) -{ - LUA_TRACE_POINT; - struct rspamd_lua_text *t = lua_check_text (L, 1); - gchar *dest; - - if (t != NULL) { - if (t->flags & RSPAMD_TEXT_FLAG_OWN) { - /* We already own it */ - lua_pushboolean (L, true); - } - else { - dest = g_malloc (t->len); - memcpy (dest, t->start, t->len); - t->start = dest; - t->flags |= RSPAMD_TEXT_FLAG_OWN; - lua_pushboolean (L, true); - } - } - else { - return luaL_error (L, "invalid arguments"); - } - - return 1; -} - -static gint -lua_text_save_in_file (lua_State *L) -{ - LUA_TRACE_POINT; - struct rspamd_lua_text *t = lua_check_text (L, 1); - const gchar *fname = NULL; - guint mode = 00644; - gint fd = -1; - gboolean need_close = FALSE; - - if (t != NULL) { - if (lua_type (L, 2) == LUA_TSTRING) { - fname = luaL_checkstring (L, 2); - - if (lua_type (L, 3) == LUA_TNUMBER) { - mode = lua_tonumber (L, 3); - } - } - else if (lua_type (L, 2) == LUA_TNUMBER) { - /* Created fd */ - fd = lua_tonumber (L, 2); - } - - if (fd == -1) { - if (fname) { - fd = rspamd_file_xopen (fname, O_CREAT | O_WRONLY | O_EXCL, mode, 0); - - if (fd == -1) { - lua_pushboolean (L, false); - lua_pushstring (L, strerror (errno)); - - return 2; - } - need_close = TRUE; - } - else { - fd = STDOUT_FILENO; - } - } - - if (write (fd, t->start, t->len) == -1) { - if (fd != STDOUT_FILENO) { - close (fd); - } - - lua_pushboolean (L, false); - lua_pushstring (L, strerror (errno)); - - return 2; - } - - if (need_close) { - close (fd); - } - - lua_pushboolean (L, true); - } - else { - return luaL_error (L, "invalid arguments"); - } - - return 1; -} - -static gint -lua_text_gc (lua_State *L) -{ - LUA_TRACE_POINT; - struct rspamd_lua_text *t = lua_check_text (L, 1); - - if (t != NULL) { - if (t->flags & RSPAMD_TEXT_FLAG_OWN) { - if (t->flags & RSPAMD_TEXT_FLAG_WIPE) { - rspamd_explicit_memzero ((guchar *)t->start, t->len); - } - - if (t->flags & RSPAMD_TEXT_FLAG_MMAPED) { - munmap ((gpointer)t->start, t->len); - } - else { - g_free ((gpointer)t->start); - } - } - - } - - return 0; -} - /* Init part */ static gint @@ -6260,16 +5960,6 @@ lua_load_task (lua_State * L) return 1; } -static gint -lua_load_text (lua_State * L) -{ - lua_newtable (L); - luaL_register (L, NULL, textlib_f); - - return 1; -} - - static void luaopen_archive (lua_State * L) { @@ -6295,15 +5985,6 @@ luaopen_image (lua_State * L) lua_pop (L, 1); } -void -luaopen_text (lua_State *L) -{ - rspamd_lua_new_class (L, "rspamd{text}", textlib_m); - lua_pop (L, 1); - - rspamd_lua_add_preload (L, "rspamd_text", lua_load_text); -} - void rspamd_lua_task_push (lua_State *L, struct rspamd_task *task) { diff --git a/src/lua/lua_text.c b/src/lua/lua_text.c new file mode 100644 index 000000000..e130490ef --- /dev/null +++ b/src/lua/lua_text.c @@ -0,0 +1,417 @@ +/*- + * Copyright 2019 Vsevolod Stakhov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lua_common.h" +#include "libcryptobox/cryptobox.h" +#include "unix-std.h" + +/*** + * @module rspamd_text + * This module provides access to opaque text structures used widely to prevent + * copying between Lua and C for various concerns: performance, security etc... + * + * You can convert rspamd_text into string but it will copy data. + */ + +/** + * @function rspamd_text.fromstring(str) + * Creates rspamd_text from Lua string (copied to the text) + * @param {string} str string to use + * @return {rspamd_text} resulting text + */ +LUA_FUNCTION_DEF (text, fromstring); +/** + * @function rspamd_text.fromtable(tbl[, delim]) + * Same as `table.concat` but generates rspamd_text instead of the Lua string + * @param {table} tbl table to use + * @param {string} delim optional delimiter + * @return {rspamd_text} resulting text + */ +LUA_FUNCTION_DEF (text, fromtable); +/*** + * @method rspamd_text:len() + * Returns length of a string + * @return {number} length of string in **bytes** + */ +LUA_FUNCTION_DEF (text, len); +/*** + * @method rspamd_text:str() + * Converts text to string by copying its content + * @return {string} copy of text as Lua string + */ +LUA_FUNCTION_DEF (text, str); +/*** + * @method rspamd_text:ptr() + * Converts text to lightuserdata + * @return {lightuserdata} pointer value of rspamd_text + */ +LUA_FUNCTION_DEF (text, ptr); +/*** + * @method rspamd_text:save_in_file(fname[, mode]) + * Saves text in file + * @return {boolean} true if save has been completed + */ +LUA_FUNCTION_DEF (text, save_in_file); +LUA_FUNCTION_DEF (text, take_ownership); +LUA_FUNCTION_DEF (text, gc); +LUA_FUNCTION_DEF (text, eq); + +static const struct luaL_reg textlib_f[] = { + LUA_INTERFACE_DEF (text, fromstring), + LUA_INTERFACE_DEF (text, fromtable), + {NULL, NULL} +}; + +static const struct luaL_reg textlib_m[] = { + LUA_INTERFACE_DEF (text, len), + LUA_INTERFACE_DEF (text, str), + LUA_INTERFACE_DEF (text, ptr), + LUA_INTERFACE_DEF (text, take_ownership), + LUA_INTERFACE_DEF (text, save_in_file), + {"write", lua_text_save_in_file}, + {"__len", lua_text_len}, + {"__tostring", lua_text_str}, + {"__gc", lua_text_gc}, + {"__eq", lua_text_eq}, + {NULL, NULL} +}; + +static gint +lua_text_fromstring (lua_State *L) +{ + LUA_TRACE_POINT; + const gchar *str; + gsize l = 0; + struct rspamd_lua_text *t; + + str = luaL_checklstring (L, 1, &l); + + if (str) { + t = lua_newuserdata (L, sizeof (*t)); + t->start = g_malloc (l + 1); + rspamd_strlcpy ((char *)t->start, str, l + 1); + t->len = l; + t->flags = RSPAMD_TEXT_FLAG_OWN; + rspamd_lua_setclass (L, "rspamd{text}", -1); + } + else { + return luaL_error (L, "invalid arguments"); + } + + + return 1; +} + +static gint +lua_text_fromtable (lua_State *L) +{ + LUA_TRACE_POINT; + const gchar *delim = "", *st; + struct rspamd_lua_text *t, *elt; + gsize textlen = 0, dlen, stlen, tblen; + 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 = strlen (delim); + } + + /* Calculate length needed */ + tblen = rspamd_lua_table_size (L, 1); + + for (guint i = 0; i < tblen; i ++) { + lua_rawgeti (L, 1, i + 1); + + if (lua_type (L, -1) == LUA_TSTRING) { +#if LUA_VERSION_NUM >= 502 + stlen = lua_rawlen (L, -1); +#else + stlen = lua_objlen (L, -1); +#endif + textlen += stlen; + } + else { + elt = lua_check_text (L, -1); + + if (elt) { + textlen += elt->len; + } + } + + lua_pop (L, 1); + textlen += dlen; + } + + /* 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); + + for (guint i = 0; i < tblen; i ++) { + 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; + } + else { + elt = lua_check_text (L, -1); + + if (elt) { + memcpy (dest, elt->start, elt->len); + } + } + + memcpy (dest, delim, dlen); + lua_pop (L, 1); + } + + return 1; +} + +static gint +lua_text_len (lua_State *L) +{ + LUA_TRACE_POINT; + struct rspamd_lua_text *t = lua_check_text (L, 1); + gsize l = 0; + + if (t != NULL) { + l = t->len; + } + else { + return luaL_error (L, "invalid arguments"); + } + + lua_pushinteger (L, l); + + return 1; +} + +static gint +lua_text_str (lua_State *L) +{ + LUA_TRACE_POINT; + struct rspamd_lua_text *t = lua_check_text (L, 1); + + if (t != NULL) { + lua_pushlstring (L, t->start, t->len); + } + else { + return luaL_error (L, "invalid arguments"); + } + + return 1; +} + +static gint +lua_text_ptr (lua_State *L) +{ + LUA_TRACE_POINT; + struct rspamd_lua_text *t = lua_check_text (L, 1); + + if (t != NULL) { + lua_pushlightuserdata (L, (gpointer)t->start); + } + else { + return luaL_error (L, "invalid arguments"); + } + + return 1; +} + +static gint +lua_text_take_ownership (lua_State *L) +{ + LUA_TRACE_POINT; + struct rspamd_lua_text *t = lua_check_text (L, 1); + gchar *dest; + + if (t != NULL) { + if (t->flags & RSPAMD_TEXT_FLAG_OWN) { + /* We already own it */ + lua_pushboolean (L, true); + } + else { + dest = g_malloc (t->len); + memcpy (dest, t->start, t->len); + t->start = dest; + t->flags |= RSPAMD_TEXT_FLAG_OWN; + lua_pushboolean (L, true); + } + } + else { + return luaL_error (L, "invalid arguments"); + } + + return 1; +} + +static gint +lua_text_save_in_file (lua_State *L) +{ + LUA_TRACE_POINT; + struct rspamd_lua_text *t = lua_check_text (L, 1); + const gchar *fname = NULL; + guint mode = 00644; + gint fd = -1; + gboolean need_close = FALSE; + + if (t != NULL) { + if (lua_type (L, 2) == LUA_TSTRING) { + fname = luaL_checkstring (L, 2); + + if (lua_type (L, 3) == LUA_TNUMBER) { + mode = lua_tonumber (L, 3); + } + } + else if (lua_type (L, 2) == LUA_TNUMBER) { + /* Created fd */ + fd = lua_tonumber (L, 2); + } + + if (fd == -1) { + if (fname) { + fd = rspamd_file_xopen (fname, O_CREAT | O_WRONLY | O_EXCL, mode, 0); + + if (fd == -1) { + lua_pushboolean (L, false); + lua_pushstring (L, strerror (errno)); + + return 2; + } + need_close = TRUE; + } + else { + fd = STDOUT_FILENO; + } + } + + if (write (fd, t->start, t->len) == -1) { + if (fd != STDOUT_FILENO) { + close (fd); + } + + lua_pushboolean (L, false); + lua_pushstring (L, strerror (errno)); + + return 2; + } + + if (need_close) { + close (fd); + } + + lua_pushboolean (L, true); + } + else { + return luaL_error (L, "invalid arguments"); + } + + return 1; +} + +static gint +lua_text_gc (lua_State *L) +{ + LUA_TRACE_POINT; + struct rspamd_lua_text *t = lua_check_text (L, 1); + + if (t != NULL) { + if (t->flags & RSPAMD_TEXT_FLAG_OWN) { + if (t->flags & RSPAMD_TEXT_FLAG_WIPE) { + rspamd_explicit_memzero ((guchar *)t->start, t->len); + } + + if (t->flags & RSPAMD_TEXT_FLAG_MMAPED) { + munmap ((gpointer)t->start, t->len); + } + else { + g_free ((gpointer)t->start); + } + } + + } + + return 0; +} + +static gint +lua_text_eq (lua_State *L) +{ + LUA_TRACE_POINT; + struct rspamd_lua_text *t1 = lua_check_text (L, 1), + *t2 = lua_check_text (L, 2); + + if (t1->len == t2->len) { + lua_pushboolean (L, memcmp (t1->start, t2->start, t1->len) == 0); + } + else { + lua_pushboolean (L, false); + } + + return 1; +} + +static gint +lua_text_wipe (lua_State *L) +{ + LUA_TRACE_POINT; + struct rspamd_lua_text *t = lua_check_text (L, 1); + + if (t != NULL) { + if (t->flags & RSPAMD_TEXT_FLAG_OWN) { + rspamd_explicit_memzero ((guchar *)t->start, t->len); + } + else { + return luaL_error (L, "cannot wipe not owned text"); + } + + } + else { + return luaL_error (L, "invalid arguments"); + } + + return 0; +} + +static gint +lua_load_text (lua_State * L) +{ + lua_newtable (L); + luaL_register (L, NULL, textlib_f); + + return 1; +} + +void +luaopen_text (lua_State *L) +{ + rspamd_lua_new_class (L, "rspamd{text}", textlib_m); + lua_pop (L, 1); + + rspamd_lua_add_preload (L, "rspamd_text", lua_load_text); +} -- 2.39.5