Func: Do not crash on va_args confusion for script funcs

Script and BIF functions with a single any parameter are excluded from
type checking regarding arguments. This makes it possible to call a
ScriptFunc with more arguments than it actually has parameters and frame
space for, causing heap-buffer-overflows.

This change runtime checks expected parameters and provided arguments
and short-circuits execution as well as logging runtime expression errors.

Fixes #2446
This commit is contained in:
Arne Welzel 2022-10-28 13:55:57 +02:00
parent 2ed42ef771
commit 4314467e44
6 changed files with 70 additions and 0 deletions

View file

@ -362,6 +362,17 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const
const CallExpr* call_expr = parent ? parent->GetCall() : nullptr;
call_stack.emplace_back(CallInfo{call_expr, this, *args});
// If a script function is ever invoked with more arguments than it has
// parameters log an error and return. Most likely a "variadic function"
// that only has a single any parameter and is excluded from static type
// checking is involved. This should otherwise not be possible to hit.
auto num_params = static_cast<size_t>(GetType()->Params()->NumFields());
if ( args->size() > num_params )
{
emit_builtin_exception("too many arguments for function call");
return nullptr;
}
if ( etm && Flavor() == FUNC_FLAVOR_EVENT )
etm->StartEvent(this, args);

View file

@ -0,0 +1,2 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
expression error in <...>/any-script-func-variadic-errors.zeek, line 14: too many arguments for function call (f(1, 2))

View file

@ -0,0 +1,2 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
l=lambda local x=1

View file

@ -0,0 +1,2 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
expression error in <...>/any-script-func-variadic-errors.zeek, line 15: too many arguments for function call (f(1, 2))

View file

@ -0,0 +1,6 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
zeek_init() &priority=10
l=a local x=1
zeek_init() &priority=-10
l=a local x=1
l=a local x=1

View file

@ -0,0 +1,47 @@
# @TEST-EXEC: zeek -b %INPUT >output
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff output
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff .stderr
function f(x: any)
{
local l = "a local";
print fmt("l=%s x=%s", l, x);
}
event zeek_init() &priority=10
{
print "zeek_init() &priority=10";
f(1);
f(1, 2);
# Not reached
print "FAIL";
f(1);
}
event zeek_init() &priority=-10
{
print "zeek_init() &priority=-10";
f(1);
f(1);
}
@TEST-START-NEXT
# Do not allow to call variadic through a script-level variable.
global f: function(x: any);
event zeek_init()
{
local _lambda = function(x: any) {
local l = "lambda local";
print fmt("l=%s x=%s", l, x);
};
f = _lambda;
f(1);
f(1, 2);
# Not reached
print "FAIL";
f(1);
}