diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-05-14 12:15:41 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-05-14 12:16:19 +0100 |
commit | fe590fd7b5ea560fd468d57296c4bcf25e6cf320 (patch) | |
tree | a4f491ff149baf7d1636af4357ce8463901eb2c7 /lualib/lua_selectors | |
parent | b9a659c5d01a92d124344d62dff70da431c6443c (diff) | |
download | rspamd-fe590fd7b5ea560fd468d57296c4bcf25e6cf320.tar.gz rspamd-fe590fd7b5ea560fd468d57296c4bcf25e6cf320.zip |
[Fix] Fix calling of methods in selectors
Diffstat (limited to 'lualib/lua_selectors')
-rw-r--r-- | lualib/lua_selectors/init.lua | 133 | ||||
-rw-r--r-- | lualib/lua_selectors/transforms.lua | 3 |
2 files changed, 71 insertions, 65 deletions
diff --git a/lualib/lua_selectors/init.lua b/lualib/lua_selectors/init.lua index 11fcd55d1..ba20810c5 100644 --- a/lualib/lua_selectors/init.lua +++ b/lualib/lua_selectors/init.lua @@ -35,6 +35,7 @@ local fun = require 'fun' local lua_util = require "lua_util" local M = "selectors" local rspamd_text = require "rspamd_text" +local unpack_function = table.unpack or unpack local E = {} local extractors = require "lua_selectors/extractors" @@ -46,6 +47,28 @@ local function pure_type(ltype) return ltype:match('^(.*)_list$') end +local function implicit_tostring(t, ud_or_table) + if t == 'table' then + -- Table (very special) + if ud_or_table.value then + return ud_or_table.value,'string' + elseif ud_or_table.addr then + return ud_or_table.addr,'string' + end + + return logger.slog("%s", ud_or_table),'string' + elseif t == 'userdata' then + if t.cookie and t.cookie == text_cookie then + -- Preserve opaque + return ud_or_table,'string' + else + return tostring(ud_or_table),'string' + end + else + return tostring(ud_or_table),'string' + end +end + local function process_selector(task, sel) local function allowed_type(t) if t == 'string' or t == 'text' or t == 'string_list' or t == 'text_list' then @@ -59,28 +82,6 @@ local function process_selector(task, sel) return pure_type(t) end - local function implicit_tostring(t, ud_or_table) - if t == 'table' then - -- Table (very special) - if ud_or_table.value then - return ud_or_table.value,'string' - elseif ud_or_table.addr then - return ud_or_table.addr,'string' - end - - return logger.slog("%s", ud_or_table),'string' - elseif t == 'userdata' then - if t.cookie and t.cookie == text_cookie then - -- Preserve opaque - return ud_or_table,'string' - else - return tostring(ud_or_table),'string' - end - else - return tostring(ud_or_table),'string' - end - end - local input,etype = sel.selector.get_value(task, sel.selector.args) if not input then @@ -92,55 +93,51 @@ local function process_selector(task, sel) sel.selector.name, etype) local pipe = sel.processor_pipe or E + local first_elt = pipe[1] - if etype:match('^userdata') or etype:match('^table') then - -- Apply userdata conversion first - local first_elt = pipe[1] - - if first_elt and first_elt.method then - -- Explicit conversion - local meth = first_elt - - if meth.types[etype] then - lua_util.debugm(M, task, 'apply method `%s` to %s', - meth.name, etype) - input,etype = meth.process(input, etype) - else - local pt = pure_type(etype) + if first_elt and first_elt.method then + -- Explicit conversion + local meth = first_elt - if meth.types[pt] then - lua_util.debugm(M, task, 'map method `%s` to list of %s', - meth.name, pt) - -- Map method to a list of inputs, excluding empty elements - input = fun.filter(function(map_elt) return map_elt end, - fun.map(function(list_elt) - local ret, _ = meth.process(list_elt, pt) - return ret - end, input)) - etype = 'string_list' - end - end - -- Remove method from the pipeline - pipe = fun.drop_n(1, pipe) + if meth.types[etype] then + lua_util.debugm(M, task, 'apply method `%s` to %s', + meth.name, etype) + input,etype = meth.process(input, etype) else - -- Implicit conversion - local pt = pure_type(etype) - if not pt then - lua_util.debugm(M, task, 'apply implicit conversion %s->string', etype) - input = implicit_tostring(etype, input) - etype = 'string' - else - lua_util.debugm(M, task, 'apply implicit map %s->string', pt) + if meth.types[pt] then + lua_util.debugm(M, task, 'map method `%s` to list of %s', + meth.name, pt) + -- Map method to a list of inputs, excluding empty elements input = fun.filter(function(map_elt) return map_elt end, fun.map(function(list_elt) - local ret = implicit_tostring(pt, list_elt) + local ret, _ = meth.process(list_elt, pt) return ret end, input)) etype = 'string_list' end end + -- Remove method from the pipeline + pipe = fun.drop_n(1, pipe) + elseif etype:match('^userdata') or etype:match('^table') then + -- Implicit conversion + + local pt = pure_type(etype) + + if not pt then + lua_util.debugm(M, task, 'apply implicit conversion %s->string', etype) + input = implicit_tostring(etype, input) + etype = 'string' + else + lua_util.debugm(M, task, 'apply implicit map %s->string', pt) + input = fun.filter(function(map_elt) return map_elt end, + fun.map(function(list_elt) + local ret = implicit_tostring(pt, list_elt) + return ret + end, input)) + etype = 'string_list' + end end -- Now we fold elements using left fold @@ -337,14 +334,24 @@ exports.parse_selector = function(cfg, str) types = { userdata = true, table = true, + string = true, }, map_type = 'string', process = function(inp, t, args) - if t == 'userdata' then - return inp[method_name](inp, args),'string' - else - -- Table + if t == 'table' then return inp[method_name],'string' + else + -- We call method unpacking arguments and dropping all but the first result returned + local ret = (inp[method_name](inp, unpack_function(args))) + local ret_type = type(ret) + -- Now apply types heuristic + if ret_type == 'string' then + return ret,'string' + elseif ret_type == 'table' then + return ret,'string_list' + else + return implicit_tostring(ret_type, ret) + end end end, } diff --git a/lualib/lua_selectors/transforms.lua b/lualib/lua_selectors/transforms.lua index e47fdcec6..bbf5f510a 100644 --- a/lualib/lua_selectors/transforms.lua +++ b/lualib/lua_selectors/transforms.lua @@ -132,9 +132,8 @@ local transform_function = { ['types'] = { ['string'] = true }, - ['map_type'] = 'hash', + ['map_type'] = 'string', ['process'] = function(inp, _, args) - return common.create_digest(inp, args),'string' end, ['description'] = [[Create a digest from a string. |