mirror of
https://github.com/falcosecurity/falco.git
synced 2025-09-13 13:32:50 +00:00
Move compiler state and AST grafting to rule_loader.lua
This is needed so that rule_loader (which should be renamed in a later pass..) can tag filters with their index.
This commit is contained in:
@@ -341,7 +341,6 @@ function expand_macros(node, defs, changed)
|
||||
elseif node.type == "Filter" then
|
||||
if (node.value.type == "Macro") then
|
||||
if (defs[node.value.value] == nil) then
|
||||
tostring = require 'ml'.tstring
|
||||
error("Undefined macro '".. node.value.value .. "' used in filter.")
|
||||
end
|
||||
node.value = defs[node.value.value]
|
||||
@@ -445,7 +444,7 @@ function print_ast(node, level)
|
||||
elseif t == "MacroDef" then
|
||||
-- don't print for now
|
||||
else
|
||||
error ("Unexpected type: "..t)
|
||||
error ("Unexpected type in print_ast: "..t)
|
||||
end
|
||||
end
|
||||
compiler.parser.print_ast = print_ast
|
||||
@@ -463,22 +462,9 @@ end
|
||||
|
||||
|
||||
--[[
|
||||
Sets up compiler state and returns it.
|
||||
|
||||
This is an opaque blob that is passed into subsequent compiler calls and
|
||||
should not be modified by the client.
|
||||
|
||||
It holds state such as macro definitions that must be kept across calls
|
||||
to the line-oriented compiler.
|
||||
Compiles a single line from a digwatch ruleset and updates the passed-in macros table. Returns the AST of the line.
|
||||
--]]
|
||||
function compiler.init()
|
||||
return {macros={}, filter_ast=nil}
|
||||
end
|
||||
|
||||
--[[
|
||||
Compiles a single line from a digwatch ruleset and updates the passed-in state object. Returns the AST of the line.
|
||||
--]]
|
||||
function compiler.compile_line(line, state)
|
||||
function compiler.compile_line(line, macro_defs)
|
||||
local ast, error_msg = compiler.parser.parse_line(line)
|
||||
|
||||
if (error_msg) then
|
||||
@@ -504,7 +490,7 @@ function compiler.compile_line(line, state)
|
||||
end
|
||||
|
||||
for m, _ in pairs(macros) do
|
||||
if state.macros[m] == nil then
|
||||
if macros[m] == nil then
|
||||
error ("Undefined macro '"..m.."' used in '"..line.."'")
|
||||
end
|
||||
end
|
||||
@@ -512,7 +498,7 @@ function compiler.compile_line(line, state)
|
||||
if (ast.type == "MacroDef") then
|
||||
-- Parsed line is a macro definition, so update our dictionary of macros and
|
||||
-- return
|
||||
state.macros[ast.name] = ast.value
|
||||
macro_defs[ast.name] = ast.value
|
||||
return ast
|
||||
|
||||
elseif (ast.type == "Rule") then
|
||||
@@ -522,14 +508,9 @@ function compiler.compile_line(line, state)
|
||||
expand_in(ast.filter)
|
||||
|
||||
repeat
|
||||
expanded = expand_macros(ast, state.macros, false)
|
||||
expanded = expand_macros(ast, macro_defs, false)
|
||||
until expanded == false
|
||||
|
||||
if (state.filter_ast == nil) then
|
||||
state.filter_ast = ast.filter.value
|
||||
else
|
||||
state.filter_ast = { type = "BinaryBoolOp", operator = "or", left = state.filter_ast, right = ast.filter.value }
|
||||
end
|
||||
else
|
||||
error("Unexpected top-level AST type: "..ast.type)
|
||||
end
|
||||
|
@@ -32,7 +32,7 @@ local function install_filter(node)
|
||||
--io.write(node.argument.value.." "..node.operator)
|
||||
|
||||
else
|
||||
error ("Unexpected type: "..t)
|
||||
error ("Unexpected type in install_filter: "..t)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -49,12 +49,34 @@ end
|
||||
|
||||
local state
|
||||
|
||||
--[[
|
||||
Sets up compiler state and returns it.
|
||||
|
||||
It holds state such as macro definitions that must be kept across calls
|
||||
to the line-oriented compiler.
|
||||
--]]
|
||||
local function init()
|
||||
return {macros={}, filter_ast=nil}
|
||||
end
|
||||
|
||||
|
||||
function load_rule(r)
|
||||
if (state == nil) then
|
||||
state = compiler.init()
|
||||
state = init()
|
||||
end
|
||||
local line_ast = compiler.compile_line(r, state.macros)
|
||||
|
||||
if (line_ast.type == "MacroDef") then
|
||||
return
|
||||
elseif (not (line_ast.type == "Rule")) then
|
||||
error ("Unexpected type in load_rule: "..line_ast.type)
|
||||
end
|
||||
|
||||
if (state.filter_ast == nil) then
|
||||
state.filter_ast = line_ast.filter.value
|
||||
else
|
||||
state.filter_ast = { type = "BinaryBoolOp", operator = "or", left = state.filter_ast, right = line_ast.filter.value }
|
||||
end
|
||||
compiler.compile_line(r, state)
|
||||
end
|
||||
|
||||
function on_done()
|
||||
|
@@ -5,10 +5,11 @@ if #arg ~= 1 then
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
local state = compiler.init()
|
||||
local macros = {}
|
||||
local ast
|
||||
|
||||
local function doit(line)
|
||||
local ast = compiler.compile_line(line, state)
|
||||
ast = compiler.compile_line(line, macros)
|
||||
|
||||
if not ast then
|
||||
print("error", error_msg)
|
||||
@@ -20,8 +21,8 @@ for str in string.gmatch(arg[1], "([^;]+)") do
|
||||
doit(str)
|
||||
end
|
||||
|
||||
if not (state.ast == nil) then -- can be nil if only macros
|
||||
compiler.parser.print_ast(state.ast)
|
||||
if not (ast) then
|
||||
compiler.parser.print_ast(ast)
|
||||
end
|
||||
|
||||
os.exit(0)
|
||||
|
Reference in New Issue
Block a user