Merge remote-tracking branch 'origin/topic/jsiwek/alternate-hook-event-prototypes'

* origin/topic/jsiwek/alternate-hook-event-prototypes:
  Add warning for ineffective &default arguments in handlers
  Fix frame size allocation of alternate event/hook handlers
  Emit error for alternate event/hook prototype args with attributes
  Improve alternate event/hook prototype matching
  Allow alternate event/hook prototype declarations
This commit is contained in:
Tim Wojtulewicz 2020-04-13 14:59:50 -07:00
commit ba1c03188f
24 changed files with 715 additions and 16 deletions

62
CHANGES
View file

@ -1,4 +1,66 @@
3.2.0-dev.391 | 2020-04-13 14:59:50 -0700
* Add warning for ineffective &default arguments in handlers
For event/hook handlers that had a previous declaration, any &default
arguments are ineffective. Only &default uses in the initial
prototype's arguments have an effect (that includes if the handler
is actually the site at which the declaration occurs). (Jon Siwek, Corelight)
* Fix frame size allocation of alternate event/hook handlers
When the only existing handler doesn't use the full argument list, still
have to ensure the full frame is allocated because all arguments get set
regardless. (Jon Siwek, Corelight)
* Emit error for alternate event/hook prototype args with attributes
Argument attributes are only allowed in the canonical prototype. (Jon Siwek, Corelight)
* 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. (Jon Siwek, Corelight)
* Allow alternate event/hook prototype declarations
The alternates must be some subset of the canonical prototype (the one
that's first declared) and allows users to define handlers for any
such prototype. Example:
# Prototype declarations
global my_event: event(s: string, c: count);
global my_event: event(c: count);
global my_event: event();
# Handler definitions
event my_event(s: string, c: count) { print s, c; }
event my_event(c: count) { print c; }
event my_event() { }
This allows handlers to consume a subset of the arguments or even
re-order them. This makes it easier to either extend an existing
event/hook's arguments and/or deprecate usages of certain prototypes. (Jon Siwek, Corelight)
* Fix Broker topics used to uniquely identify cluster nodes
Node-specific topic prefix subscriptions/publications now add a trailing
slash like "zeek/cluster/node/<name>/". Without the trailing slash,
messages attempting to target "proxy-10" may also be sent to "proxy-1"
since subscription matching is prefix-based. (Jon Siwek, Corelight)
* Update submodule(s)
[nomail] (Jon Siwek, Corelight)
* Fix include in X509Common.h
Give full path to Analyzer.h, so that X509Common.h is include-able by
plugins. (Johanna Amann, Corelight)
3.2.0-dev.382 | 2020-04-09 13:17:03 -0700
* Remove 'using namespace std' as well as other using statements from headers.

View file

@ -1 +1 @@
3.2.0-dev.382
3.2.0-dev.391

@ -1 +1 @@
Subproject commit 69d7443794e8712344561a49517340aab3e58ff4
Subproject commit abfe5cb864a17b8c06c70d4674b32a51280ee62b

2
doc

@ -1 +1 @@
Subproject commit 23327f87955b382729db1419ba8e75feba038c05
Subproject commit fe6fe81c1524bb2d41b1d1d2fa80177e1437e501

View file

@ -28,7 +28,7 @@ event rule_expire(r: Rule, p: PluginState) &priority=-5
rule_expire_impl(r, p);
}
event rule_exists(r: Rule, p: PluginState, msg: string &default="") &priority=5
event rule_exists(r: Rule, p: PluginState, msg: string) &priority=5
{
rule_added_impl(r, p, T, msg);
@ -36,7 +36,7 @@ event rule_exists(r: Rule, p: PluginState, msg: string &default="") &priority=5
schedule r$expire { rule_expire(r, p) };
}
event rule_added(r: Rule, p: PluginState, msg: string &default="") &priority=5
event rule_added(r: Rule, p: PluginState, msg: string) &priority=5
{
rule_added_impl(r, p, F, msg);
@ -44,7 +44,7 @@ event rule_added(r: Rule, p: PluginState, msg: string &default="") &priority=5
schedule r$expire { rule_expire(r, p) };
}
event rule_removed(r: Rule, p: PluginState, msg: string &default="") &priority=-5
event rule_removed(r: Rule, p: PluginState, msg: string) &priority=-5
{
rule_removed_impl(r, p, msg);
}
@ -54,7 +54,7 @@ event rule_timeout(r: Rule, i: FlowInfo, p: PluginState) &priority=-5
rule_timeout_impl(r, i, p);
}
event rule_error(r: Rule, p: PluginState, msg: string &default="") &priority=-5
event rule_error(r: Rule, p: PluginState, msg: string) &priority=-5
{
rule_error_impl(r, p, msg);
}

View file

@ -259,7 +259,7 @@ function cr_check_rule(r: Rule): bool
@if ( ! Cluster::is_enabled() || ( Cluster::is_enabled() && Cluster::local_node_type() == Cluster::MANAGER ) )
event rule_added(r: Rule, p: PluginState, msg: string &default="")
event rule_added(r: Rule, p: PluginState, msg: string)
{
if ( !cr_check_rule(r) )
return;

View file

@ -449,6 +449,11 @@ void BroFunc::AddBody(IntrusivePtr<Stmt> new_body, id_list* new_inits,
if ( new_frame_size > frame_size )
frame_size = new_frame_size;
auto num_args = FType()->Args()->NumFields();
if ( num_args > static_cast<int>(frame_size) )
frame_size = num_args;
new_body = AddInits(std::move(new_body), new_inits);
if ( Flavor() == FUNC_FLAVOR_FUNCTION )

View file

@ -431,8 +431,42 @@ void ID::DescribeReST(ODesc* d, bool roles_only) const
d->Add("`");
}
else
{
type->DescribeReST(d, roles_only);
if ( IsFunc(type->Tag()) )
{
auto ft = type->AsFuncType();
if ( ft->Flavor() == FUNC_FLAVOR_EVENT ||
ft->Flavor() == FUNC_FLAVOR_HOOK )
{
const auto& protos = ft->Prototypes();
if ( protos.size() > 1 )
{
auto first = true;
for ( const auto& proto : protos )
{
if ( first )
{
first = false;
continue;
}
d->NL();
d->Add(":Type: :zeek:type:`");
d->Add(ft->FlavorString());
d->Add("` (");
proto.args->DescribeFieldsReST(d, true);
d->Add(")");
}
}
}
}
}
d->NL();
}

View file

@ -434,6 +434,7 @@ FuncType::FuncType(IntrusivePtr<RecordType> arg_args,
flavor = arg_flavor;
bool has_default_arg = false;
std::map<int, int> offsets;
for ( int i = 0; i < args->NumFields(); ++i )
{
@ -450,7 +451,10 @@ FuncType::FuncType(IntrusivePtr<RecordType> arg_args,
}
arg_types->Append({NewRef{}, args->FieldType(i)});
offsets[i] = i;
}
prototypes.emplace_back(Prototype{false, args, std::move(offsets)});
}
FuncType* FuncType::ShallowClone()
@ -460,6 +464,7 @@ FuncType* FuncType::ShallowClone()
f->arg_types = {NewRef{}, arg_types->AsTypeList()};
f->yield = yield;
f->flavor = flavor;
f->prototypes = prototypes;
return f;
}
@ -574,6 +579,50 @@ void FuncType::DescribeReST(ODesc* d, bool roles_only) const
}
}
void FuncType::AddPrototype(Prototype p)
{
prototypes.emplace_back(std::move(p));
}
std::optional<FuncType::Prototype> FuncType::FindPrototype(const RecordType& args) const
{
for ( auto i = 0u; i < prototypes.size(); ++i )
{
const auto& p = prototypes[i];
if ( args.NumFields() != p.args->NumFields() )
continue;
if ( args.NumFields() == 0 )
{
if ( p.args->NumFields() == 0 )
return p;
continue;
}
bool matched = true;
for ( auto i = 0; i < args.NumFields(); ++i )
{
auto ptype = p.args->FieldType(i);
auto desired_type = args.FieldType(i);
if ( ! same_type(ptype, desired_type) ||
! streq(args.FieldName(i), p.args->FieldName(i)) )
{
matched = false;
break;
}
}
if ( matched )
return p;
}
return {};
}
TypeDecl::TypeDecl(IntrusivePtr<BroType> t, const char* i, attr_list* arg_attrs, bool in_record)
: type(std::move(t)),
attrs(arg_attrs ? make_intrusive<Attributes>(arg_attrs, type, in_record, false) : nullptr),

View file

@ -12,6 +12,7 @@
#include <unordered_map>
#include <map>
#include <list>
#include <optional>
// BRO types.
@ -439,6 +440,17 @@ protected:
class FuncType final : public BroType {
public:
/**
* Prototype is only currently used for events and hooks which declare
* multiple signature prototypes that allow users to have handlers
* with various argument permutations.
*/
struct Prototype {
bool deprecated;
IntrusivePtr<RecordType> args;
std::map<int, int> offsets;
};
FuncType(IntrusivePtr<RecordType> args, IntrusivePtr<BroType> yield,
function_flavor f);
FuncType* ShallowClone() override;
@ -464,12 +476,29 @@ public:
void Describe(ODesc* d) const override;
void DescribeReST(ODesc* d, bool roles_only = false) const override;
/**
* Adds a new event/hook signature allowed for use in handlers.
*/
void AddPrototype(Prototype s);
/**
* Returns a prototype signature that matches the desired argument types.
*/
std::optional<Prototype> FindPrototype(const RecordType& args) const;
/**
* Returns all allowed function prototypes.
*/
const std::vector<Prototype>& Prototypes() const
{ return prototypes; }
protected:
FuncType() : BroType(TYPE_FUNC) { flavor = FUNC_FLAVOR_FUNCTION; }
IntrusivePtr<RecordType> args;
IntrusivePtr<TypeList> arg_types;
IntrusivePtr<BroType> yield;
function_flavor flavor;
std::vector<Prototype> prototypes;
};
class TypeType final : public BroType {

View file

@ -29,13 +29,90 @@ static IntrusivePtr<Val> init_val(Expr* init, const BroType* t,
}
}
static bool add_prototype(ID* id, BroType* t, attr_list* attrs,
const IntrusivePtr<Expr>& init)
{
if ( ! IsFunc(id->Type()->Tag()) )
return false;
if ( ! IsFunc(t->Tag()) )
{
t->Error("type incompatible with previous definition", id);
return false;
}
auto canon_ft = id->Type()->AsFuncType();
auto alt_ft = t->AsFuncType();
if ( canon_ft->Flavor() != alt_ft->Flavor() )
{
alt_ft->Error("incompatible function flavor", canon_ft);
return false;
}
if ( canon_ft->Flavor() == FUNC_FLAVOR_FUNCTION )
{
alt_ft->Error("redeclaration of function", canon_ft);
return false;
}
if ( init )
{
init->Error("initialization not allowed during event/hook alternate prototype declaration");
return false;
}
auto canon_args = canon_ft->Args();
auto alt_args = alt_ft->Args();
if ( auto p = canon_ft->FindPrototype(*alt_args); p )
{
alt_ft->Error("alternate function prototype already exists", p->args.get());
return false;
}
std::map<int, int> offsets;
for ( auto i = 0; i < alt_args->NumFields(); ++i )
{
auto field = alt_args->FieldName(i);
if ( alt_args->FieldDecl(i)->attrs )
{
alt_ft->Error(fmt("alternate function prototype arguments may not have attributes: arg '%s'", field), canon_ft);
return false;
}
auto o = canon_args->FieldOffset(field);
if ( o < 0 )
{
alt_ft->Error(fmt("alternate function prototype arg '%s' not found in canonical prototype", field), canon_ft);
return false;
}
offsets[i] = o;
}
auto deprecated = false;
if ( attrs )
for ( const auto& a : *attrs )
if ( a->Tag() == ATTR_DEPRECATED )
deprecated = true;
FuncType::Prototype p{deprecated, {NewRef{}, alt_args}, std::move(offsets)};
canon_ft->AddPrototype(std::move(p));
return true;
}
static void make_var(ID* id, IntrusivePtr<BroType> t, init_class c,
IntrusivePtr<Expr> init, attr_list* attr, decl_type dt,
bool do_init)
{
if ( id->Type() )
{
if ( id->IsRedefinable() || (! init && attr) )
if ( id->IsRedefinable() || (! init && attr && ! IsFunc(id->Type()->Tag())) )
{
BroObj* redef_obj = init ? (BroObj*) init.get() : (BroObj*) t.get();
if ( dt != VAR_REDEF )
@ -44,7 +121,11 @@ static void make_var(ID* id, IntrusivePtr<BroType> t, init_class c,
else if ( dt != VAR_REDEF || init || ! attr )
{
if ( IsFunc(id->Type()->Tag()) )
add_prototype(id, t.get(), attr, init);
else
id->Error("already defined", init.get());
return;
}
}
@ -338,6 +419,41 @@ static bool has_attr(const attr_list* al, attr_tag tag)
return find_attr(al, tag) != nullptr;
}
static std::optional<FuncType::Prototype> func_type_check(const FuncType* decl, const FuncType* impl)
{
if ( decl->Flavor() != impl->Flavor() )
{
impl->Error("incompatible function flavor", decl);
return {};
}
if ( impl->Flavor() == FUNC_FLAVOR_FUNCTION )
{
if ( same_type(decl, impl) )
return decl->Prototypes()[0];
impl->Error("incompatible function types", decl);
return {};
}
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,
bool is_redef, IntrusivePtr<FuncType> t, attr_list* attrs)
{
@ -351,16 +467,57 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor,
t->ClearYieldType(flavor);
}
std::optional<FuncType::Prototype> prototype;
if ( id->Type() )
{
if ( ! same_type(id->Type(), t.get()) )
id->Type()->Error("incompatible types", t.get());
auto decl = id->Type()->AsFuncType();
prototype = func_type_check(decl, t.get());
if ( prototype )
{
if ( decl->Flavor() == FUNC_FLAVOR_FUNCTION )
{
// If a previous declaration of the function had &default
// params, automatically transfer any that are missing
// (convenience so that implementations don't need to specify
// the &default expression again).
transfer_arg_defaults(prototype->args.get(), t->Args());
}
else
// If a previous declaration of the function had &default params,
// automatically transfer any that are missing (convenience so that
// implementations don't need to specify the &default expression again).
transfer_arg_defaults(id->Type()->AsFuncType()->Args(), t->Args());
{
// Warn for trying to use &default parameters in hook/event
// handler body when it already has a declaration since only
// &default in the declaration has any effect.
auto args = t->Args();
for ( int i = 0; i < args->NumFields(); ++i )
{
auto f = args->FieldDecl(i);
if ( f->attrs && f->attrs->FindAttr(ATTR_DEFAULT) )
{
reporter->PushLocation(args->GetLocationInfo());
reporter->Warning(
"&default on parameter '%s' has no effect (not a %s declaration)",
args->FieldName(i), t->FlavorString().data());
reporter->PopLocation();
}
}
}
if ( prototype->deprecated )
t->Warn("use of deprecated prototype", id);
}
else
{
// 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 )
@ -410,6 +567,9 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor,
arg_id = install_ID(arg_i->id, module_name, false, false);
arg_id->SetType(arg_i->type);
if ( prototype )
arg_id->SetOffset(prototype->offsets[i]);
}
if ( Attr* depr_attr = find_attr(attrs, ATTR_DEPRECATED) )

View file

@ -0,0 +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 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)

View file

@ -0,0 +1,12 @@
warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-event-hook-prototypes/alternate-event-hook-prototypes.zeek, line 68 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-event-hook-prototypes/alternate-event-hook-prototypes.zeek, line 10: use of deprecated prototype (hook(c:count;) : bool and my_hook)
my_hook, infinite, 13
my_hook, 13, infinite
my_hook, infinite
my_hook, 13
my_hook
my_event, enantiodromia, 42
my_event, 42, enantiodromia
my_event, enantiodromia
my_event, 42
my_event
foo, C

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 @@
error in ./bad.zeek, line 2 and ./bad.zeek, line 1: alternate function prototype arguments may not have attributes: arg 'a' (event(c:string; b:string; a:string;) and event(a:string; b:string; c:string;))

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,8 @@
warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.ineffective-default-args/ineffective-default-args.zeek, line 9: &default on parameter 'b' has no effect (not a event declaration)
warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.ineffective-default-args/ineffective-default-args.zeek, line 19: &default on parameter 'c' has no effect (not a event declaration)
bar, A, B
baz, A, B
qux, Q, Q
grault, A, B
corge, C
foo c, C

View file

@ -0,0 +1,8 @@
error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 13 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 4: use of undeclared alternate prototype (event(c:count; s:string;) and my_event)
error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 18 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 4: use of undeclared alternate prototype (event(s:string;) and my_event)
error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 23 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 4: use of undeclared alternate prototype (event(c:count;) and my_event)
error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 28 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 4: use of undeclared alternate prototype (event() and my_event)
error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 38 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 6: use of undeclared alternate prototype (hook(c:count; s:string;) : bool and my_hook)
error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 43 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 6: use of undeclared alternate prototype (hook(s:string;) : bool and my_hook)
error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 48 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 6: use of undeclared alternate prototype (hook(c:count;) : bool and my_hook)
error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 53 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.undeclared-alternate-event-hook-prototype/undeclared-alternate-event-hook-prototype.zeek, line 6: use of undeclared alternate prototype (hook() : bool and my_hook)

View file

@ -0,0 +1,24 @@
# @TEST-EXEC-FAIL: zeek -b %INPUT >out 2>&1
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out
global my_event: event(s: string, c: count);
global my_event: event(nope: string, cantdothis: count);
global my_hook: hook(s: string, c: count);
global my_hook: hook(andnotthiseither: addr);
event my_event(s: string, c: count)
{
print "my_event", s, c;
}
hook my_hook(s: string, c: count)
{
print "my_hook", s, c;
}
event zeek_init()
{
hook my_hook("infinite", 13);
event my_event("enantiodromia", 42);
}

View file

@ -0,0 +1,83 @@
# @TEST-EXEC: zeek -b %INPUT >out 2>&1
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out
global my_event: event(s: string, c: count);
global my_event: event(c: count, s: string);
global my_event: event(s: string);
global my_event: event(c: count);
global my_event: event();
global my_hook: hook(s: string, c: count);
global my_hook: hook(c: count, s: string);
global my_hook: hook(s: string);
global my_hook: hook(c: count) &deprecated;
global my_hook: hook();
# Required Frame size gets (re)calculated on AddBody, so this "foo" setup is
# checking that if the only existing body doesn't use all arguments, the Frame
# size is still allocated sufficiently to hold all arguments of the canonical
# prototype.
global foo: event(a: string, b: string, c: string);
global foo: event(c: string);
event foo(c: string)
{
print "foo", c;
}
event my_event(s: string, c: count)
{
print "my_event", s, c;
}
event my_event(c: count, s: string)
{
print "my_event", c, s;
}
event my_event(s: string)
{
print "my_event", s;
}
event my_event(c: count)
{
print "my_event", c;
}
event my_event()
{
print "my_event";
}
hook my_hook(s: string, c: count)
{
print "my_hook", s, c;
}
hook my_hook(c: count, s: string)
{
print "my_hook", c, s;
}
hook my_hook(s: string)
{
print "my_hook", s;
}
hook my_hook(c: count)
{
print "my_hook", c;
}
hook my_hook()
{
print "my_hook";
}
event zeek_init()
{
hook my_hook("infinite", 13);
event my_event("enantiodromia", 42);
event foo("A", "B", "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");
}

View file

@ -0,0 +1,50 @@
# @TEST-EXEC: zeek -b %INPUT >out
# @TEST-EXEC-FAIL: zeek -b bad.zeek >errors 2>&1
# @TEST-EXEC: btest-diff out
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff errors
global foo: event(a: string, b: string, c: string &default="C");
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");
}
@TEST-START-FILE bad.zeek
global foo: event(a: string, b: string, c: string &default="C");
global foo: event(c: string, b: string, a: string &default="A");
@TEST-END-FILE bad.zeek

View file

@ -0,0 +1,54 @@
# @TEST-EXEC: zeek -b %INPUT >out 2>&1
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out
global grault: event(a: string, b: string &default="B");
global foo: event(a: string, b: string, c: string &default="C");
global foo: event(c: string);
event grault(a: string, b: string &default="G")
{
print "grault", a, b;
}
event corge(c: string &default="C")
{
print "corge", c;
}
event foo(c: string &default="CCCC")
{
print "foo c", c;
}
global bar: function(a: string, b: string);
function bar(a: string &default="A", b: string &default="B")
{
print "bar", a, b;
}
global baz: function(a: string &default="A", b: string &default="B");
function baz(a: string, b: string)
{
print "baz", a, b;
}
global qux: function(a: string &default="A", b: string &default="B");
function qux(a: string &default="Q", b: string &default="Q")
{
print "qux", a, b;
}
event zeek_init()
{
bar();
baz();
qux();
event grault("A");
event corge();
event foo("A", "B");
}

View file

@ -0,0 +1,62 @@
# @TEST-EXEC-FAIL: zeek -b %INPUT >out 2>&1
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out
global my_event: event(s: string, c: count);
global my_hook: hook(s: string, c: count);
event my_event(s: string, c: count)
{
print "my_event", s, c;
}
event my_event(c: count, s: string)
{
print "my_event", c, s;
}
event my_event(s: string)
{
print "my_event", s;
}
event my_event(c: count)
{
print "my_event", c;
}
event my_event()
{
print "my_event";
}
hook my_hook(s: string, c: count)
{
print "my_hook", s, c;
}
hook my_hook(c: count, s: string)
{
print "my_hook", c, s;
}
hook my_hook(s: string)
{
print "my_hook", s;
}
hook my_hook(c: count)
{
print "my_hook", c;
}
hook my_hook()
{
print "my_hook";
}
event zeek_init()
{
hook my_hook("infinite", 13);
event my_event("enantiodromia", 42);
}