Fix wrong frame offsets for locals of alternate event/hook prototypes

Local frame offsets were being assigned based on number of the alternate
prototype's parameters, which may end up having less total parameters
than the canonical prototype, causing the local value to incorrectly
overwrite an event/hook argument value.
This commit is contained in:
Jon Siwek 2020-07-10 01:53:26 -07:00
parent 8597b998bb
commit 20294d372c
5 changed files with 71 additions and 14 deletions

View file

@ -429,6 +429,8 @@ public:
bool deprecated; bool deprecated;
std::string deprecation_msg; std::string deprecation_msg;
RecordTypePtr args; RecordTypePtr args;
// Maps from parameter index in canonical prototype to
// parameter index in this alternate prorotype.
std::map<int, int> offsets; std::map<int, int> offsets;
}; };

View file

@ -96,7 +96,7 @@ static bool add_prototype(const zeek::detail::IDPtr& id, zeek::Type* t,
return false; return false;
} }
offsets[i] = o; offsets[o] = i;
} }
auto deprecated = false; auto deprecated = false;
@ -604,24 +604,54 @@ void begin_func(zeek::detail::IDPtr id, const char* module_name,
else else
id->SetType(t); id->SetType(t);
const auto& args = t->Params();
const auto& canon_args = id->GetType()->AsFuncType()->Params();
zeek::detail::push_scope(std::move(id), std::move(attrs)); zeek::detail::push_scope(std::move(id), std::move(attrs));
const auto& args = t->Params(); for ( int i = 0; i < canon_args->NumFields(); ++i )
int num_args = args->NumFields();
for ( int i = 0; i < num_args; ++i )
{ {
zeek::TypeDecl* arg_i = args->FieldDecl(i); zeek::TypeDecl* arg_i;
bool hide = false;
if ( prototype )
{
auto it = prototype->offsets.find(i);
if ( it == prototype->offsets.end() )
{
// Alternate prototype hides this param
hide = true;
arg_i = canon_args->FieldDecl(i);
}
else
{
// Alternate prototype maps this param to another index
arg_i = args->FieldDecl(it->second);
}
}
else
{
if ( i < args->NumFields() )
arg_i = args->FieldDecl(i);
else
break;
}
auto arg_id = zeek::detail::lookup_ID(arg_i->id, module_name); auto arg_id = zeek::detail::lookup_ID(arg_i->id, module_name);
if ( arg_id && ! arg_id->IsGlobal() ) if ( arg_id && ! arg_id->IsGlobal() )
arg_id->Error("argument name used twice"); arg_id->Error("argument name used twice");
arg_id = zeek::detail::install_ID(arg_i->id, module_name, false, false); const char* local_name = arg_i->id;
arg_id->SetType(arg_i->type);
if ( prototype ) if ( hide )
arg_id->SetOffset(prototype->offsets[i]); // Note the illegal '-' in hidden name implies we haven't
// clobbered any local variable names.
local_name = fmt("%s-hidden", local_name);
arg_id = zeek::detail::install_ID(local_name, module_name, false, false);
arg_id->SetType(arg_i->type);
} }
if ( zeek::detail::Attr* depr_attr = find_attr(zeek::detail::current_scope()->Attrs().get(), if ( zeek::detail::Attr* depr_attr = find_attr(zeek::detail::current_scope()->Attrs().get(),

View file

@ -0,0 +1,3 @@
warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 11 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 7: use of deprecated parameter 'b': Don't use 'b' (event(a:string; b:string; c:string;))
warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 30 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 9: use of deprecated 'myev' prototype: Don't use this prototype (event(a:string; b:string;))
error in ./hide.zeek, line 5: unknown identifier b, at or near "b"

View file

@ -1,5 +1,8 @@
warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 9 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 5: use of deprecated parameter 'b': Don't use 'b' (event(a:string; b:string; c:string;)) warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 11 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 7: use of deprecated parameter 'b': Don't use 'b' (event(a:string; b:string; c:string;))
warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 19 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 7: use of deprecated 'myev' prototype: Don't use this prototype (event(a:string; b:string;)) warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 30 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 9: use of deprecated 'myev' prototype: Don't use this prototype (event(a:string; b:string;))
myev (canon), one, two, three myev (canon), one, two, three
myev (new), one, three myev (new), one, three, [1, 2, 3]
myev (new), one, three, 0
myev (new), one, three, 1
myev (new), one, three, 2
myev (old), one, two myev (old), one, two

View file

@ -1,6 +1,8 @@
# @TEST-EXEC: zeek -b %INPUT >out 2>&1 # @TEST-EXEC: zeek -b %INPUT >out 2>&1
# #
# @TEST-EXEC-FAIL: zeek -b %INPUT hide.zeek >hidden-error 2>&1
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out # @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff hidden-error
global myev: event(a: string, b: string &deprecated="Don't use 'b'", c: string); global myev: event(a: string, b: string &deprecated="Don't use 'b'", c: string);
global myev: event(a: string, c: string); global myev: event(a: string, c: string);
@ -13,7 +15,16 @@ event myev(a: string, b: string, c: string) &priority=11
event myev(a: string, c: string) &priority = 7 event myev(a: string, c: string) &priority = 7
{ {
print "myev (new)", a, c; local ddd = vector(1,2,3);
print "myev (new)", a, c, ddd;
}
global eee = vector(1,2,3);
event myev(a: string, c: string) &priority = 6
{
for ( o in eee )
print "myev (new)", a, c, o;
} }
event myev(a: string, b: string) &priority = 5 event myev(a: string, b: string) &priority = 5
@ -26,3 +37,11 @@ event zeek_init()
event myev("one", "two", "three"); event myev("one", "two", "three");
} }
@TEST-START-FILE hide.zeek
event myev(a: string, c: string) &priority = 7
{
local ddd = vector(1,2,3);
print "myev (new)", a, c, ddd;
print b;
}
@TEST-END-FILE