From f6caa565bd01f2513f4358621fdf4ffe4fe3edad Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Thu, 25 Oct 2012 15:15:46 -0500 Subject: [PATCH 01/23] Add a new BIF "bytestring_to_double" Addresses #908. --- src/bro.bif | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/bro.bif b/src/bro.bif index 1b1c23950d..76fe5f6fa7 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -2701,6 +2701,25 @@ function to_port%(s: string%): port return new PortVal(port, TRANSPORT_UNKNOWN); %} +## Converts a string of bytes (in network byte order) to a :bro:type:`double`. +## +## s: The string of bytes representing a double value. +## +## Returns: The double value contained in *s*, or 0 if the conversion +## failed. +## +function bytestring_to_double%(s: string%): double + %{ + if ( s->Len() != sizeof(double) ) + { + builtin_error("bad conversion to double"); + return new Val(0.0, TYPE_DOUBLE); + } + + double d = ntohd( *(double *)s->Bytes() ); + return new Val(d, TYPE_DOUBLE); + %} + ## Converts a reverse pointer name to an address. For example, ## ``1.0.168.192.in-addr.arpa`` to ``192.168.0.1``. ## From 48c448737833c01eb0289ff477322a274b804bb1 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Thu, 25 Oct 2012 17:10:51 -0500 Subject: [PATCH 02/23] Add test cases for the bytestring_to_double BIF --- .../Baseline/bifs.bytestring_to_double/out | 9 +++++++ testing/btest/bifs/bytestring_to_double.bro | 26 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 testing/btest/Baseline/bifs.bytestring_to_double/out create mode 100644 testing/btest/bifs/bytestring_to_double.bro diff --git a/testing/btest/Baseline/bifs.bytestring_to_double/out b/testing/btest/Baseline/bifs.bytestring_to_double/out new file mode 100644 index 0000000000..5927de2b7e --- /dev/null +++ b/testing/btest/Baseline/bifs.bytestring_to_double/out @@ -0,0 +1,9 @@ +3.140000e+15 +-3.140000e+15 +4.000000e-308 +0.000000e+00 +-0.000000e+00 +inf +-inf +nan +4.94e-324 diff --git a/testing/btest/bifs/bytestring_to_double.bro b/testing/btest/bifs/bytestring_to_double.bro new file mode 100644 index 0000000000..cc0a3a69f0 --- /dev/null +++ b/testing/btest/bifs/bytestring_to_double.bro @@ -0,0 +1,26 @@ +# +# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: btest-diff out + +event bro_init() + { + local s1 = "\x43\x26\x4f\xa0\x71\x30\x80\x00"; # 3.14e15 + local s2 = "\xc3\x26\x4f\xa0\x71\x30\x80\x00"; #-3.14e15 + local s3 = "\x00\x1c\xc3\x59\xe0\x67\xa3\x49"; # 4e-308 + local s4 = "\x00\x00\x00\x00\x00\x00\x00\x00"; # 0.0 + local s5 = "\x80\x00\x00\x00\x00\x00\x00\x00"; #-0.0 + local s6 = "\x7f\xf0\x00\x00\x00\x00\x00\x00"; # Inf + local s7 = "\xff\xf0\x00\x00\x00\x00\x00\x00"; #-Inf + local s8 = "\x7f\xf8\x00\x00\x00\x00\x00\x00"; # NaN + local s9 = "\x00\x00\x00\x00\x00\x00\x00\x01"; # subnormal + + print bytestring_to_double(s1); + print bytestring_to_double(s2); + print fmt("%e", bytestring_to_double(s3)); + print fmt("%e", bytestring_to_double(s4)); + print fmt("%e", bytestring_to_double(s5)); + print bytestring_to_double(s6); + print bytestring_to_double(s7); + print bytestring_to_double(s8); + print fmt("%.2e", bytestring_to_double(s9)); + } From 10376b13f597bd29ead952e35c2499d7e52f3ad9 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Tue, 13 Nov 2012 15:48:25 -0600 Subject: [PATCH 03/23] Portability improvement (data alignment issues) --- src/bro.bif | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bro.bif b/src/bro.bif index 76fe5f6fa7..8dad05b24d 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -2716,8 +2716,9 @@ function bytestring_to_double%(s: string%): double return new Val(0.0, TYPE_DOUBLE); } - double d = ntohd( *(double *)s->Bytes() ); - return new Val(d, TYPE_DOUBLE); + double d; + memcpy(&d, s->Bytes(), sizeof(double)); + return new Val(ntohd(d), TYPE_DOUBLE); %} ## Converts a reverse pointer name to an address. For example, From e0fb9eb2b2a0f731244b0f104123e0c96821fb3a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 15 Nov 2012 13:45:13 -0600 Subject: [PATCH 04/23] Add new function flavor called a "hook". This new flavor of function behaves like a "synchronous event". See documentation for more details on usage. --- doc/scripts/builtins.rst | 72 +++++++++++++++++-- src/Attr.cc | 8 ++- src/BroDoc.cc | 1 + src/BroDoc.h | 26 +++++++ src/Expr.cc | 27 ++++++- src/Expr.h | 2 +- src/Func.cc | 14 ++-- src/Func.h | 2 +- src/ID.cc | 5 +- src/SerialTypes.h | 1 + src/Serializer.cc | 15 ++-- src/Serializer.h | 2 +- src/Stmt.cc | 49 ++++++++++++- src/Stmt.h | 18 +++++ src/StmtEnums.h | 2 +- src/Type.cc | 70 +++++++++++++++--- src/Type.h | 22 +++--- src/Var.cc | 35 +++++---- src/input/Manager.cc | 4 +- src/logging/Manager.cc | 2 +- src/parse.y | 62 +++++++++++++--- src/scan.l | 1 + .../doc.autogen-reST-example/example.rst | 6 +- .../autogen-reST-func-params.rst | 6 +- testing/btest/Baseline/language.hook/out | 7 ++ .../btest/Baseline/language.invalid_hook/out | 1 + testing/btest/istate/events-ssl.bro | 4 +- testing/btest/istate/events.bro | 4 +- testing/btest/language/hook.bro | 71 ++++++++++++++++++ testing/btest/language/invalid_hook.bro | 16 +++++ 30 files changed, 476 insertions(+), 79 deletions(-) create mode 100644 testing/btest/Baseline/language.hook/out create mode 100644 testing/btest/Baseline/language.invalid_hook/out create mode 100644 testing/btest/language/hook.bro create mode 100644 testing/btest/language/invalid_hook.bro diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index d274de6b7b..ba786ba0d2 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -417,10 +417,6 @@ The Bro scripting language supports the following built-in types. Writing to files like this for logging usually isn't recommended, for better logging support see :doc:`/logging`. -.. bro:type:: func - - See :bro:type:`function`. - .. bro:type:: function Function types in Bro are declared using:: @@ -504,6 +500,74 @@ The Bro scripting language supports the following built-in types. identifier and the body of each will be executed in turn. Ordering of execution can be influenced with :bro:attr:`&priority`. +.. bro:type:: hook + + A hook is another flavor of function that shares characteristics of + both a :bro:type:`function` and a :bro:type:`event`. They are like + events in that many handler bodies can be defined for the same hook + identifier, they have no return vale, and the order of execution + can be enforced with :bro:attr:`&priority`. They are more like + functions in the way they are invoked/called, because, unlike + events, their execution is immediate and they do not get scheduled + through an event queue. Also, a unique feature of a hook is that + a given hook handler body can short-circuit the execution of + remaining hook handlers simply by exiting from the body as a result + of a ``break`` statement (as opposed to a ``return`` or just + reaching the end of the body). + + A hook type is declared like:: + + hook( argument* ) + + where *argument* is a (possibly empty) comma-separated list of + arguments. For example: + + .. code:: bro + + global myhook: hook(s: string) + + Here ``myhook`` is the hook type identifier and no hook handler + bodies have been defined for it yet. To define some hook handler + bodies the syntax looks like: + + .. code:: bro + + hook myhook(s: string) &priority=10 + { + print "priority 10 myhook handler", s; + s = "bye"; + } + + hook myhook(s: string) + { + print "break out of myhook handling", s; + break; + } + + hook myhook(s: string) &priority=-5 + { + print "not going to happen", s; + } + + Note that, although the first (forward) declaration of ``myhook`` as + a hook type isn't strictly required, when it is provided, the + argument types must match. + + To invoke immediate execution of all hook handler bodies, a ``hook`` + statement must be used: + + .. code:: bro + + hook myhook("hi"); + + And the output would like like:: + + priority 10 myhook handler, hi + break out of myhook handling, bye + + Note how the modification to arguments can be seen by remaining + hook handlers. + Attributes ---------- diff --git a/src/Attr.cc b/src/Attr.cc index bdf247b4f5..6e0769c7b0 100644 --- a/src/Attr.cc +++ b/src/Attr.cc @@ -71,7 +71,9 @@ void Attr::DescribeReST(ODesc* d) const else if ( expr->Type()->Tag() == TYPE_FUNC ) { - d->Add(":bro:type:`func`"); + d->Add(":bro:type:`"); + d->Add(expr->Type()->AsFuncType()->FlavorString()); + d->Add("`"); } else @@ -401,13 +403,13 @@ void Attributes::CheckAttr(Attr* a) case ATTR_GROUP: if ( type->Tag() != TYPE_FUNC || - ! type->AsFuncType()->IsEvent() ) + type->AsFuncType()->Flavor() != FUNC_FLAVOR_EVENT ) Error("&group only applicable to events"); break; case ATTR_ERROR_HANDLER: if ( type->Tag() != TYPE_FUNC || - ! type->AsFuncType()->IsEvent() ) + type->AsFuncType()->Flavor() != FUNC_FLAVOR_EVENT ) Error("&error_handler only applicable to events"); break; diff --git a/src/BroDoc.cc b/src/BroDoc.cc index 1e2d7d52ea..23b1f56aaa 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -271,6 +271,7 @@ void BroDoc::WriteInterface(const char* heading, char underline, WriteBroDocObjList(state_vars, isPublic, "State Variables", sub, isShort); WriteBroDocObjList(types, isPublic, "Types", sub, isShort); WriteBroDocObjList(events, isPublic, "Events", sub, isShort); + WriteBroDocObjList(hooks, isPublic, "Hooks", sub, isShort); WriteBroDocObjList(functions, isPublic, "Functions", sub, isShort); WriteBroDocObjList(redefs, isPublic, "Redefinitions", sub, isShort); } diff --git a/src/BroDoc.h b/src/BroDoc.h index ac6ff0a59b..79f02b7110 100644 --- a/src/BroDoc.h +++ b/src/BroDoc.h @@ -179,6 +179,30 @@ public: all.push_back(o); } + /** + * Schedules documentation of a hook declared by the script. + * @param o A pointer to a BroDocObj which contains the internal + * Bro language representation of the script hook and + * also any associated comments about it. + */ + void AddHook(const BroDocObj* o) + { + hooks.push_back(o); + all.push_back(o); + } + + /** + * Schedules documentation of a hook handler declared by the script. + * @param o A pointer to a BroDocObj which contains the internal + * Bro language representation of the script hook handler and + * also any associated comments about it. + */ + void AddHookHandler(const BroDocObj* o) + { + hook_handlers.push_back(o); + all.push_back(o); + } + /** * Schedules documentation of a function declared by the script. * @param o A pointer to a BroDocObj which contains the internal @@ -241,6 +265,8 @@ protected: BroDocObjList notices; BroDocObjList events; BroDocObjList event_handlers; + BroDocObjList hooks; + BroDocObjList hook_handlers; BroDocObjMap functions; BroDocObjList redefs; diff --git a/src/Expr.cc b/src/Expr.cc index e6936267d8..0ef9e2ad94 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -4374,7 +4374,7 @@ bool InExpr::DoUnserialize(UnserialInfo* info) return true; } -CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args) +CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) : Expr(EXPR_CALL) { func = arg_func; @@ -4402,8 +4402,29 @@ CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args) if ( ! yield ) { - Error("event called in expression"); - SetError(); + switch ( func_type->AsFuncType()->Flavor() ) { + case FUNC_FLAVOR_FUNCTION: + Error("function has no yield type"); + SetError(); + break; + case FUNC_FLAVOR_EVENT: + Error("event called in expression, use event statement instead"); + SetError(); + break; + case FUNC_FLAVOR_HOOK: + // It's fine to not have a yield if it's known that the call + // is being done from a hook statement. + if ( ! in_hook ) + { + Error("hook called in expression, use hook statement instead"); + SetError(); + } + break; + default: + Error("invalid function flavor"); + SetError(); + break; + } } else SetType(yield->Ref()); diff --git a/src/Expr.h b/src/Expr.h index c16cf86612..bd4824f8ee 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -959,7 +959,7 @@ protected: class CallExpr : public Expr { public: - CallExpr(Expr* func, ListExpr* args); + CallExpr(Expr* func, ListExpr* args, bool in_hook = false); ~CallExpr(); Expr* Func() const { return func; } diff --git a/src/Func.cc b/src/Func.cc index 582de1d9bb..27acce4f04 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -284,8 +284,8 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const #endif if ( ! bodies.size() ) { - // Can only happen for events. - assert(IsEvent()); + // Can only happen for events and hooks. + assert(Flavor() == FUNC_FLAVOR_EVENT || Flavor() == FUNC_FLAVOR_HOOK); loop_over_list(*args, i) Unref((*args)[i]); return 0 ; @@ -309,7 +309,7 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const DescribeDebug(&d, args); g_trace_state.LogTrace("%s called: %s\n", - IsEvent() ? "event" : "function", d.Description()); + FType()->FlavorString().c_str(), d.Description()); } loop_over_list(*args, i) @@ -348,6 +348,12 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const parent->SetDelayed(); break; } + + if ( flow == FLOW_BREAK && Flavor() == FUNC_FLAVOR_HOOK ) + { + // short-circuit execution of remaining hook handler bodies + break; + } } // Warn if the function returns something, but we returned from @@ -380,7 +386,7 @@ void BroFunc::AddBody(Stmt* new_body, id_list* new_inits, int new_frame_size, new_body = AddInits(new_body, new_inits); - if ( ! IsEvent() ) + if ( Flavor() == FUNC_FLAVOR_FUNCTION ) { // For functions, we replace the old body with the new one. assert(bodies.size() <= 1); diff --git a/src/Func.h b/src/Func.h index 909b2a9802..a2dbb2ddc2 100644 --- a/src/Func.h +++ b/src/Func.h @@ -25,7 +25,7 @@ public: virtual ~Func(); virtual int IsPure() const = 0; - int IsEvent() const { return FType()->IsEvent(); } + function_flavor Flavor() const { return FType()->Flavor(); } struct Body { Stmt* stmts; diff --git a/src/ID.cc b/src/ID.cc index a70aa3fd0e..5239c3bb35 100644 --- a/src/ID.cc +++ b/src/ID.cc @@ -107,7 +107,8 @@ void ID::SetVal(Val* v, Opcode op, bool arg_weak_ref) #endif if ( type && val && - type->Tag() == TYPE_FUNC && type->AsFuncType()->IsEvent() ) + type->Tag() == TYPE_FUNC && + type->AsFuncType()->Flavor() == FUNC_FLAVOR_EVENT ) { EventHandler* handler = event_registry->Lookup(name); if ( ! handler ) @@ -657,7 +658,7 @@ void ID::DescribeReSTShort(ODesc* d) const break; case TYPE_FUNC: - d->Add(type->AsFuncType()->IsEvent() ? "event" : type_name(t)); + d->Add(type->AsFuncType()->FlavorString()); break; default: diff --git a/src/SerialTypes.h b/src/SerialTypes.h index c47ff19298..a18c9bcc65 100644 --- a/src/SerialTypes.h +++ b/src/SerialTypes.h @@ -165,6 +165,7 @@ SERIAL_STMT(EVENT_BODY_LIST, 16) SERIAL_STMT(INIT_STMT, 17) SERIAL_STMT(NULL_STMT, 18) SERIAL_STMT(WHEN_STMT, 19) +SERIAL_STMT(HOOK_STMT, 20) #define SERIAL_TYPE(name, val) SERIAL_CONST(name, val, BRO_TYPE) SERIAL_TYPE(BRO_TYPE, 1) diff --git a/src/Serializer.cc b/src/Serializer.cc index fc6d00d06c..8a43874342 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -389,23 +389,30 @@ bool Serializer::UnserializeCall(UnserialInfo* info) { if ( info->print ) fprintf(info->print, "%s [%.06f] %s(%s)\n", - functype->IsEvent() ? "Event" : "Function call", + functype->FlavorString().c_str(), time, name, types ? d.Description() : ""); - if ( functype->IsEvent() ) + switch ( functype->Flavor() ) { + case FUNC_FLAVOR_EVENT: { EventHandler* handler = event_registry->Lookup(name); assert(handler); if ( ! info->ignore_callbacks ) GotEvent(name, time, handler, args); } - else + break; + case FUNC_FLAVOR_FUNCTION: + case FUNC_FLAVOR_HOOK: if ( ! info->ignore_callbacks ) GotFunctionCall(name, time, id->ID_Val()->AsFunc(), args); + break; + default: + reporter->InternalError("invalid function flavor"); + break; + } if ( info->ignore_callbacks ) delete_vals(args); - } else delete_vals(args); diff --git a/src/Serializer.h b/src/Serializer.h index e7396cb7f8..72e0723880 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -125,7 +125,7 @@ protected: // This will be increased whenever there is an incompatible change // in the data format. - static const uint32 DATA_FORMAT_VERSION = 22; + static const uint32 DATA_FORMAT_VERSION = 23; ChunkedIO* io; diff --git a/src/Stmt.cc b/src/Stmt.cc index 7d754d8e72..0a5ae16ef6 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -23,7 +23,7 @@ const char* stmt_name(BroStmtTag t) "print", "event", "expr", "if", "when", "switch", "for", "next", "break", "return", "add", "delete", "list", "bodylist", - "", + "", "hook", "null", }; @@ -933,6 +933,52 @@ bool EventStmt::DoUnserialize(UnserialInfo* info) return event_expr != 0; } +HookStmt::HookStmt(CallExpr* arg_e) : ExprStmt(STMT_HOOK, arg_e) + { + call_expr = arg_e; + } + +Val* HookStmt::Exec(Frame* f, stmt_flow_type& flow) const + { + RegisterAccess(); + + Val* ret = call_expr->Eval(f); + Unref(ret); + + flow = FLOW_NEXT; + + return 0; + } + +TraversalCode HookStmt::Traverse(TraversalCallback* cb) const + { + TraversalCode tc = cb->PreStmt(this); + HANDLE_TC_STMT_PRE(tc); + + // call expr is stored in base class's "e" field. + tc = e->Traverse(cb); + HANDLE_TC_STMT_PRE(tc); + + tc = cb->PostStmt(this); + HANDLE_TC_STMT_POST(tc); + } + +IMPLEMENT_SERIAL(HookStmt, SER_HOOK_STMT); + +bool HookStmt::DoSerialize(SerialInfo* info) const + { + DO_SERIALIZE(SER_HOOK_STMT, ExprStmt); + return call_expr->Serialize(info); + } + +bool HookStmt::DoUnserialize(UnserialInfo* info) + { + DO_UNSERIALIZE(ExprStmt); + + call_expr = (CallExpr*) Expr::Unserialize(info, EXPR_CALL); + return call_expr != 0; + } + ForStmt::ForStmt(id_list* arg_loop_vars, Expr* loop_expr) : ExprStmt(STMT_FOR, loop_expr) { @@ -1944,6 +1990,7 @@ int same_stmt(const Stmt* s1, const Stmt* s2) case STMT_RETURN: case STMT_EXPR: case STMT_EVENT: + case STMT_HOOK: { const ExprStmt* e1 = (const ExprStmt*) s1; const ExprStmt* e2 = (const ExprStmt*) s2; diff --git a/src/Stmt.h b/src/Stmt.h index 7c3b42609b..68bb8d6425 100644 --- a/src/Stmt.h +++ b/src/Stmt.h @@ -286,6 +286,24 @@ protected: EventExpr* event_expr; }; +class HookStmt : public ExprStmt { +public: + HookStmt(CallExpr* e); + + Val* Exec(Frame* f, stmt_flow_type& flow) const; + + TraversalCode Traverse(TraversalCallback* cb) const; + +protected: + friend class Stmt; + + HookStmt() { call_expr = 0; } + + DECLARE_SERIAL(HookStmt); + + CallExpr* call_expr; +}; + class ForStmt : public ExprStmt { public: ForStmt(id_list* loop_vars, Expr* loop_expr); diff --git a/src/StmtEnums.h b/src/StmtEnums.h index f431e3fea1..fa5b70389d 100644 --- a/src/StmtEnums.h +++ b/src/StmtEnums.h @@ -15,7 +15,7 @@ typedef enum { STMT_RETURN, STMT_ADD, STMT_DELETE, STMT_LIST, STMT_EVENT_BODY_LIST, - STMT_INIT, + STMT_INIT, STMT_HOOK, STMT_NULL #define NUM_STMTS (int(STMT_NULL) + 1) } BroStmtTag; diff --git a/src/Type.cc b/src/Type.cc index 414c07d3d7..df2b7b0a3d 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -651,12 +651,12 @@ bool SetType::DoUnserialize(UnserialInfo* info) return true; } -FuncType::FuncType(RecordType* arg_args, BroType* arg_yield, int arg_is_event) +FuncType::FuncType(RecordType* arg_args, BroType* arg_yield, function_flavor arg_flavor) : BroType(TYPE_FUNC) { args = arg_args; yield = arg_yield; - is_event = arg_is_event; + flavor = arg_flavor; arg_types = new TypeList(); @@ -664,6 +664,21 @@ FuncType::FuncType(RecordType* arg_args, BroType* arg_yield, int arg_is_event) arg_types->Append(args->FieldType(i)->Ref()); } +string FuncType::FlavorString() const + { + switch ( flavor ) { + case FUNC_FLAVOR_FUNCTION: + return "function"; + case FUNC_FLAVOR_EVENT: + return "event"; + case FUNC_FLAVOR_HOOK: + return "hook"; + default: + reporter->InternalError("Invalid function flavor"); + return "invalid_func_flavor"; + } + } + FuncType::~FuncType() { Unref(arg_types); @@ -698,7 +713,7 @@ void FuncType::Describe(ODesc* d) const { if ( d->IsReadable() ) { - d->Add(is_event ? "event" : "function"); + d->Add(FlavorString()); d->Add("("); args->DescribeFields(d); d->Add(")"); @@ -712,7 +727,7 @@ void FuncType::Describe(ODesc* d) const else { d->Add(int(Tag())); - d->Add(is_event); + d->Add(flavor); d->Add(yield != 0); args->DescribeFields(d); if ( yield ) @@ -723,7 +738,7 @@ void FuncType::Describe(ODesc* d) const void FuncType::DescribeReST(ODesc* d) const { d->Add(":bro:type:`"); - d->Add(is_event ? "event" : "function"); + d->Add(FlavorString()); d->Add("`"); d->Add(" ("); args->DescribeFieldsReST(d, true); @@ -755,9 +770,26 @@ bool FuncType::DoSerialize(SerialInfo* info) const SERIALIZE_OPTIONAL(yield); + int ser_flavor = 0; + + switch ( flavor ) { + case FUNC_FLAVOR_FUNCTION: + ser_flavor = 0; + break; + case FUNC_FLAVOR_EVENT: + ser_flavor = 1; + break; + case FUNC_FLAVOR_HOOK: + ser_flavor = 2; + break; + default: + reporter->InternalError("Invalid function flavor serialization"); + break; + } + return args->Serialize(info) && arg_types->Serialize(info) && - SERIALIZE(is_event); + SERIALIZE(ser_flavor); } bool FuncType::DoUnserialize(UnserialInfo* info) @@ -774,7 +806,27 @@ bool FuncType::DoUnserialize(UnserialInfo* info) if ( ! arg_types ) return false; - return UNSERIALIZE(&is_event); + int ser_flavor = 0; + + if ( ! UNSERIALIZE(&ser_flavor) ) + return false; + + switch ( ser_flavor ) { + case 0: + flavor = FUNC_FLAVOR_FUNCTION; + break; + case 1: + flavor = FUNC_FLAVOR_EVENT; + break; + case 2: + flavor = FUNC_FLAVOR_HOOK; + break; + default: + reporter->InternalError("Invalid function flavor unserialization"); + break; + } + + return true; } TypeDecl::TypeDecl(BroType* t, const char* i, attr_list* arg_attrs, bool in_record) @@ -1595,7 +1647,7 @@ int same_type(const BroType* t1, const BroType* t2, int is_init) const FuncType* ft1 = (const FuncType*) t1; const FuncType* ft2 = (const FuncType*) t2; - if ( ft1->IsEvent() != ft2->IsEvent() ) + if ( ft1->Flavor() != ft2->Flavor() ) return 0; if ( t1->YieldType() || t2->YieldType() ) @@ -1882,7 +1934,7 @@ BroType* merge_types(const BroType* t1, const BroType* t2) BroType* yield = t1->YieldType() ? merge_types(t1->YieldType(), t2->YieldType()) : 0; - return new FuncType(args->AsRecordType(), yield, ft1->IsEvent()); + return new FuncType(args->AsRecordType(), yield, ft1->Flavor()); } case TYPE_RECORD: diff --git a/src/Type.h b/src/Type.h index efe15e6188..53250183a1 100644 --- a/src/Type.h +++ b/src/Type.h @@ -35,7 +35,11 @@ typedef enum { #define NUM_TYPES (int(TYPE_ERROR) + 1) } TypeTag; -typedef enum { FUNC_FLAVOR_FUNCTION, FUNC_FLAVOR_EVENT } function_flavor; +typedef enum { + FUNC_FLAVOR_FUNCTION, + FUNC_FLAVOR_EVENT, + FUNC_FLAVOR_HOOK +} function_flavor; typedef enum { TYPE_INTERNAL_VOID, @@ -350,18 +354,19 @@ protected: class FuncType : public BroType { public: - FuncType(RecordType* args, BroType* yield, int is_event); + FuncType(RecordType* args, BroType* yield, function_flavor f); ~FuncType(); RecordType* Args() const { return args; } BroType* YieldType(); void SetYieldType(BroType* arg_yield) { yield = arg_yield; } - int IsEvent() const { return is_event; } + function_flavor Flavor() const { return flavor; } + string FlavorString() const; - // Used to convert a function type to an event type. - void ClearYieldType() - { Unref(yield); yield = 0; is_event = 1; } + // Used to convert a function type to an event or hook type. + void ClearYieldType(function_flavor arg_flav) + { Unref(yield); yield = 0; flavor = arg_flav; } int MatchesIndex(ListExpr*& index) const; int CheckArgs(const type_list* args) const; @@ -374,14 +379,13 @@ public: void DescribeReST(ODesc* d) const; protected: - FuncType() { args = 0; arg_types = 0; yield = 0; return_value = 0; } + FuncType() { args = 0; arg_types = 0; yield = 0; flavor = FUNC_FLAVOR_FUNCTION; } DECLARE_SERIAL(FuncType) RecordType* args; TypeList* arg_types; BroType* yield; - int is_event; - ID* return_value; + function_flavor flavor; }; class TypeType : public BroType { diff --git a/src/Var.cc b/src/Var.cc index d54d94a078..7dd5d14820 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -171,7 +171,9 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, id->UpdateValAttrs(); - if ( t && t->Tag() == TYPE_FUNC && t->AsFuncType()->IsEvent() ) + if ( t && t->Tag() == TYPE_FUNC && + ( t->AsFuncType()->Flavor() == FUNC_FLAVOR_EVENT || + t->AsFuncType()->Flavor() == FUNC_FLAVOR_HOOK ) ) { // For events, add a function value (without any body) here so that // we can later access the ID even if no implementations have been @@ -258,7 +260,7 @@ void add_type(ID* id, BroType* t, attr_list* attr, int /* is_event */) case TYPE_FUNC: tnew = new FuncType(t->AsFuncType()->Args(), t->AsFuncType()->YieldType(), - t->AsFuncType()->IsEvent()); + t->AsFuncType()->Flavor()); break; default: SerializationFormat* form = new BinarySerializationFormat(); @@ -292,14 +294,14 @@ void add_type(ID* id, BroType* t, attr_list* attr, int /* is_event */) void begin_func(ID* id, const char* module_name, function_flavor flavor, int is_redef, FuncType* t) { - if ( flavor == FUNC_FLAVOR_EVENT ) + if ( flavor == FUNC_FLAVOR_EVENT || flavor == FUNC_FLAVOR_HOOK ) { const BroType* yt = t->YieldType(); if ( yt && yt->Tag() != TYPE_VOID ) - id->Error("event cannot yield a value", t); + id->Error("event/hook cannot yield a value", t); - t->ClearYieldType(); + t->ClearYieldType(flavor); } if ( id->Type() ) @@ -313,21 +315,26 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor, if ( id->HasVal() ) { - int id_is_event = id->ID_Val()->AsFunc()->IsEvent(); + function_flavor id_flavor = id->ID_Val()->AsFunc()->Flavor(); - if ( id_is_event != (flavor == FUNC_FLAVOR_EVENT) ) - id->Error("inconsistency between event and function", t); - if ( id_is_event ) - { + if ( id_flavor != flavor ) + id->Error("inconsistent function flavor", t); + + switch ( id_flavor ) { + case FUNC_FLAVOR_EVENT: + case FUNC_FLAVOR_HOOK: if ( is_redef ) // Clear out value so it will be replaced. id->SetVal(0); - } - else - { + break; + case FUNC_FLAVOR_FUNCTION: if ( ! id->IsRedefinable() ) id->Error("already defined"); - } + break; + default: + reporter->InternalError("invalid function flavor"); + break; + } } else id->SetType(t); diff --git a/src/input/Manager.cc b/src/input/Manager.cc index 43ac63200f..33f612cddd 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -393,7 +393,7 @@ bool Manager::CreateEventStream(RecordVal* fval) bool allow_file_func = false; - if ( ! etype->IsEvent() ) + if ( etype->Flavor() != FUNC_FLAVOR_EVENT ) { reporter->Error("stream event is a function, not an event"); return false; @@ -566,7 +566,7 @@ bool Manager::CreateTableStream(RecordVal* fval) { FuncType* etype = event->FType()->AsFuncType(); - if ( ! etype->IsEvent() ) + if ( etype->Flavor() != FUNC_FLAVOR_EVENT ) { reporter->Error("stream event is a function, not an event"); return false; diff --git a/src/logging/Manager.cc b/src/logging/Manager.cc index 4c6d2e92fd..f62cd1685d 100644 --- a/src/logging/Manager.cc +++ b/src/logging/Manager.cc @@ -327,7 +327,7 @@ bool Manager::CreateStream(EnumVal* id, RecordVal* sval) // Make sure the event is prototyped as expected. FuncType* etype = event->FType()->AsFuncType(); - if ( ! etype->IsEvent() ) + if ( etype->Flavor() != FUNC_FLAVOR_EVENT ) { reporter->Error("stream event is a function, not an event"); return false; diff --git a/src/parse.y b/src/parse.y index c1f6ddd96e..e1ce5f3d57 100644 --- a/src/parse.y +++ b/src/parse.y @@ -2,14 +2,14 @@ // See the file "COPYING" in the main distribution directory for copyright. %} -%expect 87 +%expect 88 %token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY %token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF %token TOK_BOOL TOK_BREAK TOK_CASE TOK_CONST %token TOK_CONSTANT TOK_COPY TOK_COUNT TOK_COUNTER TOK_DEFAULT TOK_DELETE %token TOK_DOUBLE TOK_ELSE TOK_ENUM TOK_EVENT TOK_EXPORT TOK_FILE TOK_FOR -%token TOK_FUNCTION TOK_GLOBAL TOK_ID TOK_IF TOK_INT +%token TOK_FUNCTION TOK_GLOBAL TOK_HOOK TOK_ID TOK_IF TOK_INT %token TOK_INTERVAL TOK_LIST TOK_LOCAL TOK_MODULE %token TOK_NEXT TOK_OF TOK_PATTERN TOK_PATTERN_TEXT %token TOK_PORT TOK_PRINT TOK_RECORD TOK_REDEF @@ -56,6 +56,7 @@ %type pattern %type expr init anonymous_function %type event +%type hook %type stmt stmt_list func_body for_head %type type opt_type enum_body %type func_hdr func_params @@ -118,6 +119,7 @@ extern const char* g_curr_debug_error; #define YYLTYPE yyltype +static bool in_hook = false; int in_init = 0; int in_record = 0; bool resolving_global_ID = false; @@ -859,7 +861,13 @@ type: | TOK_EVENT '(' formal_args ')' { set_location(@1, @3); - $$ = new FuncType($3, 0, 1); + $$ = new FuncType($3, 0, FUNC_FLAVOR_EVENT); + } + + | TOK_HOOK '(' formal_args ')' + { + set_location(@1, @3); + $$ = new FuncType($3, 0, FUNC_FLAVOR_HOOK); } | TOK_FILE TOK_OF type @@ -991,12 +999,23 @@ decl: ID* id = $2; if ( id->Type()->Tag() == TYPE_FUNC ) { - if ( id->Type()->AsFuncType()->IsEvent() ) - current_reST_doc->AddEvent( - new BroDocObj(id, reST_doc_comments)); - else + switch ( id->Type()->AsFuncType()->Flavor() ) { + case FUNC_FLAVOR_FUNCTION: current_reST_doc->AddFunction( new BroDocObj(id, reST_doc_comments)); + break; + case FUNC_FLAVOR_EVENT: + current_reST_doc->AddEvent( + new BroDocObj(id, reST_doc_comments)); + break; + case FUNC_FLAVOR_HOOK: + current_reST_doc->AddHook( + new BroDocObj(id, reST_doc_comments)); + break; + default: + reporter->InternalError("invalid function flavor"); + break; + } } else @@ -1175,6 +1194,15 @@ func_hdr: current_reST_doc->AddEventHandler( new BroDocObj($2, reST_doc_comments)); } + | TOK_HOOK def_global_id func_params + { + begin_func($2, current_module.c_str(), + FUNC_FLAVOR_HOOK, 0, $3); + $$ = $3; + if ( generate_documentation ) + current_reST_doc->AddHookHandler( + new BroDocObj($2, reST_doc_comments)); + } | TOK_REDEF TOK_EVENT event_id func_params { begin_func($3, current_module.c_str(), @@ -1209,9 +1237,9 @@ begin_func: func_params: '(' formal_args ')' ':' type - { $$ = new FuncType($2, $5, 0); } + { $$ = new FuncType($2, $5, FUNC_FLAVOR_FUNCTION); } | '(' formal_args ')' - { $$ = new FuncType($2, base_type(TYPE_VOID), 0); } + { $$ = new FuncType($2, base_type(TYPE_VOID), FUNC_FLAVOR_FUNCTION); } ; opt_type: @@ -1331,6 +1359,14 @@ stmt: brofiler.AddStmt($$); } + | TOK_HOOK { in_hook = true; } hook { in_hook = false; } ';' opt_no_test + { + set_location(@1, @5); + $$ = new HookStmt($3); + if ( ! $6 ) + brofiler.AddStmt($$); + } + | TOK_IF '(' expr ')' stmt { set_location(@1, @4); @@ -1484,6 +1520,14 @@ event: } ; +hook: + expr '(' opt_expr_list ')' + { + set_location(@1, @4); + $$ = new CallExpr($1, $3, in_hook); + } + ; + case_list: case_list case { $1->append($2); } diff --git a/src/scan.l b/src/scan.l index 8ff33e7d24..4e1a66144e 100644 --- a/src/scan.l +++ b/src/scan.l @@ -287,6 +287,7 @@ for return TOK_FOR; function return TOK_FUNCTION; global return TOK_GLOBAL; "?$" return TOK_HAS_FIELD; +hook return TOK_HOOK; if return TOK_IF; in return TOK_IN; "!"{OWS}in/[^A-Za-z0-9] return TOK_NOT_IN; /* don't confuse w "! infoo"! */ diff --git a/testing/btest/Baseline/doc.autogen-reST-example/example.rst b/testing/btest/Baseline/doc.autogen-reST-example/example.rst index bee8658e14..1f60efe70b 100644 --- a/testing/btest/Baseline/doc.autogen-reST-example/example.rst +++ b/testing/btest/Baseline/doc.autogen-reST-example/example.rst @@ -73,9 +73,9 @@ Events Functions ######### -=============================================== ======================================= -:bro:id:`Example::a_function`: :bro:type:`func` Summarize purpose of "a_function" here. -=============================================== ======================================= +=================================================== ======================================= +:bro:id:`Example::a_function`: :bro:type:`function` Summarize purpose of "a_function" here. +=================================================== ======================================= Redefinitions ############# diff --git a/testing/btest/Baseline/doc.autogen-reST-func-params/autogen-reST-func-params.rst b/testing/btest/Baseline/doc.autogen-reST-func-params/autogen-reST-func-params.rst index 15526f12c7..9739d024e3 100644 --- a/testing/btest/Baseline/doc.autogen-reST-func-params/autogen-reST-func-params.rst +++ b/testing/btest/Baseline/doc.autogen-reST-func-params/autogen-reST-func-params.rst @@ -20,9 +20,9 @@ Types Functions ######### -===================================== ====================================== -:bro:id:`test_func`: :bro:type:`func` This is a global function declaration. -===================================== ====================================== +========================================= ====================================== +:bro:id:`test_func`: :bro:type:`function` This is a global function declaration. +========================================= ====================================== Detailed Interface ~~~~~~~~~~~~~~~~~~ diff --git a/testing/btest/Baseline/language.hook/out b/testing/btest/Baseline/language.hook/out new file mode 100644 index 0000000000..10688acc3b --- /dev/null +++ b/testing/btest/Baseline/language.hook/out @@ -0,0 +1,7 @@ +myhook, &priority=10, [a=1156, b=hello world] +myhook, &priority=5, [a=37, b=goobye world] +myhook3, 8 +myhook4, 2 +myhook4, 1 +myhook, &priority=10, [a=2, b=it works] +myhook, &priority=5, [a=37, b=goobye world] diff --git a/testing/btest/Baseline/language.invalid_hook/out b/testing/btest/Baseline/language.invalid_hook/out new file mode 100644 index 0000000000..167d62ccc8 --- /dev/null +++ b/testing/btest/Baseline/language.invalid_hook/out @@ -0,0 +1 @@ +error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.invalid_hook/invalid_hook.bro, line 15: hook called in expression, use hook statement instead (myhook(nope)) diff --git a/testing/btest/istate/events-ssl.bro b/testing/btest/istate/events-ssl.bro index 1d285869b4..e4440834a7 100644 --- a/testing/btest/istate/events-ssl.bro +++ b/testing/btest/istate/events-ssl.bro @@ -11,8 +11,8 @@ # @TEST-EXEC: cat receiver/http.log | $SCRIPTS/diff-remove-timestamps >receiver.http.log # @TEST-EXEC: cmp sender.http.log receiver.http.log # -# @TEST-EXEC: bro -x sender/events.bst | sed 's/^Event \[[-0-9.]*\] //g' | grep '^http_' | grep -v http_stats | sed 's/(.*$//g' | $SCRIPTS/diff-remove-timestamps >events.snd.log -# @TEST-EXEC: bro -x receiver/events.bst | sed 's/^Event \[[-0-9.]*\] //g' | grep '^http_' | grep -v http_stats | sed 's/(.*$//g' | $SCRIPTS/diff-remove-timestamps >events.rec.log +# @TEST-EXEC: bro -x sender/events.bst | sed 's/^event \[[-0-9.]*\] //g' | grep '^http_' | grep -v http_stats | sed 's/(.*$//g' | $SCRIPTS/diff-remove-timestamps >events.snd.log +# @TEST-EXEC: bro -x receiver/events.bst | sed 's/^event \[[-0-9.]*\] //g' | grep '^http_' | grep -v http_stats | sed 's/(.*$//g' | $SCRIPTS/diff-remove-timestamps >events.rec.log # @TEST-EXEC: btest-diff events.rec.log # @TEST-EXEC: btest-diff events.snd.log # @TEST-EXEC: cmp events.rec.log events.snd.log diff --git a/testing/btest/istate/events.bro b/testing/btest/istate/events.bro index 590aabcd23..c292f77113 100644 --- a/testing/btest/istate/events.bro +++ b/testing/btest/istate/events.bro @@ -11,8 +11,8 @@ # @TEST-EXEC: cat receiver/http.log | $SCRIPTS/diff-remove-timestamps >receiver.http.log # @TEST-EXEC: cmp sender.http.log receiver.http.log # -# @TEST-EXEC: bro -x sender/events.bst | sed 's/^Event \[[-0-9.]*\] //g' | grep '^http_' | grep -v http_stats | sed 's/(.*$//g' | $SCRIPTS/diff-remove-timestamps >events.snd.log -# @TEST-EXEC: bro -x receiver/events.bst | sed 's/^Event \[[-0-9.]*\] //g' | grep '^http_' | grep -v http_stats | sed 's/(.*$//g' | $SCRIPTS/diff-remove-timestamps >events.rec.log +# @TEST-EXEC: bro -x sender/events.bst | sed 's/^event \[[-0-9.]*\] //g' | grep '^http_' | grep -v http_stats | sed 's/(.*$//g' | $SCRIPTS/diff-remove-timestamps >events.snd.log +# @TEST-EXEC: bro -x receiver/events.bst | sed 's/^event \[[-0-9.]*\] //g' | grep '^http_' | grep -v http_stats | sed 's/(.*$//g' | $SCRIPTS/diff-remove-timestamps >events.rec.log # @TEST-EXEC: btest-diff events.rec.log # @TEST-EXEC: btest-diff events.snd.log # @TEST-EXEC: cmp events.rec.log events.snd.log diff --git a/testing/btest/language/hook.bro b/testing/btest/language/hook.bro new file mode 100644 index 0000000000..8f7a85ce95 --- /dev/null +++ b/testing/btest/language/hook.bro @@ -0,0 +1,71 @@ +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out + +type rec: record { + a: count; + b: string; +}; + +global myhook: hook(r: rec); +global myhook2: hook(s: string); +# a hook doesn't have to take any arguments +global myhook4: hook(); + +hook myhook(r: rec) &priority=5 + { + print "myhook, &priority=5", r; + # break statement short-circuits the hook handling chain. + break; + print "ERROR: break statement should return from hook handler body"; + } + +hook myhook(r: rec) + { + # This handler shouldn't execute ever because of the handler at priority=5 + # exiting the body from a "break" statement. + print "myhook, &priority=0", rec; + } + +hook myhook(r: rec) &priority=10 + { + print "myhook, &priority=10", r; + # modifications to the record argument will be seen by remaining handlers. + r$a = 37; + r$b = "goobye world"; + # returning from the handler early, is fine, remaining handlers still run. + return; + print "ERROR: break statement should return from hook handler body"; + } + +# hook function doesn't need a declaration, we can go straight to defining +# a handler body. +hook myhook3(i: count) + { + print "myhook3", i; + } + +hook myhook4() &priority=1 + { + print "myhook4", 1; + } + +hook myhook4() &priority=2 + { + print "myhook4", 2; + } + +event bro_init() + { + hook myhook([$a=1156, $b="hello world"]); + + # A hook with no handlers is fine, it's just a no-op. + hook myhook2("nope"); + + hook myhook3(8); + hook myhook4(); + + # A hook can be treated like other data types and doesn't have to be + # invoked directly by name. + local h = myhook; + hook h([$a=2, $b="it works"]); + } diff --git a/testing/btest/language/invalid_hook.bro b/testing/btest/language/invalid_hook.bro new file mode 100644 index 0000000000..0dbbfd1b6f --- /dev/null +++ b/testing/btest/language/invalid_hook.bro @@ -0,0 +1,16 @@ +# @TEST-EXEC-FAIL: bro -b %INPUT >out 2>&1 +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out + +global myhook: hook(s: string); + +hook myhook(s: string) + { + print "myhook", s; + } + +event bro_init() + { + # hooks must be invoked with a "hook", statement. They have no return + # value and don't make sense to evaluate as arbitrary expressions. + local r = myhook("nope"); + } From c8d64b50289132d4f455c991ecaae62ad4e1424e Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 15 Nov 2012 14:02:24 -0600 Subject: [PATCH 05/23] Add memory leak unit test for "hook" function flavor. --- testing/btest/core/leaks/hook.bro | 78 +++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 testing/btest/core/leaks/hook.bro diff --git a/testing/btest/core/leaks/hook.bro b/testing/btest/core/leaks/hook.bro new file mode 100644 index 0000000000..eadb406e71 --- /dev/null +++ b/testing/btest/core/leaks/hook.bro @@ -0,0 +1,78 @@ +# Needs perftools support. +# +# @TEST-GROUP: leaks +# +# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks +# +# @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local bro -m -b -r $TRACES/wikipedia.trace %INPUT + +type rec: record { + a: count; + b: string; +}; + +global myhook: hook(r: rec); +global myhook2: hook(s: string); +# a hook doesn't have to take any arguments +global myhook4: hook(); + +hook myhook(r: rec) &priority=5 + { + print "myhook, &priority=5", r; + # break statement short-circuits the hook handling chain. + break; + print "ERROR: break statement should return from hook handler body"; + } + +hook myhook(r: rec) + { + # This handler shouldn't execute ever because of the handler at priority=5 + # exiting the body from a "break" statement. + print "myhook, &priority=0", rec; + } + +hook myhook(r: rec) &priority=10 + { + print "myhook, &priority=10", r; + # modifications to the record argument will be seen by remaining handlers. + r$a = 37; + r$b = "goobye world"; + # returning from the handler early, is fine, remaining handlers still run. + return; + print "ERROR: break statement should return from hook handler body"; + } + +# hook function doesn't need a declaration, we can go straight to defining +# a handler body. +hook myhook3(i: count) + { + print "myhook3", i; + } + +hook myhook4() &priority=1 + { + print "myhook4", 1; + } + +hook myhook4() &priority=2 + { + print "myhook4", 2; + } + +event new_connection(c: connection) + { + print "new_connection", c$id; + + hook myhook([$a=1156, $b="hello world"]); + + # A hook with no handlers is fine, it's just a no-op. + hook myhook2("nope"); + + hook myhook3(8); + hook myhook4(); + + # A hook can be treated like other data types and doesn't have to be + # invoked directly by name. + local h = myhook; + hook h([$a=2, $b="it works"]); + } From e0805498c6fd491bf56d51a4b3533c51c607d060 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 15 Nov 2012 16:40:18 -0600 Subject: [PATCH 06/23] Fix some warnings from sphinx when building docs. --- scripts/base/frameworks/intel/main.bro | 4 ++-- scripts/policy/integration/collective-intel/README | 10 ++++------ scripts/policy/protocols/modbus/track-memmap.bro | 3 ++- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/scripts/base/frameworks/intel/main.bro b/scripts/base/frameworks/intel/main.bro index d66990e611..aeb7bf4bfc 100644 --- a/scripts/base/frameworks/intel/main.bro +++ b/scripts/base/frameworks/intel/main.bro @@ -59,7 +59,7 @@ export { }; ## Enum to represent where data came from when it was discovered. - ## The convenction is to prefix the name with "IN_". + ## The convention is to prefix the name with ``IN_``. type Where: enum { ## A catchall value to represent data of unknown provenance. IN_ANYWHERE, @@ -342,4 +342,4 @@ function insert(item: Item) else event Intel::new_item(item); } - \ No newline at end of file + diff --git a/scripts/policy/integration/collective-intel/README b/scripts/policy/integration/collective-intel/README index 550eb96962..17d534c8dd 100644 --- a/scripts/policy/integration/collective-intel/README +++ b/scripts/policy/integration/collective-intel/README @@ -1,6 +1,4 @@ -Collective Intelligence Framework Integration -============================================= - -The scripts in this module are for deeper integration with the Collective Intelligence -Framework (CIF) since Bro's Intel framework doesn't natively behave the same as CIF nor -does it store and maintain the same data in all cases. \ No newline at end of file +The scripts in this module are for deeper integration with the +Collective Intelligence Framework (CIF) since Bro's Intel framework +doesn't natively behave the same as CIF nor does it store and maintain +the same data in all cases. diff --git a/scripts/policy/protocols/modbus/track-memmap.bro b/scripts/policy/protocols/modbus/track-memmap.bro index fc02d9b274..e2001e66bf 100644 --- a/scripts/policy/protocols/modbus/track-memmap.bro +++ b/scripts/policy/protocols/modbus/track-memmap.bro @@ -2,11 +2,12 @@ ##! changes as they are discovered. ##! ##! .. todo: Not all register reads and write functions are being supported yet. -module Modbus; @load base/protocols/modbus @load base/utils/directions-and-hosts +module Modbus; + export { redef enum Log::ID += { Modbus::REGISTER_CHANGE_LOG }; From 9e49703087dfc0c69e9362144fc91bcf4d2cc7c1 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 15 Nov 2012 16:54:33 -0600 Subject: [PATCH 07/23] Improve auto-generated enum documentation. The names of enum types are tracked so that variables holding a value of a given enum type can generate a reference to it instead of just listing the type as a generic "enum". --- src/ID.cc | 8 ++++++++ src/Type.cc | 10 +++++++++- src/Type.h | 12 ++++++++++-- src/parse.y | 13 ++++++++----- .../autogen-reST-enums.rst | 16 ++++++++++++++++ testing/btest/doc/autogen-reST-enums.bro | 3 +++ 6 files changed, 54 insertions(+), 8 deletions(-) diff --git a/src/ID.cc b/src/ID.cc index a70aa3fd0e..dcf163650c 100644 --- a/src/ID.cc +++ b/src/ID.cc @@ -660,8 +660,16 @@ void ID::DescribeReSTShort(ODesc* d) const d->Add(type->AsFuncType()->IsEvent() ? "event" : type_name(t)); break; + case TYPE_ENUM: + if ( is_type ) + d->Add(type_name(t)); + else + d->Add(type->AsEnumType()->Name().c_str()); + break; + default: d->Add(type_name(t)); + break; } } diff --git a/src/Type.cc b/src/Type.cc index 414c07d3d7..e1a9271aa3 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1202,9 +1202,10 @@ bool FileType::DoUnserialize(UnserialInfo* info) return yield != 0; } -EnumType::EnumType() +EnumType::EnumType(const string& arg_name) : BroType(TYPE_ENUM) { + name = arg_name; counter = 0; } @@ -1327,6 +1328,13 @@ const char* EnumType::Lookup(bro_int_t value) return 0; } +void EnumType::DescribeReST(ODesc* d) const + { + d->Add(":bro:type:`"); + d->Add(name.c_str()); + d->Add("`"); + } + void CommentedEnumType::DescribeReST(ODesc* d) const { // create temporary, reverse name map so that enums can be documented diff --git a/src/Type.h b/src/Type.h index efe15e6188..3a0b349f19 100644 --- a/src/Type.h +++ b/src/Type.h @@ -497,7 +497,7 @@ protected: class EnumType : public BroType { public: - EnumType(); + EnumType(const string& arg_name); ~EnumType(); // The value of this name is next internal counter value, starting @@ -513,7 +513,12 @@ public: bro_int_t Lookup(const string& module_name, const char* name); const char* Lookup(bro_int_t value); // Returns 0 if not found + string Name() const { return name; } + + void DescribeReST(ODesc* d) const; + protected: + EnumType() { counter = 0; } DECLARE_SERIAL(EnumType) virtual void AddNameInternal(const string& module_name, @@ -529,11 +534,14 @@ protected: // as a flag to prevent mixing of auto-increment and explicit // enumerator specifications. bro_int_t counter; + + // The name of the enum type is stored for documentation purposes. + string name; }; class CommentedEnumType: public EnumType { public: - CommentedEnumType() {} + CommentedEnumType(const string& arg_name) : EnumType(arg_name) {} ~CommentedEnumType(); void DescribeReST(ODesc* d) const; diff --git a/src/parse.y b/src/parse.y index c1f6ddd96e..035ec03f90 100644 --- a/src/parse.y +++ b/src/parse.y @@ -131,16 +131,18 @@ const char* cur_enum_elem_id = 0; type_decl_list* fake_type_decl_list = 0; TypeDecl* last_fake_type_decl = 0; +static ID* cur_decl_type_id = 0; + static void parser_new_enum (void) { /* Starting a new enum definition. */ assert(cur_enum_type == NULL); - cur_enum_type = new EnumType(); + cur_enum_type = new EnumType(cur_decl_type_id->Name()); // For documentation purposes, a separate type object is created // in order to avoid overlap that can be caused by redefs. if ( generate_documentation ) - cur_enum_type_doc = new CommentedEnumType(); + cur_enum_type_doc = new CommentedEnumType(cur_decl_type_id->Name()); } static void parser_redef_enum (ID *id) @@ -158,7 +160,7 @@ static void parser_redef_enum (ID *id) } if ( generate_documentation ) - cur_enum_type_doc = new CommentedEnumType(); + cur_enum_type_doc = new CommentedEnumType(id->Name()); } static void add_enum_comment (std::list* comments) @@ -1098,9 +1100,10 @@ decl: } } - | TOK_TYPE global_id ':' type opt_attr ';' + | TOK_TYPE global_id ':' { cur_decl_type_id = $2; } type opt_attr ';' { - add_type($2, $4, $5, 0); + cur_decl_type_id = 0; + add_type($2, $5, $6, 0); if ( generate_documentation ) { diff --git a/testing/btest/Baseline/doc.autogen-reST-enums/autogen-reST-enums.rst b/testing/btest/Baseline/doc.autogen-reST-enums/autogen-reST-enums.rst index 8bd6286c24..7ee7d86e66 100644 --- a/testing/btest/Baseline/doc.autogen-reST-enums/autogen-reST-enums.rst +++ b/testing/btest/Baseline/doc.autogen-reST-enums/autogen-reST-enums.rst @@ -12,6 +12,12 @@ autogen-reST-enums.bro Summary ~~~~~~~ +Options +####### +==================================================================== ====================================================================== +:bro:id:`test_enum_option`: :bro:type:`TestEnum1` :bro:attr:`&redef` this should reference the TestEnum1 type and not a generic "enum" type +==================================================================== ====================================================================== + Types ##### ======================================= ====================================== @@ -30,6 +36,16 @@ Redefinitions Detailed Interface ~~~~~~~~~~~~~~~~~~ +Options +####### +.. bro:id:: test_enum_option + + :Type: :bro:type:`TestEnum1` + :Attributes: :bro:attr:`&redef` + :Default: ``ONE`` + + this should reference the TestEnum1 type and not a generic "enum" type + Types ##### .. bro:type:: TestEnum1 diff --git a/testing/btest/doc/autogen-reST-enums.bro b/testing/btest/doc/autogen-reST-enums.bro index fc01bed243..e3cceba22e 100644 --- a/testing/btest/doc/autogen-reST-enums.bro +++ b/testing/btest/doc/autogen-reST-enums.bro @@ -34,3 +34,6 @@ redef enum TestEnum1 += { ## adding another FIVE, ##< value }; + +## this should reference the TestEnum1 type and not a generic "enum" type +const test_enum_option = ONE &redef; From 56e359ca9d7e54b61ed8806324f6b0bb89e96315 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 16 Nov 2012 12:43:39 -0600 Subject: [PATCH 08/23] Fix ambiguity between composite table index and record ctor expressions. For tables of a composite index type with the first type being a record, membership checks with an inline index key could be misinterpreted as a record constructor instead of an expression list. E.g, if the table type is "global t = table[conn_id, bool] of count", then checking membership like "[c$id, is_orig] in t" now works. Addresses #80. --- src/parse.y | 25 +++++++++++++++-------- testing/btest/Baseline/language.table/out | 6 ++++++ testing/btest/language/table.bro | 16 ++++++++++++++- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/parse.y b/src/parse.y index c1f6ddd96e..6cafa94021 100644 --- a/src/parse.y +++ b/src/parse.y @@ -456,17 +456,24 @@ expr: | '[' expr_list ']' { - // A little crufty: we peek at the type of - // the first expression in the list. If it's - // a record or a field assignment, then this - // is a record constructor. If not, then this - // is a list used for an initializer. - set_location(@1, @3); - Expr* e0 = $2->Exprs()[0]; - if ( e0->Tag() == EXPR_FIELD_ASSIGN || - e0->Type()->Tag() == TYPE_RECORD ) + bool is_record_ctor = true; + + // If every expression in the list is a field assignment, + // then treat it as a record constructor, else as a list + // used for an initializer. + + for ( int i = 0; i < $2->Exprs().length(); ++i ) + { + if ( $2->Exprs()[i]->Tag() != EXPR_FIELD_ASSIGN ) + { + is_record_ctor = false; + break; + } + } + + if ( is_record_ctor ) $$ = new RecordConstructorExpr($2); else $$ = $2; diff --git a/testing/btest/Baseline/language.table/out b/testing/btest/Baseline/language.table/out index 514cb6b02d..0d746ded2b 100644 --- a/testing/btest/Baseline/language.table/out +++ b/testing/btest/Baseline/language.table/out @@ -12,6 +12,7 @@ cardinality (PASS) cardinality (PASS) cardinality (PASS) cardinality (PASS) +cardinality (PASS) iterate over table (PASS) iterate over table (PASS) iterate over table (PASS) @@ -30,6 +31,11 @@ add element (PASS) in operator (PASS) add element (PASS) in operator (PASS) +composite index add element (PASS) +composite index in operator (PASS) +composite index in operator (PASS) +remove element (PASS) +!in operator (PASS) remove element (PASS) !in operator (PASS) remove element (PASS) diff --git a/testing/btest/language/table.bro b/testing/btest/language/table.bro index d1b0751970..3c8e8db280 100644 --- a/testing/btest/language/table.bro +++ b/testing/btest/language/table.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) @@ -26,6 +26,9 @@ event bro_init() local t10: table[port, string, bool] of string = { [10/udp, "curly", F] = "first", [11/udp, "braces", T] = "second" }; + local t11: table[conn_id, bool] of count = { + [ [$orig_h=1.1.1.1, $orig_p=1234/tcp, + $resp_h=2.2.2.2, $resp_p=4321/tcp], T ] = 42 }; # Type inference tests @@ -45,6 +48,7 @@ event bro_init() test_case( "cardinality", |t8| == 0 ); test_case( "cardinality", |t9| == 1 ); test_case( "cardinality", |t10| == 2 ); + test_case( "cardinality", |t11| == 1 ); test_case( "cardinality", |tg1| == 3 ); # Test iterating over each table @@ -121,6 +125,13 @@ event bro_init() test_case( "add element", |t5| == 3 ); test_case( "in operator", 10 in t5 ); + local cid = [$orig_h=1.1.1.1, $orig_p=1234/tcp, + $resp_h=2.2.2.2, $resp_p=4321/tcp]; + t11[[$orig_h=[::1], $orig_p=3/tcp, $resp_h=[::2], $resp_p=3/tcp], F] = 3; + test_case( "composite index add element", |t11| == 2 ); + test_case( "composite index in operator", [cid, T] in t11 ); + test_case( "composite index in operator", [[$orig_h=[::1], $orig_p=3/tcp, $resp_h=[::2], $resp_p=3/tcp], F] in t11 ); + # Test removing elements from each table (Note: cannot remove elements # from tables of multiple types) @@ -145,5 +156,8 @@ event bro_init() test_case( "remove element", |t5| == 2 ); test_case( "!in operator", 1 !in t5 ); + delete t11[cid, T]; + test_case( "remove element", |t11| == 1 ); + test_case( "!in operator", [cid, T] !in t11 ); } From 6c2ee1ef54fda85142b8e017f5cce77f0afb9955 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 23 Nov 2012 18:46:57 -0800 Subject: [PATCH 09/23] Removing in_hook variable in parser. I believe that's unnecessary and tests indeed pass just fine without it. --- src/parse.y | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/parse.y b/src/parse.y index 9a66973d6b..b4eee1a56c 100644 --- a/src/parse.y +++ b/src/parse.y @@ -119,7 +119,6 @@ extern const char* g_curr_debug_error; #define YYLTYPE yyltype -static bool in_hook = false; int in_init = 0; int in_record = 0; bool resolving_global_ID = false; @@ -1373,11 +1372,11 @@ stmt: brofiler.AddStmt($$); } - | TOK_HOOK { in_hook = true; } hook { in_hook = false; } ';' opt_no_test + | TOK_HOOK hook ';' opt_no_test { - set_location(@1, @5); - $$ = new HookStmt($3); - if ( ! $6 ) + set_location(@1, @4); + $$ = new HookStmt($2); + if ( ! $4 ) brofiler.AddStmt($$); } @@ -1538,7 +1537,7 @@ hook: expr '(' opt_expr_list ')' { set_location(@1, @4); - $$ = new CallExpr($1, $3, in_hook); + $$ = new CallExpr($1, $3, true); } ; From a5e237f50c963bfc815cff6c9c9a457189a7ec68 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 23 Nov 2012 19:33:28 -0800 Subject: [PATCH 10/23] The ASCII writer now supports a filter config option 'only_single_header_row' that turns the output into CSV format. In that mode all meta data is skipped except for a single header line with the fields names. Example: local my_filter: Log::Filter = [$name = "my-filter", $writer = Log::WRITER_ASCII, $config = table(["only_single_header_row"] = "T")]; Contributed by Carsten Langer. --- CHANGES | 15 ++++ VERSION | 2 +- .../base/frameworks/logging/writers/ascii.bro | 8 +++ src/logging/writers/Ascii.cc | 69 +++++++++++++------ src/logging/writers/Ascii.h | 1 + .../ssh-filtered.log | 6 ++ .../base/frameworks/logging/ascii-csv.bro | 37 ++++++++++ 7 files changed, 117 insertions(+), 21 deletions(-) create mode 100644 testing/btest/Baseline/scripts.base.frameworks.logging.ascii-csv/ssh-filtered.log create mode 100644 testing/btest/scripts/base/frameworks/logging/ascii-csv.bro diff --git a/CHANGES b/CHANGES index 5a04012955..cc42fa701b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,19 @@ +2.1-178 | 2012-11-23 19:35:32 -0800 + + * The ASCII writer now supports a new filter config option + "only_single_header_row" that turns the output into CSV format + when set to "T". (Carsten Langer) + + * Add new function flavor called a "hook". This new flavor of + function behaves like a "synchronous event". See + doc/scripts/builtins.rst more details on usage. (Jon Siwek) + + * Improve auto-generated enum documentation. The names of enum types + are tracked so that variables holding a value of a given enum type + can generate a reference to it instead of just listing the type as + a generic "enum". (Jon Siwek) + 2.1-171 | 2012-11-23 18:24:15 -0800 * Fix ambiguity between composite table index and record ctor diff --git a/VERSION b/VERSION index 7a44c3a19f..fc5f5588a7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-171 +2.1-178 diff --git a/scripts/base/frameworks/logging/writers/ascii.bro b/scripts/base/frameworks/logging/writers/ascii.bro index bacb0996d0..800af51502 100644 --- a/scripts/base/frameworks/logging/writers/ascii.bro +++ b/scripts/base/frameworks/logging/writers/ascii.bro @@ -1,5 +1,13 @@ ##! Interface for the ASCII log writer. Redefinable options are available ##! to tweak the output format of ASCII logs. +##! +##! The ASCII writer supports currently one writer-specific filter option via +##! ``config``: setting ``only_single_header_row`` to ``T`` turns the output into +##! into CSV mode where only a single header row with the column names is printed +##! out as meta information. Example filter using this:: +##! +##! local my_filter: Log::Filter = [$name = "my-filter", $writer = Log::WRITER_ASCII, $config = table(["only_single_header_row"] = "T")]; +##! module LogAscii; diff --git a/src/logging/writers/Ascii.cc b/src/logging/writers/Ascii.cc index 11b322f5a3..c65b0701c3 100644 --- a/src/logging/writers/Ascii.cc +++ b/src/logging/writers/Ascii.cc @@ -19,6 +19,7 @@ Ascii::Ascii(WriterFrontend* frontend) : WriterBackend(frontend) { fd = 0; ascii_done = false; + only_single_header_row = false; output_to_stdout = BifConst::LogAscii::output_to_stdout; include_meta = BifConst::LogAscii::include_meta; @@ -80,7 +81,7 @@ void Ascii::CloseFile(double t) if ( ! fd ) return; - if ( include_meta ) + if ( include_meta && ! only_single_header_row ) WriteHeaderField("close", Timestamp(0)); safe_close(fd); @@ -108,29 +109,29 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const Field* const * return false; } + for ( WriterInfo::config_map::const_iterator i = info.config.begin(); i != info.config.end(); i++ ) + { + if ( strcmp(i->first, "only_single_header_row") == 0 ) + { + if ( strcmp(i->second, "T") == 0 ) + only_single_header_row = true; + + else if ( strcmp(i->second, "F") == 0 ) + only_single_header_row = false; + + else + { + Error("invalid value for 'only_single_header_row', must be boolean (T/F)"); + return false; + } + } + } + if ( include_meta ) { string names; string types; - string str = string(meta_prefix, meta_prefix_len) - + "separator " // Always use space as separator here. - + get_escaped_string(string(separator, separator_len), false) - + "\n"; - - if ( ! safe_write(fd, str.c_str(), str.length()) ) - goto write_error; - - if ( ! (WriteHeaderField("set_separator", get_escaped_string( - string(set_separator, set_separator_len), false)) && - WriteHeaderField("empty_field", get_escaped_string( - string(empty_field, empty_field_len), false)) && - WriteHeaderField("unset_field", get_escaped_string( - string(unset_field, unset_field_len), false)) && - WriteHeaderField("path", get_escaped_string(path, false)) && - WriteHeaderField("open", Timestamp(0))) ) - goto write_error; - for ( int i = 0; i < num_fields; ++i ) { if ( i > 0 ) @@ -143,11 +144,39 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const Field* const * types += fields[i]->TypeName().c_str(); } + if ( only_single_header_row ) + { + // A single CSV-style line is all we need. + string str = names + "\n"; + if ( ! safe_write(fd, str.c_str(), str.length()) ) + goto write_error; + + return true; + } + + string str = string(meta_prefix, meta_prefix_len) + + "separator " // Always use space as separator here. + + get_escaped_string(string(separator, separator_len), false) + + "\n"; + + if ( ! safe_write(fd, str.c_str(), str.length()) ) + goto write_error; + + if ( ! (WriteHeaderField("set_separator", get_escaped_string( + string(set_separator, set_separator_len), false)) && + WriteHeaderField("empty_field", get_escaped_string( + string(empty_field, empty_field_len), false)) && + WriteHeaderField("unset_field", get_escaped_string( + string(unset_field, unset_field_len), false)) && + WriteHeaderField("path", get_escaped_string(path, false)) && + WriteHeaderField("open", Timestamp(0))) ) + goto write_error; + if ( ! (WriteHeaderField("fields", names) && WriteHeaderField("types", types)) ) goto write_error; } - + return true; write_error: diff --git a/src/logging/writers/Ascii.h b/src/logging/writers/Ascii.h index cf0190aa80..37ec19aba6 100644 --- a/src/logging/writers/Ascii.h +++ b/src/logging/writers/Ascii.h @@ -45,6 +45,7 @@ private: // Options set from the script-level. bool output_to_stdout; bool include_meta; + bool only_single_header_row; char* separator; int separator_len; diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-csv/ssh-filtered.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-csv/ssh-filtered.log new file mode 100644 index 0000000000..f59c7c8f54 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-csv/ssh-filtered.log @@ -0,0 +1,6 @@ +t id.orig_h id.orig_p id.resp_h id.resp_p status country b +1353727995.082217 1.2.3.4 1234 2.3.4.5 80 success unknown - +1353727995.082217 1.2.3.4 1234 2.3.4.5 80 - US - +1353727995.082217 1.2.3.4 1234 2.3.4.5 80 failure UK - +1353727995.082217 1.2.3.4 1234 2.3.4.5 80 - BR - +1353727995.082217 1.2.3.4 1234 2.3.4.5 80 failure (empty) T diff --git a/testing/btest/scripts/base/frameworks/logging/ascii-csv.bro b/testing/btest/scripts/base/frameworks/logging/ascii-csv.bro new file mode 100644 index 0000000000..1c10f5fc6b --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/ascii-csv.bro @@ -0,0 +1,37 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: cat ssh.log | grep -v PREFIX.*20..- >ssh-filtered.log +# @TEST-EXEC: btest-diff ssh-filtered.log + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + b: bool &optional; + } &log; +} + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + + local filter = Log::get_filter(SSH::LOG, "default"); + filter$config = table(["only_single_header_row"] = "T"); + Log::add_filter(SSH::LOG, filter); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $b=T, $status="failure", $country=""]); + +} + From 7245aa597768aa335cd597ba7798da3dab992346 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 23 Nov 2012 19:39:27 -0800 Subject: [PATCH 11/23] Adding NEWS placeholder for hooks and CSV mode. --- NEWS | 5 +++++ VERSION | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 26dcf0e8cd..63c4d5d6f7 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,11 @@ New Functionality - ssl.log now also records the subject client and issuer certificates. +- Hooks: TODO: Briefly summarize the documention from + doc/scripts/builtins.rst here. + +- The ASCII writer can now output CSV files on a per filter basis. + Changed Functionality ~~~~~~~~~~~~~~~~~~~~~ diff --git a/VERSION b/VERSION index fc5f5588a7..6463a80a16 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-178 +2.1-179 From e2fdf16e0c87b914cf271e03766010f24d1b41ca Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 23 Nov 2012 19:51:42 -0800 Subject: [PATCH 12/23] Updating submodule(s). [nomail] --- aux/broccoli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broccoli b/aux/broccoli index 907210ce14..a8846fc5b0 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 907210ce1470724fb386f939cc1b10a4caa2ae39 +Subproject commit a8846fc5b004ffe4e3d00e826d0077ba19518192 From c98301e51f6c4cfd48d299e7cfe59e03565cd2d8 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 26 Nov 2012 15:58:25 -0500 Subject: [PATCH 13/23] Fixed a DNS attribute issue (reported by Matt Thompson). --- scripts/base/protocols/dns/main.bro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/base/protocols/dns/main.bro b/scripts/base/protocols/dns/main.bro index 8ae3806ab6..ee0e4166da 100644 --- a/scripts/base/protocols/dns/main.bro +++ b/scripts/base/protocols/dns/main.bro @@ -67,7 +67,7 @@ export { ready: bool &default=F; ## The total number of resource records in a reply message's answer ## section. - total_answers: count &default=0; + total_answers: count &optional; ## The total number of resource records in a reply message's answer, ## authority, and additional sections. total_replies: count &optional; @@ -231,6 +231,7 @@ event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) Log::write(DNS::LOG, c$dns); # This record is logged and no longer pending. delete c$dns_state$pending[c$dns$trans_id]; + delete c$dns; } } From 378ee699ffc058f368a06691e4237c7f1e791462 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 26 Nov 2012 16:54:36 -0600 Subject: [PATCH 14/23] Hook functions now directly callable instead of w/ "hook" statements. The return value of the call is an implicit boolean value of T if all hook handlers ran, or F if one hook handler exited as a result of a break statement and potentially prevented other handlers from running. Scripts don't need to declare hooks with an explicit return type of bool (internally, that's assumed), and any values given to (optional) return statements in handler definitions are just ignored. Addresses #918. --- doc/scripts/builtins.rst | 29 +++++----- src/Expr.cc | 11 ++-- src/Expr.h | 2 +- src/Func.cc | 23 ++++++-- src/SerialTypes.h | 1 - src/Stmt.cc | 54 ++----------------- src/Stmt.h | 18 ------- src/StmtEnums.h | 2 +- src/Var.cc | 4 +- src/parse.y | 24 ++------- testing/btest/Baseline/language.hook/out | 8 +++ .../btest/Baseline/language.invalid_hook/out | 1 - testing/btest/core/leaks/hook.bro | 30 ++++++++--- testing/btest/language/hook.bro | 30 ++++++++--- testing/btest/language/invalid_hook.bro | 16 ------ 15 files changed, 108 insertions(+), 145 deletions(-) delete mode 100644 testing/btest/Baseline/language.invalid_hook/out delete mode 100644 testing/btest/language/invalid_hook.bro diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index ba786ba0d2..cf62299783 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -505,15 +505,14 @@ The Bro scripting language supports the following built-in types. A hook is another flavor of function that shares characteristics of both a :bro:type:`function` and a :bro:type:`event`. They are like events in that many handler bodies can be defined for the same hook - identifier, they have no return vale, and the order of execution - can be enforced with :bro:attr:`&priority`. They are more like - functions in the way they are invoked/called, because, unlike - events, their execution is immediate and they do not get scheduled - through an event queue. Also, a unique feature of a hook is that - a given hook handler body can short-circuit the execution of - remaining hook handlers simply by exiting from the body as a result - of a ``break`` statement (as opposed to a ``return`` or just - reaching the end of the body). + identifier and the order of execution can be enforced with + :bro:attr:`&priority`. They are more like functions in the way they + are invoked/called, because, unlike events, their execution is + immediate and they do not get scheduled through an event queue. + Also, a unique feature of a hook is that a given hook handler body + can short-circuit the execution of remaining hook handlers simply by + exiting from the body as a result of a ``break`` statement (as + opposed to a ``return`` or just reaching the end of the body). A hook type is declared like:: @@ -553,12 +552,12 @@ The Bro scripting language supports the following built-in types. a hook type isn't strictly required, when it is provided, the argument types must match. - To invoke immediate execution of all hook handler bodies, a ``hook`` - statement must be used: + To invoke immediate execution of all hook handler bodies, they + can be called just like a function: .. code:: bro - hook myhook("hi"); + myhook("hi"); And the output would like like:: @@ -568,6 +567,12 @@ The Bro scripting language supports the following built-in types. Note how the modification to arguments can be seen by remaining hook handlers. + The return value of a hook call is an implicit :bro:type:`bool` + value with ``T`` meaning that all handlers for the hook were + executed and ``F`` meaning that only some of the handlers may have + executed due to one handler body exiting as a result of a ``break`` + statement. + Attributes ---------- diff --git a/src/Expr.cc b/src/Expr.cc index 733e0fe9a5..a7075566aa 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -4374,7 +4374,7 @@ bool InExpr::DoUnserialize(UnserialInfo* info) return true; } -CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) +CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args) : Expr(EXPR_CALL) { func = arg_func; @@ -4415,13 +4415,8 @@ CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) break; case FUNC_FLAVOR_HOOK: - // It's fine to not have a yield if it's known that the call - // is being done from a hook statement. - if ( ! in_hook ) - { - Error("hook called in expression, use hook statement instead"); - SetError(); - } + Error("hook has no yield type"); + SetError(); break; default: diff --git a/src/Expr.h b/src/Expr.h index bd4824f8ee..c16cf86612 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -959,7 +959,7 @@ protected: class CallExpr : public Expr { public: - CallExpr(Expr* func, ListExpr* args, bool in_hook = false); + CallExpr(Expr* func, ListExpr* args); ~CallExpr(); Expr* Func() const { return func; } diff --git a/src/Func.cc b/src/Func.cc index 27acce4f04..e3675ebc2c 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -349,16 +349,31 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const break; } - if ( flow == FLOW_BREAK && Flavor() == FUNC_FLAVOR_HOOK ) + if ( Flavor() == FUNC_FLAVOR_HOOK ) { - // short-circuit execution of remaining hook handler bodies - break; + // Ignore any return values of hook bodies, final return value + // depends on whether a body returns as a result of break statement + Unref(result); + result = 0; + + if ( flow == FLOW_BREAK ) + { + // short-circuit execution of remaining hook handler bodies + result = new Val(false, TYPE_BOOL); + break; + } } } + if ( Flavor() == FUNC_FLAVOR_HOOK ) + { + if ( ! result ) + result = new Val(true, TYPE_BOOL); + } + // Warn if the function returns something, but we returned from // the function without an explicit return, or without a value. - if ( FType()->YieldType() && FType()->YieldType()->Tag() != TYPE_VOID && + else if ( FType()->YieldType() && FType()->YieldType()->Tag() != TYPE_VOID && (flow != FLOW_RETURN /* we fell off the end */ || ! result /* explicit return with no result */) && ! f->HasDelayed() ) diff --git a/src/SerialTypes.h b/src/SerialTypes.h index a18c9bcc65..c47ff19298 100644 --- a/src/SerialTypes.h +++ b/src/SerialTypes.h @@ -165,7 +165,6 @@ SERIAL_STMT(EVENT_BODY_LIST, 16) SERIAL_STMT(INIT_STMT, 17) SERIAL_STMT(NULL_STMT, 18) SERIAL_STMT(WHEN_STMT, 19) -SERIAL_STMT(HOOK_STMT, 20) #define SERIAL_TYPE(name, val) SERIAL_CONST(name, val, BRO_TYPE) SERIAL_TYPE(BRO_TYPE, 1) diff --git a/src/Stmt.cc b/src/Stmt.cc index 0a5ae16ef6..c65b44a9bd 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -23,7 +23,7 @@ const char* stmt_name(BroStmtTag t) "print", "event", "expr", "if", "when", "switch", "for", "next", "break", "return", "add", "delete", "list", "bodylist", - "", "hook", + "", "null", }; @@ -933,52 +933,6 @@ bool EventStmt::DoUnserialize(UnserialInfo* info) return event_expr != 0; } -HookStmt::HookStmt(CallExpr* arg_e) : ExprStmt(STMT_HOOK, arg_e) - { - call_expr = arg_e; - } - -Val* HookStmt::Exec(Frame* f, stmt_flow_type& flow) const - { - RegisterAccess(); - - Val* ret = call_expr->Eval(f); - Unref(ret); - - flow = FLOW_NEXT; - - return 0; - } - -TraversalCode HookStmt::Traverse(TraversalCallback* cb) const - { - TraversalCode tc = cb->PreStmt(this); - HANDLE_TC_STMT_PRE(tc); - - // call expr is stored in base class's "e" field. - tc = e->Traverse(cb); - HANDLE_TC_STMT_PRE(tc); - - tc = cb->PostStmt(this); - HANDLE_TC_STMT_POST(tc); - } - -IMPLEMENT_SERIAL(HookStmt, SER_HOOK_STMT); - -bool HookStmt::DoSerialize(SerialInfo* info) const - { - DO_SERIALIZE(SER_HOOK_STMT, ExprStmt); - return call_expr->Serialize(info); - } - -bool HookStmt::DoUnserialize(UnserialInfo* info) - { - DO_UNSERIALIZE(ExprStmt); - - call_expr = (CallExpr*) Expr::Unserialize(info, EXPR_CALL); - return call_expr != 0; - } - ForStmt::ForStmt(id_list* arg_loop_vars, Expr* loop_expr) : ExprStmt(STMT_FOR, loop_expr) { @@ -1378,7 +1332,10 @@ ReturnStmt::ReturnStmt(Expr* arg_e) : ExprStmt(STMT_RETURN, arg_e) } else if ( ! e ) - Error("return statement needs expression"); + { + if ( ft->Flavor() != FUNC_FLAVOR_HOOK ) + Error("return statement needs expression"); + } else (void) check_and_promote_expr(e, yt); @@ -1990,7 +1947,6 @@ int same_stmt(const Stmt* s1, const Stmt* s2) case STMT_RETURN: case STMT_EXPR: case STMT_EVENT: - case STMT_HOOK: { const ExprStmt* e1 = (const ExprStmt*) s1; const ExprStmt* e2 = (const ExprStmt*) s2; diff --git a/src/Stmt.h b/src/Stmt.h index 68bb8d6425..7c3b42609b 100644 --- a/src/Stmt.h +++ b/src/Stmt.h @@ -286,24 +286,6 @@ protected: EventExpr* event_expr; }; -class HookStmt : public ExprStmt { -public: - HookStmt(CallExpr* e); - - Val* Exec(Frame* f, stmt_flow_type& flow) const; - - TraversalCode Traverse(TraversalCallback* cb) const; - -protected: - friend class Stmt; - - HookStmt() { call_expr = 0; } - - DECLARE_SERIAL(HookStmt); - - CallExpr* call_expr; -}; - class ForStmt : public ExprStmt { public: ForStmt(id_list* loop_vars, Expr* loop_expr); diff --git a/src/StmtEnums.h b/src/StmtEnums.h index fa5b70389d..f431e3fea1 100644 --- a/src/StmtEnums.h +++ b/src/StmtEnums.h @@ -15,7 +15,7 @@ typedef enum { STMT_RETURN, STMT_ADD, STMT_DELETE, STMT_LIST, STMT_EVENT_BODY_LIST, - STMT_INIT, STMT_HOOK, + STMT_INIT, STMT_NULL #define NUM_STMTS (int(STMT_NULL) + 1) } BroStmtTag; diff --git a/src/Var.cc b/src/Var.cc index 9c4fb5b978..68be18b55e 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -294,12 +294,12 @@ void add_type(ID* id, BroType* t, attr_list* attr, int /* is_event */) void begin_func(ID* id, const char* module_name, function_flavor flavor, int is_redef, FuncType* t) { - if ( flavor == FUNC_FLAVOR_EVENT || flavor == FUNC_FLAVOR_HOOK ) + if ( flavor == FUNC_FLAVOR_EVENT ) { const BroType* yt = t->YieldType(); if ( yt && yt->Tag() != TYPE_VOID ) - id->Error("event/hook cannot yield a value", t); + id->Error("event cannot yield a value", t); t->ClearYieldType(flavor); } diff --git a/src/parse.y b/src/parse.y index b4eee1a56c..39673cacc2 100644 --- a/src/parse.y +++ b/src/parse.y @@ -2,7 +2,7 @@ // See the file "COPYING" in the main distribution directory for copyright. %} -%expect 88 +%expect 87 %token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY %token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF @@ -56,7 +56,6 @@ %type pattern %type expr init anonymous_function %type event -%type hook %type stmt stmt_list func_body for_head %type type opt_type enum_body %type func_hdr func_params @@ -212,7 +211,6 @@ static std::list* concat_opt_docs (std::list* pre, Val* val; RE_Matcher* re; Expr* expr; - CallExpr* call_expr; EventExpr* event_expr; Stmt* stmt; ListExpr* list; @@ -875,7 +873,7 @@ type: | TOK_HOOK '(' formal_args ')' { set_location(@1, @3); - $$ = new FuncType($3, 0, FUNC_FLAVOR_HOOK); + $$ = new FuncType($3, base_type(TYPE_BOOL), FUNC_FLAVOR_HOOK); } | TOK_FILE TOK_OF type @@ -1209,6 +1207,8 @@ func_hdr: } | TOK_HOOK def_global_id func_params { + $3->ClearYieldType(FUNC_FLAVOR_HOOK); + $3->SetYieldType(base_type(TYPE_BOOL)); begin_func($2, current_module.c_str(), FUNC_FLAVOR_HOOK, 0, $3); $$ = $3; @@ -1372,14 +1372,6 @@ stmt: brofiler.AddStmt($$); } - | TOK_HOOK hook ';' opt_no_test - { - set_location(@1, @4); - $$ = new HookStmt($2); - if ( ! $4 ) - brofiler.AddStmt($$); - } - | TOK_IF '(' expr ')' stmt { set_location(@1, @4); @@ -1533,14 +1525,6 @@ event: } ; -hook: - expr '(' opt_expr_list ')' - { - set_location(@1, @4); - $$ = new CallExpr($1, $3, true); - } - ; - case_list: case_list case { $1->append($2); } diff --git a/testing/btest/Baseline/language.hook/out b/testing/btest/Baseline/language.hook/out index 10688acc3b..18828ad15f 100644 --- a/testing/btest/Baseline/language.hook/out +++ b/testing/btest/Baseline/language.hook/out @@ -1,7 +1,15 @@ myhook, &priority=10, [a=1156, b=hello world] +myhook return F +myhook return T myhook, &priority=5, [a=37, b=goobye world] +F myhook3, 8 +T myhook4, 2 myhook4, 1 +T myhook, &priority=10, [a=2, b=it works] +myhook return F +myhook return T myhook, &priority=5, [a=37, b=goobye world] +F diff --git a/testing/btest/Baseline/language.invalid_hook/out b/testing/btest/Baseline/language.invalid_hook/out deleted file mode 100644 index 167d62ccc8..0000000000 --- a/testing/btest/Baseline/language.invalid_hook/out +++ /dev/null @@ -1 +0,0 @@ -error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.invalid_hook/invalid_hook.bro, line 15: hook called in expression, use hook statement instead (myhook(nope)) diff --git a/testing/btest/core/leaks/hook.bro b/testing/btest/core/leaks/hook.bro index eadb406e71..d9dcbff369 100644 --- a/testing/btest/core/leaks/hook.bro +++ b/testing/btest/core/leaks/hook.bro @@ -39,7 +39,25 @@ hook myhook(r: rec) &priority=10 r$b = "goobye world"; # returning from the handler early, is fine, remaining handlers still run. return; - print "ERROR: break statement should return from hook handler body"; + print "ERROR: return statement should return from hook handler body"; + } + +hook myhook(r: rec) &priority=9 + { + print "myhook return F"; + # return value is ignored, remaining handlers still run, final return + # value is whether any hook body returned via break statement + return F; + print "ERROR: return statement should return from hook handler body"; + } + +hook myhook(r: rec) &priority=8 + { + print "myhook return T"; + # return value is ignored, remaining handlers still run, final return + # value is whether any hook body returned via break statement + return T; + print "ERROR: return statement should return from hook handler body"; } # hook function doesn't need a declaration, we can go straight to defining @@ -63,16 +81,16 @@ event new_connection(c: connection) { print "new_connection", c$id; - hook myhook([$a=1156, $b="hello world"]); + print myhook([$a=1156, $b="hello world"]); # A hook with no handlers is fine, it's just a no-op. - hook myhook2("nope"); + print myhook2("nope"); - hook myhook3(8); - hook myhook4(); + print myhook3(8); + print myhook4(); # A hook can be treated like other data types and doesn't have to be # invoked directly by name. local h = myhook; - hook h([$a=2, $b="it works"]); + print h([$a=2, $b="it works"]); } diff --git a/testing/btest/language/hook.bro b/testing/btest/language/hook.bro index 8f7a85ce95..eedd2ff056 100644 --- a/testing/btest/language/hook.bro +++ b/testing/btest/language/hook.bro @@ -34,7 +34,25 @@ hook myhook(r: rec) &priority=10 r$b = "goobye world"; # returning from the handler early, is fine, remaining handlers still run. return; - print "ERROR: break statement should return from hook handler body"; + print "ERROR: return statement should return from hook handler body"; + } + +hook myhook(r: rec) &priority=9 + { + print "myhook return F"; + # return value is ignored, remaining handlers still run, final return + # value is whether any hook body returned via break statement + return F; + print "ERROR: return statement should return from hook handler body"; + } + +hook myhook(r: rec) &priority=8 + { + print "myhook return T"; + # return value is ignored, remaining handlers still run, final return + # value is whether any hook body returned via break statement + return T; + print "ERROR: return statement should return from hook handler body"; } # hook function doesn't need a declaration, we can go straight to defining @@ -56,16 +74,16 @@ hook myhook4() &priority=2 event bro_init() { - hook myhook([$a=1156, $b="hello world"]); + print myhook([$a=1156, $b="hello world"]); # A hook with no handlers is fine, it's just a no-op. - hook myhook2("nope"); + print myhook2("nope"); - hook myhook3(8); - hook myhook4(); + print myhook3(8); + print myhook4(); # A hook can be treated like other data types and doesn't have to be # invoked directly by name. local h = myhook; - hook h([$a=2, $b="it works"]); + print h([$a=2, $b="it works"]); } diff --git a/testing/btest/language/invalid_hook.bro b/testing/btest/language/invalid_hook.bro deleted file mode 100644 index 0dbbfd1b6f..0000000000 --- a/testing/btest/language/invalid_hook.bro +++ /dev/null @@ -1,16 +0,0 @@ -# @TEST-EXEC-FAIL: bro -b %INPUT >out 2>&1 -# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out - -global myhook: hook(s: string); - -hook myhook(s: string) - { - print "myhook", s; - } - -event bro_init() - { - # hooks must be invoked with a "hook", statement. They have no return - # value and don't make sense to evaluate as arbitrary expressions. - local r = myhook("nope"); - } From a0590b2140adae5b9cc4ae5520bd566d12a4331d Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 28 Nov 2012 14:19:48 -0600 Subject: [PATCH 15/23] Fix table(), set(), vector() constructors in table initializer lists. Also adds type checking of yield values to table() constructor and fixes the type checking of yield values in vector() constructor. Addresses #5. --- src/Expr.cc | 38 ++++++++-- src/Val.cc | 2 + .../output | 42 +++++++++++ .../language/table-init-container-ctors.bro | 74 +++++++++++++++++++ 4 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 testing/btest/Baseline/language.table-init-container-ctors/output create mode 100644 testing/btest/language/table-init-container-ctors.bro diff --git a/src/Expr.cc b/src/Expr.cc index 733e0fe9a5..89680b9b5b 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -2663,7 +2663,7 @@ void AssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const TableVal* tv = aggr->AsTableVal(); Val* index = op1->Eval(f); - Val* v = op2->Eval(f); + Val* v = check_and_promote(op2->Eval(f), t->YieldType(), 1); if ( ! index || ! v ) return; @@ -3386,7 +3386,14 @@ Val* TableConstructorExpr::InitVal(const BroType* t, Val* aggr) const if ( IsError() ) return 0; - return op->InitVal(t, aggr); + TableType* tt = Type()->AsTableType(); + TableVal* tval = aggr ? aggr->AsTableVal() : new TableVal(tt, attrs); + const expr_list& exprs = op->AsListExpr()->Exprs(); + + loop_over_list(exprs, i) + exprs[i]->EvalIntoAggregate(t, tval, 0); + + return tval; } void TableConstructorExpr::ExprDescribe(ODesc* d) const @@ -3456,7 +3463,26 @@ Val* SetConstructorExpr::InitVal(const BroType* t, Val* aggr) const if ( IsError() ) return 0; - return op->InitVal(t, aggr); + const BroType* index_type = t->AsTableType()->Indices(); + TableType* tt = Type()->AsTableType(); + TableVal* tval = aggr ? aggr->AsTableVal() : new TableVal(tt, attrs); + const expr_list& exprs = op->AsListExpr()->Exprs(); + + loop_over_list(exprs, i) + { + Expr* e = exprs[i]; + Val* element = check_and_promote(e->Eval(0), index_type, 1); + + if ( ! element || ! tval->Assign(element, 0) ) + { + Error(fmt("initialization type mismatch in set"), e); + return 0; + } + + Unref(element); + } + + return tval; } void SetConstructorExpr::ExprDescribe(ODesc* d) const @@ -3536,14 +3562,14 @@ Val* VectorConstructorExpr::InitVal(const BroType* t, Val* aggr) const if ( IsError() ) return 0; - VectorVal* vec = aggr->AsVectorVal(); - const BroType* vt = vec->Type()->AsVectorType()->YieldType(); + VectorType* vt = Type()->AsVectorType(); + VectorVal* vec = aggr ? aggr->AsVectorVal() : new VectorVal(vt); const expr_list& exprs = op->AsListExpr()->Exprs(); loop_over_list(exprs, i) { Expr* e = exprs[i]; - Val* v = check_and_promote(e->Eval(0), vt, 1); + Val* v = check_and_promote(e->Eval(0), t->YieldType(), 1); if ( ! v || ! vec->Assign(i, v, e) ) { diff --git a/src/Val.cc b/src/Val.cc index 79fa8a0c69..0e30218b4b 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -3117,6 +3117,8 @@ void VectorVal::ValDescribe(ODesc* d) const Val* check_and_promote(Val* v, const BroType* t, int is_init) { + if ( ! v ) return 0; + BroType* vt = v->Type(); vt = flatten_type(vt); diff --git a/testing/btest/Baseline/language.table-init-container-ctors/output b/testing/btest/Baseline/language.table-init-container-ctors/output new file mode 100644 index 0000000000..feda20fea7 --- /dev/null +++ b/testing/btest/Baseline/language.table-init-container-ctors/output @@ -0,0 +1,42 @@ +table of set +{ +[13] = { +[bar, 2] , +[foo, 1] +}, +[5] = { +[bah, 3] , +[baz, 4] +} +} + +table of vector +{ +[13] = [1, 2], +[5] = [3, 4] +} + +table of table +{ +[13] = { +[bar, 2] = 2, +[foo, 1] = 1 +}, +[5] = { +[bah, 3] = 3, +[baz, 4] = 4 +} +} + +T +T +T +T +T +T +T +T +T +T +T +T diff --git a/testing/btest/language/table-init-container-ctors.bro b/testing/btest/language/table-init-container-ctors.bro new file mode 100644 index 0000000000..8882cb5640 --- /dev/null +++ b/testing/btest/language/table-init-container-ctors.bro @@ -0,0 +1,74 @@ +# @TEST-EXEC: bro -b %INPUT >output +# @TEST-EXEC: btest-diff output + +# The various container constructor expressions should work in table +# initialization lists. + +type set_yield: set[string, count]; +type vector_yield: vector of count; +type table_yield: table[string, count] of count; + +global lone_set_ctor: set_yield = set(["foo", 1], ["bar", 2]); +global lone_vector_ctor: vector_yield = vector(1, 2); +global lone_table_ctor: table_yield = table(["foo", 1] = 1, ["bar", 2] = 2); + +global table_of_set: table[count] of set_yield = { + [13] = lone_set_ctor, + [5] = set(["bah", 3], ["baz", 4]), +}; + +global table_of_vector: table[count] of vector_yield = { + [13] = lone_vector_ctor, + [5] = vector(3, 4), +}; + +global table_of_table: table[count] of table_yield = { + [13] = lone_table_ctor, + [5] = table(["bah", 3] = 3, ["baz", 4] = 4), +}; + +# Just copying the inline ctors used in the table initializer lists here +# for later comparisons. +global inline_set_ctor: set_yield = set(["bah", 3], ["baz", 4]); +global inline_vector_ctor: vector_yield = vector(3, 4); +global inline_table_ctor: table_yield = table(["bah", 3] = 3, ["baz", 4] = 4); + +function compare_set_yield(a: set_yield, b: set_yield) + { + local s: string; + local c: count; + for ( [s, c] in a ) + print [s, c] in b; + } + +function compare_vector_yield(a: vector_yield, b: vector_yield) + { + local c: count; + for ( c in a ) + print a[c] == b[c]; + } + +function compare_table_yield(a: table_yield, b: table_yield) + { + local s: string; + local c: count; + for ( [s, c] in a ) + print [s, c] in b && a[s, c] == b[s, c]; + } + +print "table of set"; +print table_of_set; +print ""; +print "table of vector"; +print table_of_vector; +print ""; +print "table of table"; +print table_of_table; +print ""; + +compare_set_yield(table_of_set[13], lone_set_ctor); +compare_set_yield(table_of_set[5], inline_set_ctor); +compare_vector_yield(table_of_vector[13], lone_vector_ctor); +compare_vector_yield(table_of_vector[5], inline_vector_ctor); +compare_table_yield(table_of_table[13], lone_table_ctor); +compare_table_yield(table_of_table[5], inline_table_ctor); From 00f7bbda96d32d3c323ad03559669e757e4d20c4 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 28 Nov 2012 14:53:36 -0600 Subject: [PATCH 16/23] Add test of record() constructor to table initializer unit test. --- .../output | 8 +++++++ .../language/table-init-container-ctors.bro | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/testing/btest/Baseline/language.table-init-container-ctors/output b/testing/btest/Baseline/language.table-init-container-ctors/output index feda20fea7..27774a660a 100644 --- a/testing/btest/Baseline/language.table-init-container-ctors/output +++ b/testing/btest/Baseline/language.table-init-container-ctors/output @@ -28,6 +28,14 @@ table of table } } +table of record +{ +[13] = [a=1, b=foo], +[5] = [a=2, b=bar] +} + +T +T T T T diff --git a/testing/btest/language/table-init-container-ctors.bro b/testing/btest/language/table-init-container-ctors.bro index 8882cb5640..4829f41688 100644 --- a/testing/btest/language/table-init-container-ctors.bro +++ b/testing/btest/language/table-init-container-ctors.bro @@ -7,10 +7,15 @@ type set_yield: set[string, count]; type vector_yield: vector of count; type table_yield: table[string, count] of count; +type record_yield: record { + a: count; + b: string; +}; global lone_set_ctor: set_yield = set(["foo", 1], ["bar", 2]); global lone_vector_ctor: vector_yield = vector(1, 2); global lone_table_ctor: table_yield = table(["foo", 1] = 1, ["bar", 2] = 2); +global lone_record_ctor: record_yield = record($a=1, $b="foo"); global table_of_set: table[count] of set_yield = { [13] = lone_set_ctor, @@ -27,11 +32,17 @@ global table_of_table: table[count] of table_yield = { [5] = table(["bah", 3] = 3, ["baz", 4] = 4), }; +global table_of_record: table[count] of record_yield = { + [13] = lone_record_ctor, + [5] = record($a=2, $b="bar"), +}; + # Just copying the inline ctors used in the table initializer lists here # for later comparisons. global inline_set_ctor: set_yield = set(["bah", 3], ["baz", 4]); global inline_vector_ctor: vector_yield = vector(3, 4); global inline_table_ctor: table_yield = table(["bah", 3] = 3, ["baz", 4] = 4); +global inline_record_ctor: record_yield = record($a=2, $b="bar"); function compare_set_yield(a: set_yield, b: set_yield) { @@ -56,6 +67,11 @@ function compare_table_yield(a: table_yield, b: table_yield) print [s, c] in b && a[s, c] == b[s, c]; } +function compare_record_yield(a: record_yield, b: record_yield) + { + print a$a == b$a && a$b == b$b; + } + print "table of set"; print table_of_set; print ""; @@ -65,6 +81,9 @@ print ""; print "table of table"; print table_of_table; print ""; +print "table of record"; +print table_of_record; +print ""; compare_set_yield(table_of_set[13], lone_set_ctor); compare_set_yield(table_of_set[5], inline_set_ctor); @@ -72,3 +91,5 @@ compare_vector_yield(table_of_vector[13], lone_vector_ctor); compare_vector_yield(table_of_vector[5], inline_vector_ctor); compare_table_yield(table_of_table[13], lone_table_ctor); compare_table_yield(table_of_table[5], inline_table_ctor); +compare_record_yield(table_of_record[13], lone_record_ctor); +compare_record_yield(table_of_record[5], inline_record_ctor); From 3b3b05fbbb87f938399f86cd9e75fe636ced421e Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 29 Nov 2012 10:07:38 -0600 Subject: [PATCH 17/23] Clarification in hook documentation. --- doc/scripts/builtins.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index cf62299783..0e474e9677 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -548,9 +548,9 @@ The Bro scripting language supports the following built-in types. print "not going to happen", s; } - Note that, although the first (forward) declaration of ``myhook`` as - a hook type isn't strictly required, when it is provided, the - argument types must match. + Note that the first (forward) declaration of ``myhook`` as a hook + type isn't strictly required. Argument types must match for all + hook handlers and any forward declaration of a given hook. To invoke immediate execution of all hook handler bodies, they can be called just like a function: From f7e07f5f097036bf80252b03e5e79408f3f243be Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 29 Nov 2012 15:44:03 -0600 Subject: [PATCH 18/23] Fix various bugs with table/set attributes. - Identifiers that are initialized with set()/table() constructor expressions now inherit attributes from the expression. Before, statements like const i: set[string] = set() &redef; associated the attribute with the set() constructor, but not the "i" identifier, preventing redefinition. Addresses #866. - Allow &default attribute to apply to tables initialized as empty (via either "{ }" or "table()") or if the expression supplied to it can evaluate to a type that's promotable to the same yield type as the table. --- src/Attr.cc | 10 ++ src/Expr.cc | 2 +- src/Expr.h | 4 + src/Var.cc | 28 +++++ .../Baseline/language.table-init-attrs/output | 91 ++++++++++++++ testing/btest/language/table-init-attrs.bro | 115 ++++++++++++++++++ 6 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 testing/btest/Baseline/language.table-init-attrs/output create mode 100644 testing/btest/language/table-init-attrs.bro diff --git a/src/Attr.cc b/src/Attr.cc index 6e0769c7b0..6cc582f053 100644 --- a/src/Attr.cc +++ b/src/Attr.cc @@ -260,6 +260,11 @@ void Attributes::CheckAttr(Attr* a) // Ok. break; + if ( type->Tag() == TYPE_TABLE && + type->AsTableType()->IsUnspecifiedTable() ) + // Ok. + break; + a->AttrExpr()->Error("&default value has inconsistent type", type); } @@ -290,6 +295,11 @@ void Attributes::CheckAttr(Attr* a) // Ok. break; + Expr* e = a->AttrExpr(); + if ( check_and_promote_expr(e, ytype) ) + // Ok. + break; + Error("&default value has inconsistent type 2"); } diff --git a/src/Expr.cc b/src/Expr.cc index 89680b9b5b..5b472ab6a6 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3445,7 +3445,7 @@ Val* SetConstructorExpr::Eval(Frame* f) const if ( IsError() ) return 0; - TableVal* aggr = new TableVal(type->AsTableType(), 0); + TableVal* aggr = new TableVal(type->AsTableType(), attrs); const expr_list& exprs = op->AsListExpr()->Exprs(); loop_over_list(exprs, i) diff --git a/src/Expr.h b/src/Expr.h index bd4824f8ee..afdf02c124 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -747,6 +747,8 @@ public: TableConstructorExpr(ListExpr* constructor_list, attr_list* attrs); ~TableConstructorExpr() { Unref(attrs); } + Attributes* Attrs() { return attrs; } + Val* Eval(Frame* f) const; protected: @@ -767,6 +769,8 @@ public: SetConstructorExpr(ListExpr* constructor_list, attr_list* attrs); ~SetConstructorExpr() { Unref(attrs); } + Attributes* Attrs() { return attrs; } + Val* Eval(Frame* f) const; protected: diff --git a/src/Var.cc b/src/Var.cc index 9c4fb5b978..3526c96550 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -109,6 +109,34 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, if ( attr ) id->AddAttrs(new Attributes(attr, t, false)); + if ( init ) + { + switch ( init->Tag() ) { + case EXPR_TABLE_CONSTRUCTOR: + { + TableConstructorExpr* ctor = (TableConstructorExpr*) init; + if ( ctor->Attrs() ) + { + ::Ref(ctor->Attrs()); + id->AddAttrs(ctor->Attrs()); + } + } + break; + case EXPR_SET_CONSTRUCTOR: + { + SetConstructorExpr* ctor = (SetConstructorExpr*) init; + if ( ctor->Attrs() ) + { + ::Ref(ctor->Attrs()); + id->AddAttrs(ctor->Attrs()); + } + } + break; + default: + break; + } + } + if ( id->FindAttr(ATTR_PERSISTENT) || id->FindAttr(ATTR_SYNCHRONIZED) ) { if ( dt == VAR_CONST ) diff --git a/testing/btest/Baseline/language.table-init-attrs/output b/testing/btest/Baseline/language.table-init-attrs/output new file mode 100644 index 0000000000..55df002ed0 --- /dev/null +++ b/testing/btest/Baseline/language.table-init-attrs/output @@ -0,0 +1,91 @@ +my_set_ctor_init +{ +test2, +test3, +test4, +test1 +} + +my_table_ctor_init +{ +[2] = test2, +[1] = test1, +[3] = test3 +} +nope + +my_set_init +{ +test2, +test3, +test4, +test1 +} + +my_table_init +{ +[2] = test2, +[4] = test4, +[1] = test1, +[3] = test3 +} +nope + +inception +{ +[0] = { +[13] = bar +} +} +{ +[13] = bar +} +bar +forty-two +{ + +} +we need to go deeper +{ +[0] = { +[13] = bar +} +} +{ +[13] = bar +} +bar +forty-two +{ + +} +we need to go deeper + +local table t1 +{ +[1] = foo +} +foo +nope + +local table t2 +{ +[1] = foo +} +foo +nope + +local table t3 +{ + +} +nope +nope + +local table t4 +{ + +} +nope +nope + diff --git a/testing/btest/language/table-init-attrs.bro b/testing/btest/language/table-init-attrs.bro new file mode 100644 index 0000000000..76d98b9fed --- /dev/null +++ b/testing/btest/language/table-init-attrs.bro @@ -0,0 +1,115 @@ +# @TEST-EXEC: bro -b %INPUT >output +# @TEST-EXEC: btest-diff output + +# set()/table() constructors are allowed to have attributes. When initializing +# an identifier, those attributes should also apply to it. + +const my_set_ctor_init: set[string] = set("test1") &redef; + +redef my_set_ctor_init += { + "test2", + "test3", +}; + +redef my_set_ctor_init += set("test4"); + +const my_table_ctor_init: table[count] of string = table([1] = "test1") &redef &default="nope"; + +redef my_table_ctor_init += { + [2] = "test2", + [3] = "test3", +}; + +# initializer list versions work the same way. + +const my_set_init: set[string] = { "test1" } &redef; + +redef my_set_init += { + "test2", + "test3", +}; + +redef my_set_init += set("test4"); + +const my_table_init: table[count] of string = { [1] = "test1" } &redef &default="nope"; + +redef my_table_init += { + [2] = "test2", + [3] = "test3", +}; + +redef my_table_init += table([4] = "test4"); + +# For tables that yield tables, we can apply attributes to the both other and +# inner tables... + +global inception_table: table[count] of table[count] of string = table( + [0] = table([13] = "bar") &default="forty-two" +) &default=table() &default="we need to go deeper"; + +global inception_table2: table[count] of table[count] of string = { + [0] = table([13] = "bar") &default="forty-two", +} &default=table() &default="we need to go deeper"; + +event bro_init() + { + print "my_set_ctor_init"; + print my_set_ctor_init; + print ""; + print "my_table_ctor_init"; + print my_table_ctor_init; + print my_table_ctor_init[5]; + print ""; + print "my_set_init"; + print my_set_init; + print ""; + print "my_table_init"; + print my_table_init; + print my_table_init[5]; + print ""; + print "inception"; + print inception_table; + print inception_table[0]; + print inception_table[0][13]; + print inception_table[0][42]; + print inception_table[1]; + print inception_table[1][2]; + print inception_table2; + print inception_table2[0]; + print inception_table2[0][13]; + print inception_table2[0][42]; + print inception_table2[1]; + print inception_table2[1][2]; + print ""; + + # just checking attributes on locals works, too + print "local table t1"; + local t1: table[count] of string = table([1] = "foo") &default="nope"; + print t1; + print t1[1]; + print t1[2]; + print ""; + + print "local table t2"; + local t2: table[count] of string = {[1] = "foo"} &default="nope"; + print t2; + print t2[1]; + print t2[2]; + print ""; + + # and for empty initializers... + print "local table t3"; + local t3: table[count] of string = table() &default="nope"; + print t3; + print t3[1]; + print t3[2]; + print ""; + + print "local table t4"; + local t4: table[count] of string = {} &default="nope"; + print t4; + print t4[1]; + print t4[2]; + print ""; + + } From 4e85fe0454c853ea6bab90064c45de32ae35efe4 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 30 Nov 2012 15:39:00 -0600 Subject: [PATCH 19/23] Change hook calls to only be allowed when preceded by "hook" keyword. --- doc/scripts/builtins.rst | 14 +++- src/Expr.cc | 9 +- src/Expr.h | 2 +- src/parse.y | 15 +++- testing/btest/Baseline/language.hook/out | 3 + .../Baseline/language.hook_calls/invalid.out | 10 +++ .../Baseline/language.hook_calls/valid.out | 42 ++++++++++ testing/btest/core/leaks/hook.bro | 14 ++-- testing/btest/language/hook.bro | 14 ++-- testing/btest/language/hook_calls.bro | 82 +++++++++++++++++++ 10 files changed, 188 insertions(+), 17 deletions(-) create mode 100644 testing/btest/Baseline/language.hook_calls/invalid.out create mode 100644 testing/btest/Baseline/language.hook_calls/valid.out create mode 100644 testing/btest/language/hook_calls.bro diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index 0e474e9677..322aafc2cf 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -553,13 +553,21 @@ The Bro scripting language supports the following built-in types. hook handlers and any forward declaration of a given hook. To invoke immediate execution of all hook handler bodies, they - can be called just like a function: + are called similarly to a function, except preceded by the ``hook`` + keyword: .. code:: bro - myhook("hi"); + hook myhook("hi"); - And the output would like like:: + or + + .. code:: bro + + if ( hook myhook("hi") ) + print "all handlers ran"; + + And the output would look like:: priority 10 myhook handler, hi break out of myhook handling, bye diff --git a/src/Expr.cc b/src/Expr.cc index a7075566aa..a910e0d2fb 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -4374,7 +4374,7 @@ bool InExpr::DoUnserialize(UnserialInfo* info) return true; } -CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args) +CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) : Expr(EXPR_CALL) { func = arg_func; @@ -4394,6 +4394,13 @@ CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args) return; } + if ( func_type->AsFuncType()->Flavor() == FUNC_FLAVOR_HOOK && ! in_hook ) + { + func->Error("hook cannot be called directly, use hook operator"); + SetError(); + return; + } + if ( ! func_type->MatchesIndex(args) ) SetError("argument type mismatch in function call"); else diff --git a/src/Expr.h b/src/Expr.h index c16cf86612..bd4824f8ee 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -959,7 +959,7 @@ protected: class CallExpr : public Expr { public: - CallExpr(Expr* func, ListExpr* args); + CallExpr(Expr* func, ListExpr* args, bool in_hook = false); ~CallExpr(); Expr* Func() const { return func; } diff --git a/src/parse.y b/src/parse.y index 39673cacc2..0385c1c4e1 100644 --- a/src/parse.y +++ b/src/parse.y @@ -2,7 +2,7 @@ // See the file "COPYING" in the main distribution directory for copyright. %} -%expect 87 +%expect 88 %token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY %token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF @@ -32,6 +32,7 @@ %token TOK_NO_TEST +%nonassoc TOK_HOOK %left ',' '|' %right '=' TOK_ADD_TO TOK_REMOVE_FROM %right '?' ':' @@ -118,6 +119,7 @@ extern const char* g_curr_debug_error; #define YYLTYPE yyltype +static int in_hook = 0; int in_init = 0; int in_record = 0; bool resolving_global_ID = false; @@ -515,7 +517,16 @@ expr: | expr '(' opt_expr_list ')' { set_location(@1, @4); - $$ = new CallExpr($1, $3); + $$ = new CallExpr($1, $3, in_hook > 0); + } + + | TOK_HOOK { ++in_hook; } expr + { + --in_hook; + set_location(@1, @3); + if ( $3->Tag() != EXPR_CALL ) + $3->Error("not a valid hook call expression"); + $$ = $3; } | expr TOK_HAS_FIELD TOK_ID diff --git a/testing/btest/Baseline/language.hook/out b/testing/btest/Baseline/language.hook/out index 18828ad15f..bef25193b8 100644 --- a/testing/btest/Baseline/language.hook/out +++ b/testing/btest/Baseline/language.hook/out @@ -8,6 +8,9 @@ T myhook4, 2 myhook4, 1 T +myhook4, 2 +myhook4, 1 +myhook4 all handlers ran myhook, &priority=10, [a=2, b=it works] myhook return F myhook return T diff --git a/testing/btest/Baseline/language.hook_calls/invalid.out b/testing/btest/Baseline/language.hook_calls/invalid.out new file mode 100644 index 0000000000..3412c1900e --- /dev/null +++ b/testing/btest/Baseline/language.hook_calls/invalid.out @@ -0,0 +1,10 @@ +error in ./invalid.bro, line 9: hook cannot be called directly, use hook operator (myhook) +warning in ./invalid.bro, line 9: expression value ignored (myhook(3)) +error in ./invalid.bro, line 10: hook cannot be called directly, use hook operator (myhook) +error in ./invalid.bro, line 11: hook cannot be called directly, use hook operator (myhook) +error in ./invalid.bro, line 12: not a valid hook call expression (2 + 2) +warning in ./invalid.bro, line 12: expression value ignored (2 + 2) +error in ./invalid.bro, line 13: not a valid hook call expression (2 + 2) +error in ./invalid.bro, line 15: hook cannot be called directly, use hook operator (h) +warning in ./invalid.bro, line 15: expression value ignored (h(3)) +error in ./invalid.bro, line 16: hook cannot be called directly, use hook operator (h) diff --git a/testing/btest/Baseline/language.hook_calls/valid.out b/testing/btest/Baseline/language.hook_calls/valid.out new file mode 100644 index 0000000000..c711115315 --- /dev/null +++ b/testing/btest/Baseline/language.hook_calls/valid.out @@ -0,0 +1,42 @@ +myhook(), 3 +other myhook(), 3 +myhook(), 3 +other myhook(), 3 +T +myhook(), 0 +F +----------- +indirect() +myhook(), 3 +other myhook(), 3 +indirect() +myhook(), 3 +other myhook(), 3 +T +----------- +really_indirect() +indirect() +myhook(), 3 +other myhook(), 3 +really_indirect() +indirect() +myhook(), 3 +other myhook(), 3 +T +----------- +myhook(), 3 +other myhook(), 3 +myhook(), 3 +other myhook(), 3 +T +myhook(), 3 +other myhook(), 3 +yes +myhook(), 0 +double yes +----------- +myhook(), 3 +other myhook(), 3 +myhook(), 3 +other myhook(), 3 +T diff --git a/testing/btest/core/leaks/hook.bro b/testing/btest/core/leaks/hook.bro index d9dcbff369..9234184317 100644 --- a/testing/btest/core/leaks/hook.bro +++ b/testing/btest/core/leaks/hook.bro @@ -81,16 +81,20 @@ event new_connection(c: connection) { print "new_connection", c$id; - print myhook([$a=1156, $b="hello world"]); + print hook myhook([$a=1156, $b="hello world"]); # A hook with no handlers is fine, it's just a no-op. - print myhook2("nope"); + print hook myhook2("nope"); - print myhook3(8); - print myhook4(); + print hook myhook3(8); + print hook myhook4(); + if ( hook myhook4() ) + { + print "myhook4 all handlers ran"; + } # A hook can be treated like other data types and doesn't have to be # invoked directly by name. local h = myhook; - print h([$a=2, $b="it works"]); + print hook h([$a=2, $b="it works"]); } diff --git a/testing/btest/language/hook.bro b/testing/btest/language/hook.bro index eedd2ff056..9c9ab30c18 100644 --- a/testing/btest/language/hook.bro +++ b/testing/btest/language/hook.bro @@ -74,16 +74,20 @@ hook myhook4() &priority=2 event bro_init() { - print myhook([$a=1156, $b="hello world"]); + print hook myhook([$a=1156, $b="hello world"]); # A hook with no handlers is fine, it's just a no-op. - print myhook2("nope"); + print hook myhook2("nope"); - print myhook3(8); - print myhook4(); + print hook myhook3(8); + print hook myhook4(); + if ( hook myhook4() ) + { + print "myhook4 all handlers ran"; + } # A hook can be treated like other data types and doesn't have to be # invoked directly by name. local h = myhook; - print h([$a=2, $b="it works"]); + print hook h([$a=2, $b="it works"]); } diff --git a/testing/btest/language/hook_calls.bro b/testing/btest/language/hook_calls.bro new file mode 100644 index 0000000000..41ef6f52ae --- /dev/null +++ b/testing/btest/language/hook_calls.bro @@ -0,0 +1,82 @@ +# @TEST-EXEC: bro -b valid.bro >valid.out +# @TEST-EXEC: btest-diff valid.out +# @TEST-EXEC-FAIL: bro -b invalid.bro > invalid.out 2>&1 +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff invalid.out + +# hook functions must be called using the "hook" keyword as an operator... + +@TEST-START-FILE valid.bro +hook myhook(i: count) + { + print "myhook()", i; + if ( i == 0 ) break; + } + +hook myhook(i: count) &priority=-1 + { + print "other myhook()", i; + } + +function indirect(): hook(i: count) + { + print "indirect()"; + return myhook; + } + +function really_indirect(): function(): hook(i: count) + { + print "really_indirect()"; + return indirect; + } + +global t: table[count] of hook(i: count) = { + [0] = myhook, +}; + +event bro_init() + { + hook myhook(3); + print hook myhook(3); + print hook myhook(0); + print "-----------"; + hook indirect()(3); + print hook indirect()(3); + print "-----------"; + hook really_indirect()()(3); + print hook really_indirect()()(3); + print "-----------"; + local h = t[0]; + hook h(3); + print hook h(3); + if ( hook h(3) ) + print "yes"; + if ( ! hook h(0) ) + print "double yes"; + print "-----------"; + hook t[0](3); + print hook t[0](3); + } + +@TEST-END-FILE + +@TEST-START-FILE invalid.bro +hook myhook(i: count) + { + print "myhook()", i; + if ( i == 0 ) break; + } + +event bro_init() + { + myhook(3); + print myhook(3); + print myhook(0); + hook 2+2; + print hook 2+2; + local h = myhook; + h(3); + if ( h(3) ) + print "hmm"; + print "done"; + } +@TEST-END-FILE From 95ffb1cf27a3833c723ff4193b87271139d63ee7 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 30 Nov 2012 17:44:36 -0600 Subject: [PATCH 20/23] Quick pass over unit tests, adding -b flag to bro so they run faster. Doing this made bifs/ ~3x faster and language/ ~2x faster. --- testing/btest/Baseline/bifs.strptime/.stdout | 2 -- testing/btest/Baseline/bifs.strptime/out | 3 +++ testing/btest/Baseline/bifs.strptime/reporter.log | 10 ---------- testing/btest/bifs/addr_count_conversion.bro | 2 +- testing/btest/bifs/addr_to_ptr_name.bro | 2 +- testing/btest/bifs/addr_version.bro | 2 +- testing/btest/bifs/all_set.bro | 2 +- testing/btest/bifs/analyzer_name.bro | 2 +- testing/btest/bifs/any_set.bro | 2 +- testing/btest/bifs/bro_version.bro | 2 +- testing/btest/bifs/byte_len.bro | 2 +- testing/btest/bifs/bytestring_to_double.bro | 2 +- testing/btest/bifs/bytestring_to_hexstr.bro | 2 +- testing/btest/bifs/capture_state_updates.bro | 2 +- testing/btest/bifs/cat.bro | 2 +- testing/btest/bifs/cat_string_array.bro | 2 +- testing/btest/bifs/checkpoint_state.bro | 2 +- testing/btest/bifs/clear_table.bro | 2 +- testing/btest/bifs/convert_for_pattern.bro | 2 +- testing/btest/bifs/count_to_addr.bro | 2 +- testing/btest/bifs/create_file.bro | 2 +- testing/btest/bifs/current_analyzer.bro | 2 +- testing/btest/bifs/current_time.bro | 2 +- testing/btest/bifs/edit.bro | 2 +- testing/btest/bifs/enable_raw_output.test | 2 +- testing/btest/bifs/entropy_test.bro | 2 +- testing/btest/bifs/escape_string.bro | 2 +- testing/btest/bifs/exit.bro | 2 +- testing/btest/bifs/file_mode.bro | 2 +- testing/btest/bifs/find_all.bro | 2 +- testing/btest/bifs/find_entropy.bro | 2 +- testing/btest/bifs/find_last.bro | 2 +- testing/btest/bifs/fmt.bro | 2 +- testing/btest/bifs/fmt_ftp_port.bro | 2 +- testing/btest/bifs/get_matcher_stats.bro | 11 ++++++++++- testing/btest/bifs/get_port_transport_proto.bro | 2 +- testing/btest/bifs/gethostname.bro | 2 +- testing/btest/bifs/getpid.bro | 2 +- testing/btest/bifs/getsetenv.bro | 2 +- testing/btest/bifs/global_ids.bro | 2 +- testing/btest/bifs/global_sizes.bro | 2 +- testing/btest/bifs/hexdump.bro | 2 +- testing/btest/bifs/identify_data.bro | 2 +- testing/btest/bifs/is_ascii.bro | 2 +- testing/btest/bifs/is_local_interface.bro | 2 +- testing/btest/bifs/is_port.bro | 2 +- testing/btest/bifs/join_string.bro | 2 +- testing/btest/bifs/length.bro | 2 +- testing/btest/bifs/lookup_ID.bro | 2 +- testing/btest/bifs/lowerupper.bro | 2 +- testing/btest/bifs/mask_addr.bro | 2 +- testing/btest/bifs/math.bro | 2 +- testing/btest/bifs/merge_pattern.bro | 2 +- testing/btest/bifs/netbios-functions.bro | 2 +- testing/btest/bifs/order.bro | 2 +- testing/btest/bifs/parse_ftp.bro | 2 +- testing/btest/bifs/piped_exec.bro | 2 +- testing/btest/bifs/ptr_name_to_addr.bro | 2 +- testing/btest/bifs/raw_bytes_to_v4_addr.bro | 2 +- testing/btest/bifs/reading_traces.bro | 2 +- testing/btest/bifs/record_type_to_vector.bro | 2 +- testing/btest/bifs/records_fields.bro | 2 +- testing/btest/bifs/remask_addr.bro | 2 +- testing/btest/bifs/resize.bro | 2 +- testing/btest/bifs/resource_usage.bro | 2 +- testing/btest/bifs/rotate_file.bro | 2 +- testing/btest/bifs/rotate_file_by_name.bro | 2 +- testing/btest/bifs/same_object.bro | 2 +- testing/btest/bifs/sort.bro | 2 +- testing/btest/bifs/sort_string_array.bro | 2 +- testing/btest/bifs/split.bro | 2 +- testing/btest/bifs/str_shell_escape.bro | 2 +- testing/btest/bifs/strcmp.bro | 2 +- testing/btest/bifs/strftime.bro | 2 +- testing/btest/bifs/string_fill.bro | 2 +- testing/btest/bifs/string_to_pattern.bro | 2 +- testing/btest/bifs/strip.bro | 2 +- testing/btest/bifs/strptime.bro | 7 +++---- testing/btest/bifs/strstr.bro | 2 +- testing/btest/bifs/sub.bro | 2 +- testing/btest/bifs/subst_string.bro | 2 +- testing/btest/bifs/system.bro | 2 +- testing/btest/bifs/system_env.bro | 2 +- testing/btest/bifs/to_count.bro | 2 +- testing/btest/bifs/to_double.bro | 2 +- testing/btest/bifs/to_int.bro | 2 +- testing/btest/bifs/to_interval.bro | 2 +- testing/btest/bifs/to_port.bro | 2 +- testing/btest/bifs/to_time.bro | 2 +- testing/btest/bifs/type_name.bro | 2 +- testing/btest/bifs/unique_id-rnd.bro | 4 ++-- testing/btest/bifs/unique_id.bro | 2 +- testing/btest/bifs/uuid_to_string.bro | 2 +- testing/btest/bifs/val_size.bro | 2 +- testing/btest/core/discarder.bro | 8 ++++---- testing/btest/core/ipv6_esp.test | 2 +- testing/btest/core/ipv6_zero_len_ah.test | 2 +- testing/btest/core/load-duplicates.bro | 10 +++++----- testing/btest/core/load-pkg.bro | 2 +- testing/btest/core/load-relative.bro | 2 +- testing/btest/core/load-unload.bro | 2 +- testing/btest/language/any.bro | 2 +- testing/btest/language/at-if.bro | 2 +- testing/btest/language/at-ifdef.bro | 2 +- testing/btest/language/at-ifndef.bro | 2 +- testing/btest/language/at-load.bro | 2 +- testing/btest/language/bool.bro | 2 +- testing/btest/language/conditional-expression.bro | 2 +- testing/btest/language/copy.bro | 2 +- testing/btest/language/count.bro | 2 +- testing/btest/language/cross-product-init.bro | 2 +- testing/btest/language/delete-field-set.bro | 2 +- testing/btest/language/delete-field.bro | 2 +- testing/btest/language/double.bro | 2 +- testing/btest/language/enum-scope.bro | 2 +- testing/btest/language/enum.bro | 2 +- testing/btest/language/event.bro | 2 +- testing/btest/language/file.bro | 2 +- testing/btest/language/for.bro | 2 +- testing/btest/language/function.bro | 2 +- testing/btest/language/if.bro | 2 +- testing/btest/language/int.bro | 2 +- testing/btest/language/interval.bro | 2 +- testing/btest/language/module.bro | 2 +- testing/btest/language/next-test.bro | 2 +- testing/btest/language/no-module.bro | 2 +- testing/btest/language/null-statement.bro | 2 +- testing/btest/language/pattern.bro | 2 +- testing/btest/language/port.bro | 2 +- testing/btest/language/precedence.bro | 2 +- testing/btest/language/raw_output_attr.test | 2 +- testing/btest/language/rec-comp-init.bro | 2 +- testing/btest/language/rec-nested-opt.bro | 2 +- testing/btest/language/rec-of-tbl.bro | 2 +- testing/btest/language/rec-table-default.bro | 2 +- testing/btest/language/record-extension.bro | 2 +- testing/btest/language/record-recursive-coercion.bro | 2 +- testing/btest/language/record-ref-assign.bro | 2 +- testing/btest/language/set-opt-record-index.bro | 2 +- testing/btest/language/set.bro | 2 +- testing/btest/language/short-circuit.bro | 2 +- testing/btest/language/sizeof.bro | 2 +- testing/btest/language/smith-waterman-test.bro | 2 +- testing/btest/language/string.bro | 2 +- testing/btest/language/strings.bro | 2 +- testing/btest/language/table-init.bro | 2 +- testing/btest/language/time.bro | 2 +- testing/btest/language/timeout.bro | 2 +- testing/btest/language/vector-coerce-expr.bro | 2 +- testing/btest/language/vector-list-init-records.bro | 2 +- testing/btest/language/vector.bro | 2 +- testing/btest/language/wrong-delete-field.bro | 2 +- testing/btest/language/wrong-record-extension.bro | 2 +- 153 files changed, 172 insertions(+), 173 deletions(-) delete mode 100644 testing/btest/Baseline/bifs.strptime/.stdout create mode 100644 testing/btest/Baseline/bifs.strptime/out delete mode 100644 testing/btest/Baseline/bifs.strptime/reporter.log diff --git a/testing/btest/Baseline/bifs.strptime/.stdout b/testing/btest/Baseline/bifs.strptime/.stdout deleted file mode 100644 index 179612d4c4..0000000000 --- a/testing/btest/Baseline/bifs.strptime/.stdout +++ /dev/null @@ -1,2 +0,0 @@ -1350604800.0 -0.0 diff --git a/testing/btest/Baseline/bifs.strptime/out b/testing/btest/Baseline/bifs.strptime/out new file mode 100644 index 0000000000..5fad7cd8e6 --- /dev/null +++ b/testing/btest/Baseline/bifs.strptime/out @@ -0,0 +1,3 @@ +warning: strptime conversion failed: fmt:%m d:1980-10-24 +1350604800.0 +0.0 diff --git a/testing/btest/Baseline/bifs.strptime/reporter.log b/testing/btest/Baseline/bifs.strptime/reporter.log deleted file mode 100644 index 367dbd63c1..0000000000 --- a/testing/btest/Baseline/bifs.strptime/reporter.log +++ /dev/null @@ -1,10 +0,0 @@ -#separator \x09 -#set_separator , -#empty_field (empty) -#unset_field - -#path reporter -#open 2012-10-19-06-06-36 -#fields ts level message location -#types time enum string string -0.000000 Reporter::WARNING strptime conversion failed: fmt:%m d:1980-10-24 (empty) -#close 2012-10-19-06-06-36 diff --git a/testing/btest/bifs/addr_count_conversion.bro b/testing/btest/bifs/addr_count_conversion.bro index 360994a8e5..fb87a0c6a3 100644 --- a/testing/btest/bifs/addr_count_conversion.bro +++ b/testing/btest/bifs/addr_count_conversion.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output global v: index_vec; diff --git a/testing/btest/bifs/addr_to_ptr_name.bro b/testing/btest/bifs/addr_to_ptr_name.bro index b9c831d061..ac2391cf9b 100644 --- a/testing/btest/bifs/addr_to_ptr_name.bro +++ b/testing/btest/bifs/addr_to_ptr_name.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output print addr_to_ptr_name([2607:f8b0:4009:802::1012]); diff --git a/testing/btest/bifs/addr_version.bro b/testing/btest/bifs/addr_version.bro index 3e0123ef42..bf96c0d1f3 100644 --- a/testing/btest/bifs/addr_version.bro +++ b/testing/btest/bifs/addr_version.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out print is_v4_addr(1.2.3.4); diff --git a/testing/btest/bifs/all_set.bro b/testing/btest/bifs/all_set.bro index 31544eb31e..67ae36622b 100644 --- a/testing/btest/bifs/all_set.bro +++ b/testing/btest/bifs/all_set.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/analyzer_name.bro b/testing/btest/bifs/analyzer_name.bro index 034344f5c4..9297d2ca27 100644 --- a/testing/btest/bifs/analyzer_name.bro +++ b/testing/btest/bifs/analyzer_name.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/any_set.bro b/testing/btest/bifs/any_set.bro index 5fe046cdf4..9f3f364556 100644 --- a/testing/btest/bifs/any_set.bro +++ b/testing/btest/bifs/any_set.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/bro_version.bro b/testing/btest/bifs/bro_version.bro index 7465cbc0f5..35975559a5 100644 --- a/testing/btest/bifs/bro_version.bro +++ b/testing/btest/bifs/bro_version.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/bifs/byte_len.bro b/testing/btest/bifs/byte_len.bro index 25191fd173..bd15b0c390 100644 --- a/testing/btest/bifs/byte_len.bro +++ b/testing/btest/bifs/byte_len.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/bytestring_to_double.bro b/testing/btest/bifs/bytestring_to_double.bro index cc0a3a69f0..78820b207c 100644 --- a/testing/btest/bifs/bytestring_to_double.bro +++ b/testing/btest/bifs/bytestring_to_double.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/bytestring_to_hexstr.bro b/testing/btest/bifs/bytestring_to_hexstr.bro index 976a4ccf71..4087047f40 100644 --- a/testing/btest/bifs/bytestring_to_hexstr.bro +++ b/testing/btest/bifs/bytestring_to_hexstr.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/capture_state_updates.bro b/testing/btest/bifs/capture_state_updates.bro index 3abfdffdc1..6a44e0f86f 100644 --- a/testing/btest/bifs/capture_state_updates.bro +++ b/testing/btest/bifs/capture_state_updates.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out # @TEST-EXEC: test -f testfile diff --git a/testing/btest/bifs/cat.bro b/testing/btest/bifs/cat.bro index b85b3af550..e923d5d066 100644 --- a/testing/btest/bifs/cat.bro +++ b/testing/btest/bifs/cat.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/cat_string_array.bro b/testing/btest/bifs/cat_string_array.bro index d2c2242411..e799f4b282 100644 --- a/testing/btest/bifs/cat_string_array.bro +++ b/testing/btest/bifs/cat_string_array.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/checkpoint_state.bro b/testing/btest/bifs/checkpoint_state.bro index 2a66bd1729..7a46516ba0 100644 --- a/testing/btest/bifs/checkpoint_state.bro +++ b/testing/btest/bifs/checkpoint_state.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT # @TEST-EXEC: test -f .state/state.bst event bro_init() diff --git a/testing/btest/bifs/clear_table.bro b/testing/btest/bifs/clear_table.bro index 94779285af..9485eba1f5 100644 --- a/testing/btest/bifs/clear_table.bro +++ b/testing/btest/bifs/clear_table.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT > out +# @TEST-EXEC: bro -b %INPUT > out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/convert_for_pattern.bro b/testing/btest/bifs/convert_for_pattern.bro index 11533cd49b..b99b010f97 100644 --- a/testing/btest/bifs/convert_for_pattern.bro +++ b/testing/btest/bifs/convert_for_pattern.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/count_to_addr.bro b/testing/btest/bifs/count_to_addr.bro index ffb2d975bf..993a701bc8 100644 --- a/testing/btest/bifs/count_to_addr.bro +++ b/testing/btest/bifs/count_to_addr.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/create_file.bro b/testing/btest/bifs/create_file.bro index 8f3d6cfdcd..af2cfb4979 100644 --- a/testing/btest/bifs/create_file.bro +++ b/testing/btest/bifs/create_file.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out # @TEST-EXEC: btest-diff testfile # @TEST-EXEC: btest-diff testfile2 diff --git a/testing/btest/bifs/current_analyzer.bro b/testing/btest/bifs/current_analyzer.bro index 45b495c046..e221d7aed0 100644 --- a/testing/btest/bifs/current_analyzer.bro +++ b/testing/btest/bifs/current_analyzer.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/bifs/current_time.bro b/testing/btest/bifs/current_time.bro index 5d16df396d..9d4899aa06 100644 --- a/testing/btest/bifs/current_time.bro +++ b/testing/btest/bifs/current_time.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/bifs/edit.bro b/testing/btest/bifs/edit.bro index c9a73d17f1..346c0bdbf7 100644 --- a/testing/btest/bifs/edit.bro +++ b/testing/btest/bifs/edit.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/enable_raw_output.test b/testing/btest/bifs/enable_raw_output.test index 92e0037a04..ebaff36c8f 100644 --- a/testing/btest/bifs/enable_raw_output.test +++ b/testing/btest/bifs/enable_raw_output.test @@ -1,7 +1,7 @@ # Files which enable raw output via the BiF shouldn't interpret NUL characters # in strings that are `print`ed to it. -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT # @TEST-EXEC: tr '\000' 'X' output # @TEST-EXEC: btest-diff output # @TEST-EXEC: cmp myfile hookfile diff --git a/testing/btest/bifs/entropy_test.bro b/testing/btest/bifs/entropy_test.bro index ca01c79ed7..8dc54e09b2 100644 --- a/testing/btest/bifs/entropy_test.bro +++ b/testing/btest/bifs/entropy_test.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/escape_string.bro b/testing/btest/bifs/escape_string.bro index 92b7b535d8..fd796497be 100644 --- a/testing/btest/bifs/escape_string.bro +++ b/testing/btest/bifs/escape_string.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/exit.bro b/testing/btest/bifs/exit.bro index e551144caa..b942a5e81c 100644 --- a/testing/btest/bifs/exit.bro +++ b/testing/btest/bifs/exit.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out || test $? -eq 7 +# @TEST-EXEC: bro -b %INPUT >out || test $? -eq 7 # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/file_mode.bro b/testing/btest/bifs/file_mode.bro index c63a2fa188..62bee05c6c 100644 --- a/testing/btest/bifs/file_mode.bro +++ b/testing/btest/bifs/file_mode.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/find_all.bro b/testing/btest/bifs/find_all.bro index edf3530c8a..4fe451a9d4 100644 --- a/testing/btest/bifs/find_all.bro +++ b/testing/btest/bifs/find_all.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/find_entropy.bro b/testing/btest/bifs/find_entropy.bro index 24f1c0ed84..2eb24fe118 100644 --- a/testing/btest/bifs/find_entropy.bro +++ b/testing/btest/bifs/find_entropy.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/find_last.bro b/testing/btest/bifs/find_last.bro index b1a567f73a..00ae2a874d 100644 --- a/testing/btest/bifs/find_last.bro +++ b/testing/btest/bifs/find_last.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/fmt.bro b/testing/btest/bifs/fmt.bro index 53b5f2235d..93607c2740 100644 --- a/testing/btest/bifs/fmt.bro +++ b/testing/btest/bifs/fmt.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out type color: enum { Red, Blue }; diff --git a/testing/btest/bifs/fmt_ftp_port.bro b/testing/btest/bifs/fmt_ftp_port.bro index 09ec5369e2..6a7b4d20c7 100644 --- a/testing/btest/bifs/fmt_ftp_port.bro +++ b/testing/btest/bifs/fmt_ftp_port.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/get_matcher_stats.bro b/testing/btest/bifs/get_matcher_stats.bro index baee49fe1e..eeaa8cb86a 100644 --- a/testing/btest/bifs/get_matcher_stats.bro +++ b/testing/btest/bifs/get_matcher_stats.bro @@ -1,5 +1,14 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b -s mysig %INPUT + +@TEST-START-FILE mysig.sig +signature my_ftp_client { + ip-proto == tcp + payload /(|.*[\n\r]) *[uU][sS][eE][rR] / + tcp-state originator + event "matched my_ftp_client" +} +@TEST-END-FILE event bro_init() { diff --git a/testing/btest/bifs/get_port_transport_proto.bro b/testing/btest/bifs/get_port_transport_proto.bro index c9b5e626ec..ae3c496d88 100644 --- a/testing/btest/bifs/get_port_transport_proto.bro +++ b/testing/btest/bifs/get_port_transport_proto.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/gethostname.bro b/testing/btest/bifs/gethostname.bro index 97af719745..1d760525cb 100644 --- a/testing/btest/bifs/gethostname.bro +++ b/testing/btest/bifs/gethostname.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/bifs/getpid.bro b/testing/btest/bifs/getpid.bro index 98edc19a44..1852b1287e 100644 --- a/testing/btest/bifs/getpid.bro +++ b/testing/btest/bifs/getpid.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/bifs/getsetenv.bro b/testing/btest/bifs/getsetenv.bro index b4ee9a0931..d217a14ea9 100644 --- a/testing/btest/bifs/getsetenv.bro +++ b/testing/btest/bifs/getsetenv.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: TESTBRO=testvalue bro %INPUT >out +# @TEST-EXEC: TESTBRO=testvalue bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/global_ids.bro b/testing/btest/bifs/global_ids.bro index 65f8944ed4..2dcb6e844d 100644 --- a/testing/btest/bifs/global_ids.bro +++ b/testing/btest/bifs/global_ids.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/global_sizes.bro b/testing/btest/bifs/global_sizes.bro index 4862db318b..4b0805172c 100644 --- a/testing/btest/bifs/global_sizes.bro +++ b/testing/btest/bifs/global_sizes.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/hexdump.bro b/testing/btest/bifs/hexdump.bro index 4c248efb77..1c86ce0db8 100644 --- a/testing/btest/bifs/hexdump.bro +++ b/testing/btest/bifs/hexdump.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/identify_data.bro b/testing/btest/bifs/identify_data.bro index 39f289d40b..68cac55c61 100644 --- a/testing/btest/bifs/identify_data.bro +++ b/testing/btest/bifs/identify_data.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT | sed 's/PNG image data/PNG image/g' >out +# @TEST-EXEC: bro -b %INPUT | sed 's/PNG image data/PNG image/g' >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/is_ascii.bro b/testing/btest/bifs/is_ascii.bro index 4d1daf96b4..fa2d39d2d8 100644 --- a/testing/btest/bifs/is_ascii.bro +++ b/testing/btest/bifs/is_ascii.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/is_local_interface.bro b/testing/btest/bifs/is_local_interface.bro index 8befdca385..ac21b04bd3 100644 --- a/testing/btest/bifs/is_local_interface.bro +++ b/testing/btest/bifs/is_local_interface.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/is_port.bro b/testing/btest/bifs/is_port.bro index fe2c3f7c35..2fe4964913 100644 --- a/testing/btest/bifs/is_port.bro +++ b/testing/btest/bifs/is_port.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/join_string.bro b/testing/btest/bifs/join_string.bro index 16222d6303..83917ef322 100644 --- a/testing/btest/bifs/join_string.bro +++ b/testing/btest/bifs/join_string.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/length.bro b/testing/btest/bifs/length.bro index 335223c124..ca82d7eab7 100644 --- a/testing/btest/bifs/length.bro +++ b/testing/btest/bifs/length.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT > out +# @TEST-EXEC: bro -b %INPUT > out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/lookup_ID.bro b/testing/btest/bifs/lookup_ID.bro index b8a29ef41f..e263c192da 100644 --- a/testing/btest/bifs/lookup_ID.bro +++ b/testing/btest/bifs/lookup_ID.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out global a = "bro test"; diff --git a/testing/btest/bifs/lowerupper.bro b/testing/btest/bifs/lowerupper.bro index fcfdcde319..77e6b1c9d1 100644 --- a/testing/btest/bifs/lowerupper.bro +++ b/testing/btest/bifs/lowerupper.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/mask_addr.bro b/testing/btest/bifs/mask_addr.bro index e1e3bccfb6..e69a55f590 100644 --- a/testing/btest/bifs/mask_addr.bro +++ b/testing/btest/bifs/mask_addr.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output const one_to_32: vector of count = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}; diff --git a/testing/btest/bifs/math.bro b/testing/btest/bifs/math.bro index 90aed5b4e6..84ace8620c 100644 --- a/testing/btest/bifs/math.bro +++ b/testing/btest/bifs/math.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/merge_pattern.bro b/testing/btest/bifs/merge_pattern.bro index b447f9a15b..de4a3afd6a 100644 --- a/testing/btest/bifs/merge_pattern.bro +++ b/testing/btest/bifs/merge_pattern.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/netbios-functions.bro b/testing/btest/bifs/netbios-functions.bro index 1fd033dd59..9b075e8729 100644 --- a/testing/btest/bifs/netbios-functions.bro +++ b/testing/btest/bifs/netbios-functions.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/order.bro b/testing/btest/bifs/order.bro index 333a8acac1..9e59caa827 100644 --- a/testing/btest/bifs/order.bro +++ b/testing/btest/bifs/order.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function myfunc1(a: addr, b: addr): int diff --git a/testing/btest/bifs/parse_ftp.bro b/testing/btest/bifs/parse_ftp.bro index ffdc941b4b..a8993fa6e0 100644 --- a/testing/btest/bifs/parse_ftp.bro +++ b/testing/btest/bifs/parse_ftp.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/piped_exec.bro b/testing/btest/bifs/piped_exec.bro index 3a76eba8f5..70f8d70523 100644 --- a/testing/btest/bifs/piped_exec.bro +++ b/testing/btest/bifs/piped_exec.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output # @TEST-EXEC: btest-diff test.txt diff --git a/testing/btest/bifs/ptr_name_to_addr.bro b/testing/btest/bifs/ptr_name_to_addr.bro index 89679ba57a..d1a7878e3d 100644 --- a/testing/btest/bifs/ptr_name_to_addr.bro +++ b/testing/btest/bifs/ptr_name_to_addr.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output global v6 = ptr_name_to_addr("2.1.0.1.0.0.0.0.0.0.0.0.0.0.0.0.2.0.8.0.9.0.0.4.0.b.8.f.7.0.6.2.ip6.arpa"); diff --git a/testing/btest/bifs/raw_bytes_to_v4_addr.bro b/testing/btest/bifs/raw_bytes_to_v4_addr.bro index 754580a5b0..bd685216ef 100644 --- a/testing/btest/bifs/raw_bytes_to_v4_addr.bro +++ b/testing/btest/bifs/raw_bytes_to_v4_addr.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/reading_traces.bro b/testing/btest/bifs/reading_traces.bro index fc83c50ccb..46ad04c25f 100644 --- a/testing/btest/bifs/reading_traces.bro +++ b/testing/btest/bifs/reading_traces.bro @@ -1,5 +1,5 @@ -# @TEST-EXEC: bro %INPUT >out1 +# @TEST-EXEC: bro -b %INPUT >out1 # @TEST-EXEC: btest-diff out1 # @TEST-EXEC: bro -r $TRACES/web.trace %INPUT >out2 # @TEST-EXEC: btest-diff out2 diff --git a/testing/btest/bifs/record_type_to_vector.bro b/testing/btest/bifs/record_type_to_vector.bro index 18ddf35022..9795ce886b 100644 --- a/testing/btest/bifs/record_type_to_vector.bro +++ b/testing/btest/bifs/record_type_to_vector.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out type myrecord: record { diff --git a/testing/btest/bifs/records_fields.bro b/testing/btest/bifs/records_fields.bro index 4f8cc0538a..ccaf5a719d 100644 --- a/testing/btest/bifs/records_fields.bro +++ b/testing/btest/bifs/records_fields.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out type r: record { diff --git a/testing/btest/bifs/remask_addr.bro b/testing/btest/bifs/remask_addr.bro index d387667b6a..7b7e89c018 100644 --- a/testing/btest/bifs/remask_addr.bro +++ b/testing/btest/bifs/remask_addr.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output const one_to_32: vector of count = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}; diff --git a/testing/btest/bifs/resize.bro b/testing/btest/bifs/resize.bro index 37e4ac38d9..f4067f31c7 100644 --- a/testing/btest/bifs/resize.bro +++ b/testing/btest/bifs/resize.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/resource_usage.bro b/testing/btest/bifs/resource_usage.bro index 35f5b020d6..5cf3f0f962 100644 --- a/testing/btest/bifs/resource_usage.bro +++ b/testing/btest/bifs/resource_usage.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/bifs/rotate_file.bro b/testing/btest/bifs/rotate_file.bro index 7132b0aaa8..a6109ff677 100644 --- a/testing/btest/bifs/rotate_file.bro +++ b/testing/btest/bifs/rotate_file.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/rotate_file_by_name.bro b/testing/btest/bifs/rotate_file_by_name.bro index 952b09aff3..f647edefe2 100644 --- a/testing/btest/bifs/rotate_file_by_name.bro +++ b/testing/btest/bifs/rotate_file_by_name.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/same_object.bro b/testing/btest/bifs/same_object.bro index eee8b1621d..dddfd80d3d 100644 --- a/testing/btest/bifs/same_object.bro +++ b/testing/btest/bifs/same_object.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/sort.bro b/testing/btest/bifs/sort.bro index 14aa286021..7b4ac9ba63 100644 --- a/testing/btest/bifs/sort.bro +++ b/testing/btest/bifs/sort.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function myfunc1(a: addr, b: addr): int diff --git a/testing/btest/bifs/sort_string_array.bro b/testing/btest/bifs/sort_string_array.bro index 23c4f55848..1916f93d0c 100644 --- a/testing/btest/bifs/sort_string_array.bro +++ b/testing/btest/bifs/sort_string_array.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/split.bro b/testing/btest/bifs/split.bro index fc1b5e96a0..4fd994ce41 100644 --- a/testing/btest/bifs/split.bro +++ b/testing/btest/bifs/split.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/str_shell_escape.bro b/testing/btest/bifs/str_shell_escape.bro index a71cb4dcf6..e631458bc1 100644 --- a/testing/btest/bifs/str_shell_escape.bro +++ b/testing/btest/bifs/str_shell_escape.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/strcmp.bro b/testing/btest/bifs/strcmp.bro index af46c7fa96..92d0430f1d 100644 --- a/testing/btest/bifs/strcmp.bro +++ b/testing/btest/bifs/strcmp.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/strftime.bro b/testing/btest/bifs/strftime.bro index 31f9538632..3d9e388c90 100644 --- a/testing/btest/bifs/strftime.bro +++ b/testing/btest/bifs/strftime.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/string_fill.bro b/testing/btest/bifs/string_fill.bro index c47f1916cc..0968215cc0 100644 --- a/testing/btest/bifs/string_fill.bro +++ b/testing/btest/bifs/string_fill.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/string_to_pattern.bro b/testing/btest/bifs/string_to_pattern.bro index 5164c4576f..4bd04bbcea 100644 --- a/testing/btest/bifs/string_to_pattern.bro +++ b/testing/btest/bifs/string_to_pattern.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/strip.bro b/testing/btest/bifs/strip.bro index de6601b83c..e508f20e3d 100644 --- a/testing/btest/bifs/strip.bro +++ b/testing/btest/bifs/strip.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/strptime.bro b/testing/btest/bifs/strptime.bro index 7a58989679..215299b300 100644 --- a/testing/btest/bifs/strptime.bro +++ b/testing/btest/bifs/strptime.bro @@ -1,10 +1,9 @@ # -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout -# @TEST-EXEC: btest-diff reporter.log +# @TEST-EXEC: bro -b %INPUT >out 2>&1 +# @TEST-EXEC: btest-diff out event bro_init() { print strptime("%Y-%m-%d", "2012-10-19"); print strptime("%m", "1980-10-24"); - } \ No newline at end of file + } diff --git a/testing/btest/bifs/strstr.bro b/testing/btest/bifs/strstr.bro index 58f79d593b..40cd8aa5fd 100644 --- a/testing/btest/bifs/strstr.bro +++ b/testing/btest/bifs/strstr.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/sub.bro b/testing/btest/bifs/sub.bro index f6a956f26a..773530ac74 100644 --- a/testing/btest/bifs/sub.bro +++ b/testing/btest/bifs/sub.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/subst_string.bro b/testing/btest/bifs/subst_string.bro index 81a3f89424..6ebed72321 100644 --- a/testing/btest/bifs/subst_string.bro +++ b/testing/btest/bifs/subst_string.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/system.bro b/testing/btest/bifs/system.bro index ab2642319c..bd27fc3db5 100644 --- a/testing/btest/bifs/system.bro +++ b/testing/btest/bifs/system.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/system_env.bro b/testing/btest/bifs/system_env.bro index 23928e9b10..cfe4e7dd2a 100644 --- a/testing/btest/bifs/system_env.bro +++ b/testing/btest/bifs/system_env.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT # @TEST-EXEC: btest-diff testfile event bro_init() diff --git a/testing/btest/bifs/to_count.bro b/testing/btest/bifs/to_count.bro index c1fe72ce52..33754117d4 100644 --- a/testing/btest/bifs/to_count.bro +++ b/testing/btest/bifs/to_count.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/to_double.bro b/testing/btest/bifs/to_double.bro index f13d34f69a..b6fb9917a7 100644 --- a/testing/btest/bifs/to_double.bro +++ b/testing/btest/bifs/to_double.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/to_int.bro b/testing/btest/bifs/to_int.bro index 9d108a9da7..0562209cd0 100644 --- a/testing/btest/bifs/to_int.bro +++ b/testing/btest/bifs/to_int.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/to_interval.bro b/testing/btest/bifs/to_interval.bro index 8fded315d2..71d73fed62 100644 --- a/testing/btest/bifs/to_interval.bro +++ b/testing/btest/bifs/to_interval.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/to_port.bro b/testing/btest/bifs/to_port.bro index 382bf5d333..0dfecac43e 100644 --- a/testing/btest/bifs/to_port.bro +++ b/testing/btest/bifs/to_port.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/to_time.bro b/testing/btest/bifs/to_time.bro index 97b109e647..d5a81b0934 100644 --- a/testing/btest/bifs/to_time.bro +++ b/testing/btest/bifs/to_time.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/type_name.bro b/testing/btest/bifs/type_name.bro index 3ec13fb27d..f331fe6aa9 100644 --- a/testing/btest/bifs/type_name.bro +++ b/testing/btest/bifs/type_name.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out type color: enum { Red, Blue }; diff --git a/testing/btest/bifs/unique_id-rnd.bro b/testing/btest/bifs/unique_id-rnd.bro index 4188725373..02be9fcb92 100644 --- a/testing/btest/bifs/unique_id-rnd.bro +++ b/testing/btest/bifs/unique_id-rnd.bro @@ -1,6 +1,6 @@ # -# @TEST-EXEC: BRO_SEED_FILE= bro %INPUT >out -# @TEST-EXEC: BRO_SEED_FILE= bro %INPUT >>out +# @TEST-EXEC: BRO_SEED_FILE= bro -b %INPUT >out +# @TEST-EXEC: BRO_SEED_FILE= bro -b %INPUT >>out # @TEST-EXEC: cat out | sort | uniq | wc -l | sed 's/ //g' >count # @TEST-EXEC: btest-diff count diff --git a/testing/btest/bifs/unique_id.bro b/testing/btest/bifs/unique_id.bro index 097f5d490d..d87c757f3f 100644 --- a/testing/btest/bifs/unique_id.bro +++ b/testing/btest/bifs/unique_id.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out print unique_id("A-"); diff --git a/testing/btest/bifs/uuid_to_string.bro b/testing/btest/bifs/uuid_to_string.bro index a64e81d783..dc84f349fa 100644 --- a/testing/btest/bifs/uuid_to_string.bro +++ b/testing/btest/bifs/uuid_to_string.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out event bro_init() diff --git a/testing/btest/bifs/val_size.bro b/testing/btest/bifs/val_size.bro index 5b2e535c5c..57b512b776 100644 --- a/testing/btest/bifs/val_size.bro +++ b/testing/btest/bifs/val_size.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT event bro_init() { diff --git a/testing/btest/core/discarder.bro b/testing/btest/core/discarder.bro index 0c87eece18..9e8f5e7a2f 100644 --- a/testing/btest/core/discarder.bro +++ b/testing/btest/core/discarder.bro @@ -1,7 +1,7 @@ -# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-ip.bro >output -# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-tcp.bro >>output -# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-udp.bro >>output -# @TEST-EXEC: bro -C -r $TRACES/icmp/icmp-destunreach-udp.pcap discarder-icmp.bro >>output +# @TEST-EXEC: bro -b -C -r $TRACES/wikipedia.trace discarder-ip.bro >output +# @TEST-EXEC: bro -b -C -r $TRACES/wikipedia.trace discarder-tcp.bro >>output +# @TEST-EXEC: bro -b -C -r $TRACES/wikipedia.trace discarder-udp.bro >>output +# @TEST-EXEC: bro -b -C -r $TRACES/icmp/icmp-destunreach-udp.pcap discarder-icmp.bro >>output # @TEST-EXEC: btest-diff output @TEST-START-FILE discarder-ip.bro diff --git a/testing/btest/core/ipv6_esp.test b/testing/btest/core/ipv6_esp.test index 8744df0036..508a4597f2 100644 --- a/testing/btest/core/ipv6_esp.test +++ b/testing/btest/core/ipv6_esp.test @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro -r $TRACES/ip6_esp.trace %INPUT >output +# @TEST-EXEC: bro -b -r $TRACES/ip6_esp.trace %INPUT >output # @TEST-EXEC: btest-diff output # Just check that the event is raised correctly for a packet containing diff --git a/testing/btest/core/ipv6_zero_len_ah.test b/testing/btest/core/ipv6_zero_len_ah.test index dc3acf8443..014ba7b3cc 100644 --- a/testing/btest/core/ipv6_zero_len_ah.test +++ b/testing/btest/core/ipv6_zero_len_ah.test @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro -r $TRACES/ipv6_zero_len_ah.trace %INPUT >output +# @TEST-EXEC: bro -b -r $TRACES/ipv6_zero_len_ah.trace %INPUT >output # @TEST-EXEC: btest-diff output # Shouldn't crash, but we also won't have seq and data fields set of the ip6_ah diff --git a/testing/btest/core/load-duplicates.bro b/testing/btest/core/load-duplicates.bro index e5dd365838..8c86fbc272 100644 --- a/testing/btest/core/load-duplicates.bro +++ b/testing/btest/core/load-duplicates.bro @@ -3,11 +3,11 @@ # @TEST-EXEC: mkdir -p foo/bar # @TEST-EXEC: echo "@load bar/test" >loader.bro # @TEST-EXEC: cp %INPUT foo/bar/test.bro -# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro misc/loaded-scripts loader bar/test -# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro misc/loaded-scripts loader bar/test.bro -# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro misc/loaded-scripts loader foo/bar/test -# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro misc/loaded-scripts loader foo/bar/test.bro -# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro misc/loaded-scripts loader `pwd`/foo/bar/test.bro +# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro -b misc/loaded-scripts loader bar/test +# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro -b misc/loaded-scripts loader bar/test.bro +# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro -b misc/loaded-scripts loader foo/bar/test +# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro -b misc/loaded-scripts loader foo/bar/test.bro +# @TEST-EXEC: BROPATH=$BROPATH:.:./foo bro -b misc/loaded-scripts loader `pwd`/foo/bar/test.bro type Test: enum { TEST, diff --git a/testing/btest/core/load-pkg.bro b/testing/btest/core/load-pkg.bro index 26e190a14c..e6671e038d 100644 --- a/testing/btest/core/load-pkg.bro +++ b/testing/btest/core/load-pkg.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro foo >output +# @TEST-EXEC: bro -b foo >output # @TEST-EXEC: btest-diff output @TEST-START-FILE foo/__load__.bro diff --git a/testing/btest/core/load-relative.bro b/testing/btest/core/load-relative.bro index 4050150d93..3bd082cf8a 100644 --- a/testing/btest/core/load-relative.bro +++ b/testing/btest/core/load-relative.bro @@ -1,6 +1,6 @@ # A test of relative-path-based @load'ing -# @TEST-EXEC: bro foo/foo >output +# @TEST-EXEC: bro -b foo/foo >output # @TEST-EXEC: btest-diff output @TEST-START-FILE foo/foo.bro diff --git a/testing/btest/core/load-unload.bro b/testing/btest/core/load-unload.bro index f76e9e337d..6525a8e8ea 100644 --- a/testing/btest/core/load-unload.bro +++ b/testing/btest/core/load-unload.bro @@ -1,6 +1,6 @@ # This tests the @unload directive # -# @TEST-EXEC: bro %INPUT misc/loaded-scripts dontloadmebro > output +# @TEST-EXEC: bro -b %INPUT misc/loaded-scripts dontloadmebro > output # @TEST-EXEC: btest-diff output # @TEST-EXEC: grep -q dontloadmebro loaded_scripts.log && exit 1 || exit 0 diff --git a/testing/btest/language/any.bro b/testing/btest/language/any.bro index 7437ee9851..fca23f6db8 100644 --- a/testing/btest/language/any.bro +++ b/testing/btest/language/any.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/at-if.bro b/testing/btest/language/at-if.bro index 979ed0bb9a..0a3e87adfa 100644 --- a/testing/btest/language/at-if.bro +++ b/testing/btest/language/at-if.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/at-ifdef.bro b/testing/btest/language/at-ifdef.bro index c30236f204..e7bb961833 100644 --- a/testing/btest/language/at-ifdef.bro +++ b/testing/btest/language/at-ifdef.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/at-ifndef.bro b/testing/btest/language/at-ifndef.bro index c98287590f..8bff0c456b 100644 --- a/testing/btest/language/at-ifndef.bro +++ b/testing/btest/language/at-ifndef.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/at-load.bro b/testing/btest/language/at-load.bro index b51594be16..7427cd639a 100644 --- a/testing/btest/language/at-load.bro +++ b/testing/btest/language/at-load.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out # In this script, we try to access each object defined in a "@load"ed script diff --git a/testing/btest/language/bool.bro b/testing/btest/language/bool.bro index b75343025f..8a1404459c 100644 --- a/testing/btest/language/bool.bro +++ b/testing/btest/language/bool.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/conditional-expression.bro b/testing/btest/language/conditional-expression.bro index 74648b6ce8..ea0acf009f 100644 --- a/testing/btest/language/conditional-expression.bro +++ b/testing/btest/language/conditional-expression.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/copy.bro b/testing/btest/language/copy.bro index 6740a080c7..3ddbc15e23 100644 --- a/testing/btest/language/copy.bro +++ b/testing/btest/language/copy.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/count.bro b/testing/btest/language/count.bro index d6dcf5a97e..b0972e29fa 100644 --- a/testing/btest/language/count.bro +++ b/testing/btest/language/count.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/cross-product-init.bro b/testing/btest/language/cross-product-init.bro index c12f9eb0bd..8cb9c48367 100644 --- a/testing/btest/language/cross-product-init.bro +++ b/testing/btest/language/cross-product-init.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output global my_subs = { 1.2.3.4/19, 5.6.7.8/21 }; diff --git a/testing/btest/language/delete-field-set.bro b/testing/btest/language/delete-field-set.bro index ad7cf6e9fb..1f1c5b0c27 100644 --- a/testing/btest/language/delete-field-set.bro +++ b/testing/btest/language/delete-field-set.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type FooBar: record { diff --git a/testing/btest/language/delete-field.bro b/testing/btest/language/delete-field.bro index 477466b76a..99136ff2b9 100644 --- a/testing/btest/language/delete-field.bro +++ b/testing/btest/language/delete-field.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type X: record { diff --git a/testing/btest/language/double.bro b/testing/btest/language/double.bro index 62ca768e22..f85b216828 100644 --- a/testing/btest/language/double.bro +++ b/testing/btest/language/double.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/enum-scope.bro b/testing/btest/language/enum-scope.bro index c8667bfada..82e7c7fd7c 100644 --- a/testing/btest/language/enum-scope.bro +++ b/testing/btest/language/enum-scope.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type foo: enum { a, b } &redef; diff --git a/testing/btest/language/enum.bro b/testing/btest/language/enum.bro index 5cafb323a6..6de7d345da 100644 --- a/testing/btest/language/enum.bro +++ b/testing/btest/language/enum.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/event.bro b/testing/btest/language/event.bro index 1ea5c7b6d8..e251a3e579 100644 --- a/testing/btest/language/event.bro +++ b/testing/btest/language/event.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out diff --git a/testing/btest/language/file.bro b/testing/btest/language/file.bro index 1f631eb4fe..47430b6813 100644 --- a/testing/btest/language/file.bro +++ b/testing/btest/language/file.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT # @TEST-EXEC: btest-diff out1 # @TEST-EXEC: btest-diff out2 diff --git a/testing/btest/language/for.bro b/testing/btest/language/for.bro index f10ef0eb1b..eb99a2705d 100644 --- a/testing/btest/language/for.bro +++ b/testing/btest/language/for.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/function.bro b/testing/btest/language/function.bro index 13efbb91f8..ab60c4fa62 100644 --- a/testing/btest/language/function.bro +++ b/testing/btest/language/function.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/if.bro b/testing/btest/language/if.bro index e9acea865f..785030a012 100644 --- a/testing/btest/language/if.bro +++ b/testing/btest/language/if.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/int.bro b/testing/btest/language/int.bro index 5cfa1620bd..f511d82bbb 100644 --- a/testing/btest/language/int.bro +++ b/testing/btest/language/int.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/interval.bro b/testing/btest/language/interval.bro index 66d44206d3..660683f5ca 100644 --- a/testing/btest/language/interval.bro +++ b/testing/btest/language/interval.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/module.bro b/testing/btest/language/module.bro index 4c70546406..3278697a8d 100644 --- a/testing/btest/language/module.bro +++ b/testing/btest/language/module.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT secondtestfile >out +# @TEST-EXEC: bro -b %INPUT secondtestfile >out # @TEST-EXEC: btest-diff out # In this source file, we define a module and export some objects diff --git a/testing/btest/language/next-test.bro b/testing/btest/language/next-test.bro index 7e9626a62c..d46ad187c4 100644 --- a/testing/btest/language/next-test.bro +++ b/testing/btest/language/next-test.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output # This script tests "next" being called during the last iteration of a diff --git a/testing/btest/language/no-module.bro b/testing/btest/language/no-module.bro index eadce66c18..24795df0fb 100644 --- a/testing/btest/language/no-module.bro +++ b/testing/btest/language/no-module.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT secondtestfile >out +# @TEST-EXEC: bro -b %INPUT secondtestfile >out # @TEST-EXEC: btest-diff out # This is the same test as "module.bro", but here we omit the module definition diff --git a/testing/btest/language/null-statement.bro b/testing/btest/language/null-statement.bro index 420ebd8a6c..20c70f4876 100644 --- a/testing/btest/language/null-statement.bro +++ b/testing/btest/language/null-statement.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out diff --git a/testing/btest/language/pattern.bro b/testing/btest/language/pattern.bro index ec50dc66fe..b904fe8737 100644 --- a/testing/btest/language/pattern.bro +++ b/testing/btest/language/pattern.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/port.bro b/testing/btest/language/port.bro index 1874e1dca3..a9c7fd33e7 100644 --- a/testing/btest/language/port.bro +++ b/testing/btest/language/port.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/precedence.bro b/testing/btest/language/precedence.bro index da8fef311c..27fc1e024a 100644 --- a/testing/btest/language/precedence.bro +++ b/testing/btest/language/precedence.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/raw_output_attr.test b/testing/btest/language/raw_output_attr.test index 22e565e4b4..8bcd479fbf 100644 --- a/testing/btest/language/raw_output_attr.test +++ b/testing/btest/language/raw_output_attr.test @@ -1,7 +1,7 @@ # Files with the &raw_output attribute shouldn't interpret NUL characters # in strings that are `print`ed to it. -# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: bro -b %INPUT # @TEST-EXEC: tr '\000' 'X' output # @TEST-EXEC: btest-diff output # @TEST-EXEC: cmp myfile hookfile diff --git a/testing/btest/language/rec-comp-init.bro b/testing/btest/language/rec-comp-init.bro index 598c0cf3bd..c65ef69097 100644 --- a/testing/btest/language/rec-comp-init.bro +++ b/testing/btest/language/rec-comp-init.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output # Make sure composit types in records are initialized. diff --git a/testing/btest/language/rec-nested-opt.bro b/testing/btest/language/rec-nested-opt.bro index ab1a64dffd..3b4a478f6b 100644 --- a/testing/btest/language/rec-nested-opt.bro +++ b/testing/btest/language/rec-nested-opt.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type Version: record { diff --git a/testing/btest/language/rec-of-tbl.bro b/testing/btest/language/rec-of-tbl.bro index 59d770bb30..8d2c9ab0e0 100644 --- a/testing/btest/language/rec-of-tbl.bro +++ b/testing/btest/language/rec-of-tbl.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type x: record { diff --git a/testing/btest/language/rec-table-default.bro b/testing/btest/language/rec-table-default.bro index ee4a0e25ee..27e0043dc3 100644 --- a/testing/btest/language/rec-table-default.bro +++ b/testing/btest/language/rec-table-default.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type X: record { diff --git a/testing/btest/language/record-extension.bro b/testing/btest/language/record-extension.bro index 21b704ca7a..78ef929a86 100644 --- a/testing/btest/language/record-extension.bro +++ b/testing/btest/language/record-extension.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output type Foo: record { diff --git a/testing/btest/language/record-recursive-coercion.bro b/testing/btest/language/record-recursive-coercion.bro index ad9e41bd3a..0eb24a70d9 100644 --- a/testing/btest/language/record-recursive-coercion.bro +++ b/testing/btest/language/record-recursive-coercion.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output type Version: record { diff --git a/testing/btest/language/record-ref-assign.bro b/testing/btest/language/record-ref-assign.bro index f71bc3890c..a9539ab716 100644 --- a/testing/btest/language/record-ref-assign.bro +++ b/testing/btest/language/record-ref-assign.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output type State: record { diff --git a/testing/btest/language/set-opt-record-index.bro b/testing/btest/language/set-opt-record-index.bro index 18ec963809..d42de8b041 100644 --- a/testing/btest/language/set-opt-record-index.bro +++ b/testing/btest/language/set-opt-record-index.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output # Make sure a set can be indexed with a record that has optional fields diff --git a/testing/btest/language/set.bro b/testing/btest/language/set.bro index 5e56e3b9b8..d1eef7e6f0 100644 --- a/testing/btest/language/set.bro +++ b/testing/btest/language/set.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/short-circuit.bro b/testing/btest/language/short-circuit.bro index f0ba585cea..598ac8da35 100644 --- a/testing/btest/language/short-circuit.bro +++ b/testing/btest/language/short-circuit.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/sizeof.bro b/testing/btest/language/sizeof.bro index 99d7b51ce8..8b29e119bd 100644 --- a/testing/btest/language/sizeof.bro +++ b/testing/btest/language/sizeof.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output # Demo policy for the sizeof operator "|x|". diff --git a/testing/btest/language/smith-waterman-test.bro b/testing/btest/language/smith-waterman-test.bro index 50f5c1dae1..2113d88e24 100644 --- a/testing/btest/language/smith-waterman-test.bro +++ b/testing/btest/language/smith-waterman-test.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output global params: sw_params = [ $min_strlen = 2, $sw_variant = 0 ]; diff --git a/testing/btest/language/string.bro b/testing/btest/language/string.bro index 3b9137cda5..abaa556b26 100644 --- a/testing/btest/language/string.bro +++ b/testing/btest/language/string.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/strings.bro b/testing/btest/language/strings.bro index 8e9eef43bf..f601797978 100644 --- a/testing/btest/language/strings.bro +++ b/testing/btest/language/strings.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output # Demo policy for string functions diff --git a/testing/btest/language/table-init.bro b/testing/btest/language/table-init.bro index 5df682c5d2..7419a50879 100644 --- a/testing/btest/language/table-init.bro +++ b/testing/btest/language/table-init.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output global global_table: table[count] of string = { diff --git a/testing/btest/language/time.bro b/testing/btest/language/time.bro index 43b6694101..dd4b6336fe 100644 --- a/testing/btest/language/time.bro +++ b/testing/btest/language/time.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/timeout.bro b/testing/btest/language/timeout.bro index 6bc0419b2f..b16ddd6e7c 100644 --- a/testing/btest/language/timeout.bro +++ b/testing/btest/language/timeout.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out diff --git a/testing/btest/language/vector-coerce-expr.bro b/testing/btest/language/vector-coerce-expr.bro index d58417f226..97f9617665 100644 --- a/testing/btest/language/vector-coerce-expr.bro +++ b/testing/btest/language/vector-coerce-expr.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro -b %INPUT >output 2>&1 # @TEST-EXEC: btest-diff output type X: record { diff --git a/testing/btest/language/vector-list-init-records.bro b/testing/btest/language/vector-list-init-records.bro index ee2b78c4a5..b1eee0ac92 100644 --- a/testing/btest/language/vector-list-init-records.bro +++ b/testing/btest/language/vector-list-init-records.bro @@ -1,7 +1,7 @@ # Initializing a vector with a list of records should promote elements as # necessary to match the vector's yield type. -# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: bro -b %INPUT >output # @TEST-EXEC: btest-diff output type Foo: record { diff --git a/testing/btest/language/vector.bro b/testing/btest/language/vector.bro index 928ddcb645..76fc8b69e3 100644 --- a/testing/btest/language/vector.bro +++ b/testing/btest/language/vector.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) diff --git a/testing/btest/language/wrong-delete-field.bro b/testing/btest/language/wrong-delete-field.bro index e0d0093258..63573faf8a 100644 --- a/testing/btest/language/wrong-delete-field.bro +++ b/testing/btest/language/wrong-delete-field.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC-FAIL: bro %INPUT >output 2>&1 +# @TEST-EXEC-FAIL: bro -b %INPUT >output 2>&1 # @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff output type X: record { diff --git a/testing/btest/language/wrong-record-extension.bro b/testing/btest/language/wrong-record-extension.bro index 4e0210546a..a8ef6a64e9 100644 --- a/testing/btest/language/wrong-record-extension.bro +++ b/testing/btest/language/wrong-record-extension.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC-FAIL: bro %INPUT >output.tmp 2>&1 +# @TEST-EXEC-FAIL: bro -b %INPUT >output.tmp 2>&1 # @TEST-EXEC: sed 's#^.*:##g' output # @TEST-EXEC: btest-diff output From f956554c74c75bc9f6514f172d73c5ad9697cecd Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 3 Dec 2012 11:57:00 -0500 Subject: [PATCH 21/23] Slightly fix up file name extraction from Content-Disposition headers. --- scripts/base/utils/files.bro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/base/utils/files.bro b/scripts/base/utils/files.bro index ccd03df0e6..e1e599b0b6 100644 --- a/scripts/base/utils/files.bro +++ b/scripts/base/utils/files.bro @@ -19,7 +19,7 @@ function generate_extraction_filename(prefix: string, c: connection, suffix: str ## the filename. function extract_filename_from_content_disposition(data: string): string { - local filename = sub(data, /^.*[fF][iI][lL][eE][nN][aA][mM][eE]=/, ""); + local filename = sub(data, /^.*[fF][iI][lL][eE][nN][aA][mM][eE][[:blank:]]*=[[:blank:]]*/, ""); # Remove quotes around the filename if they are there. if ( /^\"/ in filename ) filename = split_n(filename, /\"/, F, 2)[2]; From 63d43e6545dcfd564a3456dbe1cfab0a0f491655 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 3 Dec 2012 14:35:47 -0800 Subject: [PATCH 22/23] Renaming ASCII writer filter option 'only_single_header_row' to 'tsv'. Also clarifying usage. Closes #912. --- CHANGES | 5 +++++ VERSION | 2 +- .../base/frameworks/logging/writers/ascii.bro | 11 +++++++---- src/logging/writers/Ascii.cc | 16 ++++++++-------- src/logging/writers/Ascii.h | 2 +- .../ssh-filtered.log | 0 .../logging/{ascii-csv.bro => ascii-tsv.bro} | 2 +- 7 files changed, 23 insertions(+), 15 deletions(-) rename testing/btest/Baseline/{scripts.base.frameworks.logging.ascii-csv => scripts.base.frameworks.logging.ascii-tsv}/ssh-filtered.log (100%) rename testing/btest/scripts/base/frameworks/logging/{ascii-csv.bro => ascii-tsv.bro} (94%) diff --git a/CHANGES b/CHANGES index abe92547d9..475207a99f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,9 @@ +2.1-194 | 2012-12-03 14:36:26 -0800 + + * Renaming ASCII writer filter option 'only_single_header_row' to + 'tsv'. Also clarifying usage. Closes #912. (Robin Sommer) + 2.1-193 | 2012-12-03 14:11:14 -0800 * Fix a set of bugs with table/set attributes. (Jon Siwek) diff --git a/VERSION b/VERSION index c8d43d4760..57be098d90 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-193 +2.1-194 diff --git a/scripts/base/frameworks/logging/writers/ascii.bro b/scripts/base/frameworks/logging/writers/ascii.bro index 800af51502..352006666b 100644 --- a/scripts/base/frameworks/logging/writers/ascii.bro +++ b/scripts/base/frameworks/logging/writers/ascii.bro @@ -2,11 +2,14 @@ ##! to tweak the output format of ASCII logs. ##! ##! The ASCII writer supports currently one writer-specific filter option via -##! ``config``: setting ``only_single_header_row`` to ``T`` turns the output into -##! into CSV mode where only a single header row with the column names is printed -##! out as meta information. Example filter using this:: +##! ``config``: setting ``tsv`` to the string ``T`` turns the output into into +##! "tab-separated-value" mode where only a single header row with the column names +##! is printed out as meta information, with no "# fields" prepended; no other meta +##! data gets included in that mode. ##! -##! local my_filter: Log::Filter = [$name = "my-filter", $writer = Log::WRITER_ASCII, $config = table(["only_single_header_row"] = "T")]; +##! Example filter using this:: +##! +##! local my_filter: Log::Filter = [$name = "my-filter", $writer = Log::WRITER_ASCII, $config = table(["tsv"] = "T")]; ##! module LogAscii; diff --git a/src/logging/writers/Ascii.cc b/src/logging/writers/Ascii.cc index c65b0701c3..15b50344d5 100644 --- a/src/logging/writers/Ascii.cc +++ b/src/logging/writers/Ascii.cc @@ -19,7 +19,7 @@ Ascii::Ascii(WriterFrontend* frontend) : WriterBackend(frontend) { fd = 0; ascii_done = false; - only_single_header_row = false; + tsv = false; output_to_stdout = BifConst::LogAscii::output_to_stdout; include_meta = BifConst::LogAscii::include_meta; @@ -81,7 +81,7 @@ void Ascii::CloseFile(double t) if ( ! fd ) return; - if ( include_meta && ! only_single_header_row ) + if ( include_meta && ! tsv ) WriteHeaderField("close", Timestamp(0)); safe_close(fd); @@ -111,17 +111,17 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const Field* const * for ( WriterInfo::config_map::const_iterator i = info.config.begin(); i != info.config.end(); i++ ) { - if ( strcmp(i->first, "only_single_header_row") == 0 ) + if ( strcmp(i->first, "tsv") == 0 ) { if ( strcmp(i->second, "T") == 0 ) - only_single_header_row = true; + tsv = true; else if ( strcmp(i->second, "F") == 0 ) - only_single_header_row = false; + tsv = false; else { - Error("invalid value for 'only_single_header_row', must be boolean (T/F)"); + Error("invalid value for 'tsv', must be a string and either \"T\" or \"F\""); return false; } } @@ -144,9 +144,9 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const Field* const * types += fields[i]->TypeName().c_str(); } - if ( only_single_header_row ) + if ( tsv ) { - // A single CSV-style line is all we need. + // A single TSV-style line is all we need. string str = names + "\n"; if ( ! safe_write(fd, str.c_str(), str.length()) ) goto write_error; diff --git a/src/logging/writers/Ascii.h b/src/logging/writers/Ascii.h index 37ec19aba6..9fff5aae30 100644 --- a/src/logging/writers/Ascii.h +++ b/src/logging/writers/Ascii.h @@ -45,7 +45,7 @@ private: // Options set from the script-level. bool output_to_stdout; bool include_meta; - bool only_single_header_row; + bool tsv; char* separator; int separator_len; diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-csv/ssh-filtered.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-tsv/ssh-filtered.log similarity index 100% rename from testing/btest/Baseline/scripts.base.frameworks.logging.ascii-csv/ssh-filtered.log rename to testing/btest/Baseline/scripts.base.frameworks.logging.ascii-tsv/ssh-filtered.log diff --git a/testing/btest/scripts/base/frameworks/logging/ascii-csv.bro b/testing/btest/scripts/base/frameworks/logging/ascii-tsv.bro similarity index 94% rename from testing/btest/scripts/base/frameworks/logging/ascii-csv.bro rename to testing/btest/scripts/base/frameworks/logging/ascii-tsv.bro index 1c10f5fc6b..09276a08fd 100644 --- a/testing/btest/scripts/base/frameworks/logging/ascii-csv.bro +++ b/testing/btest/scripts/base/frameworks/logging/ascii-tsv.bro @@ -22,7 +22,7 @@ event bro_init() Log::create_stream(SSH::LOG, [$columns=Log]); local filter = Log::get_filter(SSH::LOG, "default"); - filter$config = table(["only_single_header_row"] = "T"); + filter$config = table(["tsv"] = "T"); Log::add_filter(SSH::LOG, filter); local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; From 05e6289719adba3f0e49954039c1e9819b68553b Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 3 Dec 2012 14:50:33 -0800 Subject: [PATCH 23/23] Catching out-of-memory in patricia tree code. Based on patch by Bill Parker. --- CHANGES | 4 ++ VERSION | 2 +- src/patricia.c | 131 ++++++++++++++++++++++++++++--------------------- src/util.cc | 2 +- src/util.h | 2 +- 5 files changed, 83 insertions(+), 58 deletions(-) diff --git a/CHANGES b/CHANGES index 475207a99f..9ff294055c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,8 @@ +2.1-195 | 2012-12-03 14:50:33 -0800 + + * Catching out-of-memory in patricia tree code. (Bill Parker) + 2.1-194 | 2012-12-03 14:36:26 -0800 * Renaming ASCII writer filter option 'only_single_header_row' to diff --git a/VERSION b/VERSION index 57be098d90..5f2036da97 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-194 +2.1-195 diff --git a/src/patricia.c b/src/patricia.c index 1dbc795ab7..6998576fdb 100644 --- a/src/patricia.c +++ b/src/patricia.c @@ -2,7 +2,7 @@ * Dave Plonka * * This product includes software developed by the University of Michigan, - * Merit Network, Inc., and their contributors. + * Merit Network, Inc., and their contributors. * * This file had been called "radix.c" in the MRT sources. * @@ -12,28 +12,28 @@ */ /* From copyright.txt: - * + * * Copyright (c) 1997, 1998, 1999 - * - * + * + * * The Regents of the University of Michigan ("The Regents") and Merit Network, * Inc. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the * following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other * materials provided with the distribution. - * 3. All advertising materials mentioning features or use of - * this software must display the following acknowledgement: + * 3. All advertising materials mentioning features or use of + * this software must display the following acknowledgement: * This product includes software developed by the University of Michigan, Merit - * Network, Inc., and their contributors. + * Network, Inc., and their contributors. * 4. Neither the name of the University, Merit Network, nor the - * names of their contributors may be used to endorse or - * promote products derived from this software without + * names of their contributors may be used to endorse or + * promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -44,7 +44,7 @@ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ static char copyright[] = @@ -66,6 +66,9 @@ static char copyright[] = #define Delete free +// From Bro for reporting memory exhaustion. +extern void out_of_memory(const char* where); + /* { from prefix.c */ /* prefix_tochar @@ -80,7 +83,7 @@ prefix_tochar (prefix_t * prefix) return ((u_char *) & prefix->add.sin); } -int +int comp_with_mask (void *addr, void *dest, u_int mask) { @@ -95,15 +98,15 @@ comp_with_mask (void *addr, void *dest, u_int mask) } /* inet_pton substitute implementation - * Uses inet_addr to convert an IP address in dotted decimal notation into + * Uses inet_addr to convert an IP address in dotted decimal notation into * unsigned long and copies the result to dst. - * Only supports AF_INET. Follows standard error return conventions of + * Only supports AF_INET. Follows standard error return conventions of * inet_pton. */ int local_inet_pton (int af, const char *src, void *dst) { - u_long result; + u_long result; if (af == AF_INET) { result = inet_addr(src); @@ -166,7 +169,7 @@ my_inet_pton (int af, const char *src, void *dst) } } -/* +/* * convert prefix information to ascii string with length * thread safe and (almost) re-entrant implementation */ @@ -251,6 +254,9 @@ New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix) default_bitlen = 128; if (prefix == NULL) { prefix = calloc(1, sizeof (prefix_t)); + if (prefix == NULL) + out_of_memory("patrica/new_prefix2: unable to allocate memory"); + dynamic_allocated++; } memcpy (&prefix->add.sin6, dest, 16); @@ -260,12 +266,16 @@ New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix) if (prefix == NULL) { #ifndef NT prefix = calloc(1, sizeof (prefix4_t)); + if (prefix == NULL) + out_of_memory("patrica/new_prefix2: unable to allocate memory"); #else //for some reason, compiler is getting //prefix4_t size incorrect on NT - prefix = calloc(1, sizeof (prefix_t)); + prefix = calloc(1, sizeof (prefix_t)); + if (prefix == NULL) + out_of_memory("patrica/new_prefix2: unable to allocate memory"); #endif /* NT */ - + dynamic_allocated++; } memcpy (&prefix->add.sin, dest, 4); @@ -368,7 +378,7 @@ Ref_Prefix (prefix_t * prefix) return (prefix); } -void +void Deref_Prefix (prefix_t * prefix) { if (prefix == NULL) @@ -396,6 +406,8 @@ patricia_tree_t * New_Patricia (int maxbits) { patricia_tree_t *patricia = calloc(1, sizeof *patricia); + if (patricia == NULL) + out_of_memory("patrica/new_patricia: unable to allocate memory"); patricia->maxbits = maxbits; patricia->head = NULL; @@ -503,10 +515,10 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) if (BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) { #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_exact: take right %s/%d\n", + fprintf (stderr, "patricia_search_exact: take right %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else - fprintf (stderr, "patricia_search_exact: take right at %d\n", + fprintf (stderr, "patricia_search_exact: take right at %d\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->r; @@ -514,10 +526,10 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) else { #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_exact: take left %s/%d\n", + fprintf (stderr, "patricia_search_exact: take left %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else - fprintf (stderr, "patricia_search_exact: take left at %d\n", + fprintf (stderr, "patricia_search_exact: take left at %d\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->l; @@ -529,7 +541,7 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_exact: stop at %s/%d\n", + fprintf (stderr, "patricia_search_exact: stop at %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_search_exact: stop at %d\n", node->bit); @@ -541,7 +553,7 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) if (comp_with_mask (prefix_tochar (node->prefix), prefix_tochar (prefix), bitlen)) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_search_exact: found %s/%d\n", + fprintf (stderr, "patricia_search_exact: found %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (node); @@ -575,7 +587,7 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv if (node->prefix) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_search_best: push %s/%d\n", + fprintf (stderr, "patricia_search_best: push %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ stack[cnt++] = node; @@ -584,10 +596,10 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv if (BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) { #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_best: take right %s/%d\n", + fprintf (stderr, "patricia_search_best: take right %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else - fprintf (stderr, "patricia_search_best: take right at %d\n", + fprintf (stderr, "patricia_search_best: take right at %d\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->r; @@ -595,10 +607,10 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv else { #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_search_best: take left %s/%d\n", + fprintf (stderr, "patricia_search_best: take left %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else - fprintf (stderr, "patricia_search_best: take left at %d\n", + fprintf (stderr, "patricia_search_best: take left at %d\n", node->bit); #endif /* PATRICIA_DEBUG */ node = node->l; @@ -615,7 +627,7 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv if (node == NULL) fprintf (stderr, "patricia_search_best: stop at null\n"); else if (node->prefix) - fprintf (stderr, "patricia_search_best: stop at %s/%d\n", + fprintf (stderr, "patricia_search_best: stop at %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_search_best: stop at %d\n", node->bit); @@ -627,14 +639,14 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv while (--cnt >= 0) { node = stack[cnt]; #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_search_best: pop %s/%d\n", + fprintf (stderr, "patricia_search_best: pop %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ - if (comp_with_mask (prefix_tochar (node->prefix), + if (comp_with_mask (prefix_tochar (node->prefix), prefix_tochar (prefix), node->prefix->bitlen)) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_search_best: found %s/%d\n", + fprintf (stderr, "patricia_search_best: found %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (node); @@ -665,6 +677,9 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) if (patricia->head == NULL) { node = calloc(1, sizeof *node); + if (node == NULL) + out_of_memory("patrica/patrica_lookup: unable to allocate memory"); + node->bit = prefix->bitlen; node->prefix = Ref_Prefix (prefix); node->parent = NULL; @@ -672,7 +687,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) node->data = NULL; patricia->head = node; #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: new_node #0 %s/%d (head)\n", + fprintf (stderr, "patricia_lookup: new_node #0 %s/%d (head)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ patricia->num_active_node++; @@ -691,7 +706,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) break; #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_lookup: take right %s/%d\n", + fprintf (stderr, "patricia_lookup: take right %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_lookup: take right at %d\n", node->bit); @@ -703,7 +718,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) break; #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_lookup: take left %s/%d\n", + fprintf (stderr, "patricia_lookup: take left %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_lookup: take left at %d\n", node->bit); @@ -716,7 +731,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) assert (node->prefix); #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: stop at %s/%d\n", + fprintf (stderr, "patricia_lookup: stop at %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ @@ -751,7 +766,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) parent = node->parent; #ifdef PATRICIA_DEBUG if (node->prefix) - fprintf (stderr, "patricia_lookup: up to %s/%d\n", + fprintf (stderr, "patricia_lookup: up to %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); else fprintf (stderr, "patricia_lookup: up to %d\n", node->bit); @@ -760,8 +775,8 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) if (differ_bit == bitlen && node->bit == bitlen) { if (node->prefix) { -#ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: found %s/%d\n", +#ifdef PATRICIA_DEBUG + fprintf (stderr, "patricia_lookup: found %s/%d\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (node); @@ -776,6 +791,9 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) } new_node = calloc(1, sizeof *new_node); + if (new_node == NULL) + out_of_memory("patrica/patrica_lookup: unable to allocate memory"); + new_node->bit = prefix->bitlen; new_node->prefix = Ref_Prefix (prefix); new_node->parent = NULL; @@ -795,7 +813,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) node->l = new_node; } #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: new_node #2 %s/%d (child)\n", + fprintf (stderr, "patricia_lookup: new_node #2 %s/%d (child)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ return (new_node); @@ -822,12 +840,15 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) } node->parent = new_node; #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: new_node #3 %s/%d (parent)\n", + fprintf (stderr, "patricia_lookup: new_node #3 %s/%d (parent)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ } else { glue = calloc(1, sizeof *glue); + if (glue == NULL) + out_of_memory("patrica/patrica_lookup: unable to allocate memory"); + glue->bit = differ_bit; glue->prefix = NULL; glue->parent = node->parent; @@ -856,7 +877,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) } node->parent = glue; #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_lookup: new_node #4 %s/%d (glue+node)\n", + fprintf (stderr, "patricia_lookup: new_node #4 %s/%d (glue+node)\n", prefix_toa (prefix), prefix->bitlen); #endif /* PATRICIA_DEBUG */ } @@ -874,13 +895,13 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node) if (node->r && node->l) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_remove: #0 %s/%d (r & l)\n", + fprintf (stderr, "patricia_remove: #0 %s/%d (r & l)\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ - + /* this might be a placeholder node -- have to check and make sure * there is a prefix aossciated with it ! */ - if (node->prefix != NULL) + if (node->prefix != NULL) Deref_Prefix (node->prefix); node->prefix = NULL; /* Also I needed to clear data pointer -- masaki */ @@ -890,7 +911,7 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node) if (node->r == NULL && node->l == NULL) { #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_remove: #1 %s/%d (!r & !l)\n", + fprintf (stderr, "patricia_remove: #1 %s/%d (!r & !l)\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ parent = node->parent; @@ -937,7 +958,7 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node) } #ifdef PATRICIA_DEBUG - fprintf (stderr, "patricia_remove: #2 %s/%d (r ^ l)\n", + fprintf (stderr, "patricia_remove: #2 %s/%d (r ^ l)\n", prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ if (node->r) { @@ -996,7 +1017,7 @@ try_search_exact (patricia_tree_t *tree, char *string) printf ("try_search_exact: not found\n"); } else { - printf ("try_search_exact: %s/%d found\n", + printf ("try_search_exact: %s/%d found\n", prefix_toa (node->prefix), node->prefix->bitlen); } Deref_Prefix (prefix); @@ -1023,7 +1044,7 @@ try_search_best (patricia_tree_t *tree, char *string) if ((node = patricia_search_best (tree, prefix)) == NULL) printf ("try_search_best: not found\n"); else - printf ("try_search_best: %s/%d found\n", + printf ("try_search_best: %s/%d found\n", prefix_toa (node->prefix), node->prefix->bitlen); Deref_Prefix (prefix); return 0; // [RS] What is supposed to be returned here? diff --git a/src/util.cc b/src/util.cc index 80cd3a0685..c36ff6a31c 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1416,7 +1416,7 @@ void safe_close(int fd) } } -void out_of_memory(const char* where) +extern "C" void out_of_memory(const char* where) { fprintf(stderr, "out of memory in %s.\n", where); diff --git a/src/util.h b/src/util.h index 71b9c494e8..7d65f42fa8 100644 --- a/src/util.h +++ b/src/util.h @@ -303,7 +303,7 @@ extern bool safe_write(int fd, const char* data, int len); // Wraps close(2) to emit error messages and abort on unrecoverable errors. extern void safe_close(int fd); -extern void out_of_memory(const char* where); +extern "C" void out_of_memory(const char* where); inline void* safe_realloc(void* ptr, size_t size) {