mirror of
https://github.com/falcosecurity/falco.git
synced 2025-07-15 23:36:19 +00:00
Expand in
relational expressions
For example, `a.b in [1, 2]` is expanded to `a.b = 1 or a.b = 2`. This is done over the AST, not filter text.
This commit is contained in:
parent
3dab9edc9d
commit
79cdf31aa7
@ -15,12 +15,12 @@ function error_exit_bad
|
||||
|
||||
function good
|
||||
{
|
||||
lua test.lua "$1" || error_exit_good "$1"
|
||||
lua test.lua "$1" 2> /dev/null || error_exit_good "$1"
|
||||
}
|
||||
|
||||
function bad
|
||||
{
|
||||
lua test.lua "$1" && error_exit_bad "$1"
|
||||
lua test.lua "$1" 2> /dev/null && error_exit_bad "$1"
|
||||
}
|
||||
|
||||
# Filters
|
||||
@ -47,7 +47,6 @@ good "a.b = 'bla'"
|
||||
good "a.b = not"
|
||||
good "a.b contains bla"
|
||||
good "a.b icontains 'bla'"
|
||||
good "a.g in ()"
|
||||
good "a.g in (1, 'a', b)"
|
||||
good "a.g in ( 1 ,, , b)"
|
||||
good "evt.dir=> and fd.name=*.log"
|
||||
@ -55,6 +54,7 @@ good "evt.dir=> and fd.name=/var/log/httpd.log"
|
||||
good "a.g in (1, 'a', b.c)"
|
||||
good "a.b = a.a"
|
||||
|
||||
bad "a.g in ()"
|
||||
bad "(a.b = 1"
|
||||
# Macros
|
||||
|
||||
@ -66,4 +66,6 @@ good "a : evt.dir=>"
|
||||
good "inbound: (syscall.type=listen and evt.dir='>') or (syscall.type=accept and evt.dir='<')"
|
||||
bad "a:"
|
||||
|
||||
echo
|
||||
echo "All tests passed."
|
||||
exit 0
|
||||
|
@ -237,6 +237,74 @@ local G = {
|
||||
OneWord = V"Name" + V"Number" + V"String" + P(1);
|
||||
}
|
||||
|
||||
function map(f, arr)
|
||||
local res = {}
|
||||
for i,v in ipairs(arr) do
|
||||
res[i] = f(v)
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
function foldr(f, acc, arr)
|
||||
for i,v in pairs(arr) do
|
||||
acc = f(acc, v)
|
||||
end
|
||||
return acc
|
||||
end
|
||||
|
||||
--[[
|
||||
Traverses the AST and replaces `in` relational expressions with a sequence of ORs.
|
||||
|
||||
For example, `a.b in [1, 2]` is expanded to `a.b = 1 or a.b = 2` (in ASTs)
|
||||
]]--
|
||||
function expand_in(node)
|
||||
local t = node.type
|
||||
|
||||
if t == "Filter" then
|
||||
expand_in(node.value)
|
||||
|
||||
elseif t == "UnaryBoolOp" then
|
||||
expand_in(node.argument)
|
||||
|
||||
elseif t == "BinaryBoolOp" then
|
||||
expand_in(node.left)
|
||||
expand_in(node.right)
|
||||
|
||||
elseif t == "BinaryRelOp" and node.operator == "in" then
|
||||
if (table.maxn(node.right.elements) == 0) then
|
||||
error ("In list with zero elements")
|
||||
end
|
||||
|
||||
local mapper = function(element)
|
||||
return {
|
||||
type = "BinaryRelOp",
|
||||
operator = "eq",
|
||||
left = node.left,
|
||||
right = element
|
||||
}
|
||||
end
|
||||
|
||||
local equalities = map(mapper, node.right.elements)
|
||||
local lasteq = equalities[table.maxn(equalities)]
|
||||
equalities[table.maxn(equalities)] = nil
|
||||
|
||||
local folder = function(left, right)
|
||||
return {
|
||||
type = "BinaryBoolOp",
|
||||
operator = "or",
|
||||
left = left,
|
||||
right = right
|
||||
}
|
||||
end
|
||||
lasteq = foldr(folder, lasteq, equalities)
|
||||
|
||||
node.type=lasteq.type
|
||||
node.operator=lasteq.operator
|
||||
node.left=lasteq.left
|
||||
node.right=lasteq.right
|
||||
end
|
||||
end
|
||||
|
||||
function print_ast(node, level)
|
||||
local t = node.type
|
||||
local prefix = string.rep(" ", level*2)
|
||||
@ -276,6 +344,10 @@ function parser.parse (subject)
|
||||
local errorinfo = { subject = subject }
|
||||
lpeg.setmaxstack(1000)
|
||||
local ast, error_msg = lpeg.match(G, subject, nil, errorinfo)
|
||||
if (error_msg) then
|
||||
return ast, error_msg
|
||||
end
|
||||
expand_in(ast)
|
||||
return ast, error_msg
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user