Improve alternate event/hook prototype matching

This fixes it to again allow the old behavior of matching a handler
against the canonical prototype as long as all argument types, but not
necessarily names, match.
This commit is contained in:
Jon Siwek 2020-04-09 20:20:38 -07:00
parent 8c0e8ecd28
commit 9b6934eab8
5 changed files with 85 additions and 8 deletions

View file

@ -584,8 +584,10 @@ void FuncType::AddPrototype(Prototype p)
std::optional<FuncType::Prototype> FuncType::FindPrototype(const RecordType& args) const std::optional<FuncType::Prototype> FuncType::FindPrototype(const RecordType& args) const
{ {
for ( const auto& p : prototypes ) for ( auto i = 0u; i < prototypes.size(); ++i )
{ {
const auto& p = prototypes[i];
if ( args.NumFields() != p.args->NumFields() ) if ( args.NumFields() != p.args->NumFields() )
continue; continue;
@ -604,11 +606,12 @@ std::optional<FuncType::Prototype> FuncType::FindPrototype(const RecordType& arg
auto ptype = p.args->FieldType(i); auto ptype = p.args->FieldType(i);
auto desired_type = args.FieldType(i); auto desired_type = args.FieldType(i);
if ( same_type(ptype, desired_type) ) if ( ! same_type(ptype, desired_type) ||
continue; ! streq(args.FieldName(i), p.args->FieldName(i)) )
{
matched = false; matched = false;
break; break;
}
} }
if ( matched ) if ( matched )

View file

@ -432,6 +432,21 @@ static std::optional<FuncType::Prototype> func_type_check(const FuncType* decl,
return decl->FindPrototype(*impl->Args()); return decl->FindPrototype(*impl->Args());
} }
static bool canonical_arg_types_match(const FuncType* decl, const FuncType* impl)
{
auto canon_args = decl->Args();
auto impl_args = impl->Args();
if ( canon_args->NumFields() != impl_args->NumFields() )
return false;
for ( auto i = 0; i < canon_args->NumFields(); ++i )
if ( ! same_type(canon_args->FieldType(i), impl_args->FieldType(i)) )
return false;
return true;
}
void begin_func(ID* id, const char* module_name, function_flavor flavor, void begin_func(ID* id, const char* module_name, function_flavor flavor,
bool is_redef, IntrusivePtr<FuncType> t, attr_list* attrs) bool is_redef, IntrusivePtr<FuncType> t, attr_list* attrs)
{ {
@ -462,7 +477,16 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor,
t->Warn("use of deprecated prototype", id); t->Warn("use of deprecated prototype", id);
} }
else else
t->Error("use of undeclared alternate prototype", id); {
auto decl = id->Type()->AsFuncType();
// Allow renaming arguments, but only for the canonical
// prototypes of hooks/events.
if ( canonical_arg_types_match(decl, t.get()) )
prototype = decl->Prototypes()[0];
else
t->Error("use of undeclared alternate prototype", id);
}
} }
else if ( is_redef ) else if ( is_redef )

View file

@ -1,2 +1,2 @@
error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-event-hook-prototypes-invalid-arg/alternate-event-hook-prototypes-invalid-arg.zeek, line 5 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-event-hook-prototypes-invalid-arg/alternate-event-hook-prototypes-invalid-arg.zeek, line 4: alternate function prototype already exists (event(nope:string; cantdothis:count;) and record { s:string; c:count; }) error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-event-hook-prototypes-invalid-arg/alternate-event-hook-prototypes-invalid-arg.zeek, line 5 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-event-hook-prototypes-invalid-arg/alternate-event-hook-prototypes-invalid-arg.zeek, line 4: alternate function prototype arg 'nope' not found in canonical prototype (event(nope:string; cantdothis:count;) and event(s:string; c:count;))
error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-event-hook-prototypes-invalid-arg/alternate-event-hook-prototypes-invalid-arg.zeek, line 8 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-event-hook-prototypes-invalid-arg/alternate-event-hook-prototypes-invalid-arg.zeek, line 7: alternate function prototype arg 'andnotthiseither' not found in canonical prototype (hook(andnotthiseither:addr;) : bool and hook(s:string; c:count;) : bool) error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-event-hook-prototypes-invalid-arg/alternate-event-hook-prototypes-invalid-arg.zeek, line 8 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-event-hook-prototypes-invalid-arg/alternate-event-hook-prototypes-invalid-arg.zeek, line 7: alternate function prototype arg 'andnotthiseither' not found in canonical prototype (hook(andnotthiseither:addr;) : bool and hook(s:string; c:count;) : bool)

View file

@ -0,0 +1,6 @@
foo, A, B, C
foo, A, B, C
reverse foo, A, B, C
foo a, A
foo b, B
foo c, C

View file

@ -0,0 +1,44 @@
# @TEST-EXEC: zeek -b %INPUT > out
# @TEST-EXEC: btest-diff out
global foo: event(a: string, b: string, c: string);
global foo: event(c: string, b: string, a: string);
global foo: event(a: string);
global foo: event(b: string);
global foo: event(c: string);
event foo(a: string, b: string, c: string)
{
print "foo", a, b, c;
}
event foo(mya: string, b: string, c: string)
{
print "foo", mya, b, c;
}
event foo(c: string, b: string, a: string)
{
print "reverse foo", a, b, c;
}
event foo(a: string)
{
print "foo a", a;
}
event foo(b: string)
{
print "foo b", b;
}
event foo(c: string)
{
print "foo c", c;
}
event zeek_init()
{
event foo("A", "B", "C");
}