Skip to content

Commit

Permalink
[Fix] Core: Fix squeezed dependencies handling for virtual symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
vstakhov committed Mar 22, 2019
1 parent fbf41a8 commit 59df0ce
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 72 deletions.
22 changes: 22 additions & 0 deletions lualib/lua_squeeze_rules.lua
Expand Up @@ -27,6 +27,8 @@ local SN = 'lua_squeeze'
local squeeze_sym = 'LUA_SQUEEZE'
local squeeze_function_ids = {}
local squeezed_groups = {}
local last_rule
local virtual_symbols = {}

local function gen_lua_squeeze_function(order)
return function(task)
Expand Down Expand Up @@ -142,9 +144,22 @@ exports.squeeze_rule = function(s, func, flags)
}
end

last_rule = s

return squeeze_function_ids[1]
end

-- TODO: poor approach, we register all virtual symbols with the previous real squeezed symbol
exports.squeeze_virtual = function(id, name)
if squeeze_function_ids[1] and id == squeeze_function_ids[1] and last_rule then
virtual_symbols[name] = last_rule

return id
end

return -1
end

exports.squeeze_dependency = function(child, parent)
lua_util.debugm(SN, rspamd_config, 'squeeze dep %s->%s', child, parent)

Expand Down Expand Up @@ -222,6 +237,13 @@ exports.squeeze_init = function()
end

for parent,children in pairs(squeezed_deps) do
if not squeezed_symbols[parent] then
local real_parent = virtual_symbols[parent]
if real_parent then
parent = real_parent
end
end

if not squeezed_symbols[parent] then
-- Trivial case, external dependnency

Expand Down
27 changes: 27 additions & 0 deletions src/libserver/rspamd_symcache.c
Expand Up @@ -304,6 +304,33 @@ rspamd_symcache_find_filter (struct rspamd_symcache *cache,
return NULL;
}

const gchar *
rspamd_symcache_get_parent (struct rspamd_symcache *cache,
const gchar *symbol)
{
struct rspamd_symcache_item *item;

g_assert (cache != NULL);

if (symbol == NULL) {
return NULL;
}

item = g_hash_table_lookup (cache->items_by_symbol, symbol);

if (item != NULL) {

if (item->is_virtual) {
item = g_ptr_array_index (cache->items_by_id,
item->specific.virtual.parent);
}

return item->symbol;
}

return NULL;
}

static gint
postfilters_cmp (const void *p1, const void *p2, gpointer ud)
{
Expand Down
9 changes: 9 additions & 0 deletions src/libserver/rspamd_symcache.h
Expand Up @@ -250,6 +250,15 @@ void rspamd_symcache_enable_symbol_perm (struct rspamd_symcache *cache,
struct rspamd_abstract_callback_data* rspamd_symcache_get_cbdata (
struct rspamd_symcache *cache, const gchar *symbol);

/**
* Returns symbol's parent name (or symbol name itself)
* @param cache
* @param symbol
* @return
*/
const gchar *rspamd_symcache_get_parent (struct rspamd_symcache *cache,
const gchar *symbol);

/**
* Adds flags to a symbol
* @param cache
Expand Down
195 changes: 123 additions & 72 deletions src/lua/lua_config.c
Expand Up @@ -437,6 +437,13 @@ LUA_FUNCTION_DEF (config, enable_symbol);
*/
LUA_FUNCTION_DEF (config, disable_symbol);

/***
* @method rspamd_config:get_symbol_parent(symbol)
* Returns a parent symbol for specific symbol (or symbol itself if top level)
* @param {string} symbol symbol's name
*/
LUA_FUNCTION_DEF (config, get_symbol_parent);

/***
* @method rspamd_config:__newindex(name, callback)
* This metamethod is called if new indicies are added to the `rspamd_config` object.
Expand Down Expand Up @@ -813,6 +820,7 @@ static const struct luaL_reg configlib_m[] = {
LUA_INTERFACE_DEF (config, get_symbol_callback),
LUA_INTERFACE_DEF (config, set_symbol_callback),
LUA_INTERFACE_DEF (config, get_symbol_stat),
LUA_INTERFACE_DEF (config, get_symbol_parent),
LUA_INTERFACE_DEF (config, register_finish_script),
LUA_INTERFACE_DEF (config, register_monitored),
LUA_INTERFACE_DEF (config, add_doc),
Expand Down Expand Up @@ -1363,50 +1371,48 @@ lua_metric_symbol_callback_return (struct thread_entry *thread_entry, int ret)
}

static gint
rspamd_register_symbol_fromlua (lua_State *L,
struct rspamd_config *cfg,
const gchar *name,
gint ref,
gdouble weight,
gint priority,
enum rspamd_symbol_type type,
gint parent,
gboolean optional,
gboolean no_squeeze)
rspamd_lua_squeeze_rule (lua_State *L,
struct rspamd_config *cfg,
const gchar *name,
gint cbref,
enum rspamd_symbol_type type,
gint parent)
{
struct lua_callback_data *cd;
gint ret = -1, err_idx;

if (priority == 0 && weight < 0) {
priority = 1;
}
lua_pushcfunction (L, &rspamd_lua_traceback);
err_idx = lua_gettop (L);

if ((ret = rspamd_symcache_find_symbol (cfg->cache, name)) != -1) {
if (optional) {
msg_debug_config ("duplicate symbol: %s, skip registering", name);
if (type & SYMBOL_TYPE_VIRTUAL) {
if (rspamd_lua_require_function (L, "lua_squeeze_rules", "squeeze_virtual")) {
lua_pushnumber (L, parent);
if (name) {
lua_pushstring (L, name);
}
else {
lua_pushnil (L);
}

return ret;
/* Now call for squeeze function */
if (lua_pcall (L, 2, 1, err_idx) != 0) {
GString *tb = lua_touserdata (L, -1);
msg_err_config ("call to squeeze_virtual failed: %v", tb);

if (tb) {
g_string_free (tb, TRUE);
}
}

ret = lua_tonumber (L, -1);
}
else {
msg_err_config ("duplicate symbol: %s, skip registering", name);

return -1;
msg_err_config ("lua_squeeze is absent or bad (missing squeeze_virtual),"
" your Rspamd installation"
" is likely corrupted!");
}
}

if (ref != -1) {
if (type & SYMBOL_TYPE_USE_CORO) {
/* Coroutines are incompatible with squeezing */
no_squeeze = TRUE;
}
/*
* We call for routine called lua_squeeze_rules.squeeze_rule if it exists
*/
lua_pushcfunction (L, &rspamd_lua_traceback);
err_idx = lua_gettop (L);

if (!no_squeeze && (type & (SYMBOL_TYPE_CALLBACK|SYMBOL_TYPE_NORMAL)) &&
rspamd_lua_require_function (L, "lua_squeeze_rules", "squeeze_rule")) {
else {
if (rspamd_lua_require_function (L, "lua_squeeze_rules", "squeeze_rule")) {
if (name) {
lua_pushstring (L, name);
}
Expand All @@ -1415,7 +1421,7 @@ rspamd_register_symbol_fromlua (lua_State *L,
}

/* Push function reference */
lua_rawgeti (L, LUA_REGISTRYINDEX, ref);
lua_rawgeti (L, LUA_REGISTRYINDEX, cbref);

/* Flags */
lua_createtable (L, 0, 0);
Expand Down Expand Up @@ -1452,45 +1458,62 @@ rspamd_register_symbol_fromlua (lua_State *L,
}

ret = lua_tonumber (L, -1);
}
else {
msg_err_config ("lua_squeeze is absent or bad (missing squeeze_rule),"
" your Rspamd installation"
" is likely corrupted!");
}
}

if (ret == -1) {
/* Do direct registration */
cd = rspamd_mempool_alloc0 (cfg->cfg_pool,
sizeof (struct lua_callback_data));
cd->magic = rspamd_lua_callback_magic;
cd->cb_is_ref = TRUE;
cd->callback.ref = ref;
cd->L = L;
/* Cleanup lua stack */
lua_settop (L, err_idx - 1);

if (name) {
cd->symbol = rspamd_mempool_strdup (cfg->cfg_pool, name);
}
return ret;
}

if (type & SYMBOL_TYPE_USE_CORO) {
ret = rspamd_symcache_add_symbol (cfg->cache,
name,
priority,
lua_metric_symbol_callback_coro,
cd,
type,
parent);
}
else {
ret = rspamd_symcache_add_symbol (cfg->cache,
name,
priority,
lua_metric_symbol_callback,
cd,
type,
parent);
}
static gint
rspamd_register_symbol_fromlua (lua_State *L,
struct rspamd_config *cfg,
const gchar *name,
gint ref,
gdouble weight,
gint priority,
enum rspamd_symbol_type type,
gint parent,
gboolean optional,
gboolean no_squeeze)
{
struct lua_callback_data *cd;
gint ret = -1;

rspamd_mempool_add_destructor (cfg->cfg_pool,
(rspamd_mempool_destruct_t) lua_destroy_cfg_symbol,
cd);
}
if (priority == 0 && weight < 0) {
priority = 1;
}

if ((ret = rspamd_symcache_find_symbol (cfg->cache, name)) != -1) {
if (optional) {
msg_debug_config ("duplicate symbol: %s, skip registering", name);

return ret;
}
else {
msg_err_config ("duplicate symbol: %s, skip registering", name);

return -1;
}
}

if (ref != -1) {
if (type & SYMBOL_TYPE_USE_CORO) {
/* Coroutines are incompatible with squeezing */
no_squeeze = TRUE;
}
/*
* We call for routine called lua_squeeze_rules.squeeze_rule if it exists
*/
if (no_squeeze || (ret = rspamd_lua_squeeze_rule (L, cfg, name, ref,
type, parent)) == -1) {
cd = rspamd_mempool_alloc0 (cfg->cfg_pool,
sizeof (struct lua_callback_data));
cd->magic = rspamd_lua_callback_magic;
Expand Down Expand Up @@ -1524,11 +1547,13 @@ rspamd_register_symbol_fromlua (lua_State *L,
(rspamd_mempool_destruct_t)lua_destroy_cfg_symbol,
cd);
}

/* Cleanup lua stack */
lua_settop (L, err_idx - 1);
}
else {
if (!no_squeeze) {
rspamd_lua_squeeze_rule (L, cfg, name, ref,
type, parent);
}
/* Not a squeezed symbol */
ret = rspamd_symcache_add_symbol (cfg->cache,
name,
priority,
Expand Down Expand Up @@ -2197,6 +2222,9 @@ rspamd_lua_squeeze_dependency (lua_State *L, struct rspamd_config *cfg,
ret = lua_toboolean (L, -1);
}
}
else {
msg_err_config ("cannot get lua_squeeze_rules.squeeze_dependency function");
}

lua_settop (L, err_idx - 1);

Expand Down Expand Up @@ -3411,6 +3439,29 @@ lua_config_get_symbol_stat (lua_State *L)
return 1;
}

static gint
lua_config_get_symbol_parent (lua_State *L)
{
LUA_TRACE_POINT;
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *sym = luaL_checkstring (L, 2), *parent;

if (cfg != NULL && sym != NULL) {
parent = rspamd_symcache_get_parent (cfg->cache, sym);

if (parent) {
lua_pushstring (L, parent);
}
else {
lua_pushnil (L);
}
}
else {
return luaL_error (L, "invalid arguments");
}

return 1;
}

static gint
lua_config_register_finish_script (lua_State *L)
Expand Down

0 comments on commit 59df0ce

Please sign in to comment.