From 4e1ac4e1247d23d6050fd4eb7719ded51dd54235 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 20 Mar 2020 18:03:04 -0700 Subject: [PATCH] Use vector> for Func::Call and Event queuing args This change may break BIFs that use @ARGS@, @ARG@, or @ARGC@ since their types have changed. --- NEWS | 6 ++- aux/bifcl | 2 +- src/CMakeLists.txt | 1 + src/Event.cc | 50 +++++++++++++++------ src/Event.h | 55 ++++++++++++++--------- src/EventHandler.cc | 29 +++++------- src/EventHandler.h | 5 ++- src/Expr.cc | 51 +++++++-------------- src/Expr.h | 15 ++++--- src/File.cc | 2 +- src/Frame.cc | 2 +- src/Frame.h | 7 +-- src/Func.cc | 84 ++++++++++++++++------------------ src/Func.h | 22 +++++---- src/OpaqueVal.cc | 97 +++++++++------------------------------- src/OpaqueVal.h | 41 ++++++++++++++--- src/Stats.cc | 4 +- src/Stmt.cc | 40 +++++++---------- src/Stmt.h | 7 +-- src/Val.cc | 18 ++++++++ src/Val.h | 2 + src/ZeekArgs.cc | 15 +++++++ src/ZeekArgs.h | 27 +++++++++++ src/broker/messaging.bif | 32 +++++++------ src/main.cc | 2 +- src/plugin/Manager.cc | 21 +++++++-- src/plugin/Manager.h | 4 +- src/plugin/Plugin.h | 1 + src/zeek.bif | 30 ++++++------- 29 files changed, 367 insertions(+), 305 deletions(-) create mode 100644 src/ZeekArgs.cc create mode 100644 src/ZeekArgs.h diff --git a/NEWS b/NEWS index 16389dd9b7..a1ff0dca04 100644 --- a/NEWS +++ b/NEWS @@ -27,10 +27,14 @@ Changed Functionality --------------------- - Several C++ functions have been changed to pass smart pointers - (`class IntrusivePtr<>`) instead of raw pointers. This makes the + (``class IntrusivePtr<>``) instead of raw pointers. This makes the code more robust. External plugins may need to be updated to this API change. +- BIFs that use @ARG@, @ARGS@, or @ARGC@ may break since their type has + changed: BIF arguments are now passed as a ``std::vector>`` + rather than a ``val_list`` (i.e. ``List``). + Removed Functionality --------------------- diff --git a/aux/bifcl b/aux/bifcl index b3a5d01c04..75f645ac9b 160000 --- a/aux/bifcl +++ b/aux/bifcl @@ -1 +1 @@ -Subproject commit b3a5d01c041b78a9e50544ac891c5e0d35c116f7 +Subproject commit 75f645ac9bdfd141f549b7e1a197459f2ad518be diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f1b4e19b9f..a423f69ed5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -282,6 +282,7 @@ set(MAIN_SRCS Val.cc Var.cc WeirdState.cc + ZeekArgs.cc bsd-getopt-long.c bro_inet_ntop.c cq.c diff --git a/src/Event.cc b/src/Event.cc index 6c7db7faaa..f3665cf54d 100644 --- a/src/Event.cc +++ b/src/Event.cc @@ -18,7 +18,7 @@ EventMgr mgr; uint64_t num_events_queued = 0; uint64_t num_events_dispatched = 0; -Event::Event(EventHandlerPtr arg_handler, val_list arg_args, +Event::Event(EventHandlerPtr arg_handler, zeek::Args arg_args, SourceID arg_src, analyzer::ID arg_aid, TimerMgr* arg_mgr, BroObj* arg_obj) : handler(arg_handler), @@ -33,14 +33,6 @@ Event::Event(EventHandlerPtr arg_handler, val_list arg_args, Ref(obj); } -Event::Event(EventHandlerPtr arg_handler, val_list* arg_args, - SourceID arg_src, analyzer::ID arg_aid, TimerMgr* arg_mgr, - BroObj* arg_obj) - : Event(arg_handler, std::move(*arg_args), arg_src, arg_aid, arg_mgr, arg_obj) - { - delete arg_args; - } - void Event::Describe(ODesc* d) const { if ( d->IsReadable() ) @@ -53,7 +45,7 @@ void Event::Describe(ODesc* d) const if ( ! d->IsBinary() ) d->Add("("); - describe_vals(&args, d); + describe_vals(args, d); if ( ! d->IsBinary() ) d->Add("("); } @@ -68,7 +60,7 @@ void Event::Dispatch(bool no_remote) try { - handler->Call(&args, no_remote); + handler->Call(args, no_remote); } catch ( InterpreterException& e ) @@ -106,12 +98,19 @@ EventMgr::~EventMgr() Unref(src_val); } +void EventMgr::QueueEventFast(const EventHandlerPtr &h, val_list vl, + SourceID src, analyzer::ID aid, TimerMgr* mgr, + BroObj* obj) + { + QueueEvent(new Event(h, zeek::val_list_to_args(&vl), src, aid, mgr, obj)); + } + void EventMgr::QueueEvent(const EventHandlerPtr &h, val_list vl, - SourceID src, analyzer::ID aid, - TimerMgr* mgr, BroObj* obj) + SourceID src, analyzer::ID aid, + TimerMgr* mgr, BroObj* obj) { if ( h ) - QueueEvent(new Event(h, std::move(vl), src, aid, mgr, obj)); + QueueEvent(new Event(h, zeek::val_list_to_args(&vl), src, aid, mgr, obj)); else { for ( const auto& v : vl ) @@ -119,6 +118,29 @@ void EventMgr::QueueEvent(const EventHandlerPtr &h, val_list vl, } } +void EventMgr::QueueEvent(const EventHandlerPtr &h, val_list* vl, + SourceID src, analyzer::ID aid, + TimerMgr* mgr, BroObj* obj) + { + QueueEvent(h, std::move(*vl), src, aid, mgr, obj); + delete vl; + } + +void EventMgr::QueueCheckedEvent(const EventHandlerPtr& h, zeek::Args vl, + SourceID src, analyzer::ID aid, + TimerMgr* mgr, BroObj* obj) + { + QueueEvent(new Event(h, std::move(vl), src, aid, mgr, obj)); + } + +void EventMgr::QueueUncheckedEvent(const EventHandlerPtr& h, zeek::Args vl, + SourceID src, analyzer::ID aid, + TimerMgr* mgr, BroObj* obj) + { + if ( h ) + QueueEvent(new Event(h, std::move(vl), src, aid, mgr, obj)); + } + void EventMgr::QueueEvent(Event* event) { bool done = PLUGIN_HOOK_WITH_RESULT(HOOK_QUEUE_EVENT, HookQueueEvent(event), false); diff --git a/src/Event.h b/src/Event.h index ce15cc5f52..46d166c1a3 100644 --- a/src/Event.h +++ b/src/Event.h @@ -6,20 +6,15 @@ #include "analyzer/Analyzer.h" #include "iosource/IOSource.h" #include "Flare.h" +#include "ZeekArgs.h" class EventMgr; -// We don't Unref() the individual arguments by using delete_vals() -// in a dtor because Func::Call already does that. class Event : public BroObj { public: - Event(EventHandlerPtr handler, val_list args, - SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0, - TimerMgr* mgr = 0, BroObj* obj = 0); - - Event(EventHandlerPtr handler, val_list* args, - SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0, - TimerMgr* mgr = 0, BroObj* obj = 0); + Event(EventHandlerPtr handler, zeek::Args args, + SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0, + TimerMgr* mgr = nullptr, BroObj* obj = nullptr); void SetNext(Event* n) { next_event = n; } Event* NextEvent() const { return next_event; } @@ -28,7 +23,7 @@ public: analyzer::ID Analyzer() const { return aid; } TimerMgr* Mgr() const { return mgr; } EventHandlerPtr Handler() const { return handler; } - const val_list* Args() const { return &args; } + const zeek::Args& Args() const { return args; } void Describe(ODesc* d) const override; @@ -40,7 +35,7 @@ protected: void Dispatch(bool no_remote = false); EventHandlerPtr handler; - val_list args; + zeek::Args args; SourceID src; analyzer::ID aid; TimerMgr* mgr; @@ -64,12 +59,11 @@ public: // against the case where there's no handlers (one usually also does that // because it would be a waste of effort to construct all the event // arguments when there's no handlers to consume them). + // TODO: deprecate + /* [[deprecated("Remove in v4.1. Use IntrusivePtr overload instead.")]] */ void QueueEventFast(const EventHandlerPtr &h, val_list vl, SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0, - TimerMgr* mgr = 0, BroObj* obj = 0) - { - QueueEvent(new Event(h, std::move(vl), src, aid, mgr, obj)); - } + TimerMgr* mgr = 0, BroObj* obj = 0); // Queues an event if there's an event handler (or remote consumer). This // function always takes ownership of decrementing the reference count of @@ -77,6 +71,8 @@ public: // checked for event handler existence, you may wish to call // QueueEventFast() instead of this function to prevent the redundant // existence check. + // TODO: deprecate + /* [[deprecated("Remove in v4.1. Use IntrusivePtr overload instead.")]] */ void QueueEvent(const EventHandlerPtr &h, val_list vl, SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0, TimerMgr* mgr = 0, BroObj* obj = 0); @@ -85,13 +81,32 @@ public: // pointer instead of by value. This function takes ownership of the // memory pointed to by 'vl' as well as decrementing the reference count of // each of its elements. + // TODO: deprecate + /* [[deprecated("Remove in v4.1. Use IntrusivePtr overload instead.")]] */ void QueueEvent(const EventHandlerPtr &h, val_list* vl, SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0, - TimerMgr* mgr = 0, BroObj* obj = 0) - { - QueueEvent(h, std::move(*vl), src, aid, mgr, obj); - delete vl; - } + TimerMgr* mgr = 0, BroObj* obj = 0); + + /** + * Queues an event without first checking if there's an event handler + * remote consumer. If there are actually no handlers/consumers upon + * dispatching the event, nothing happens besides having wasted a bit of + * time and resources. This method is mostly useful from a performance + * standpoint: usually callers have already checked that the event will + * consumed so they don't waste time creating an argument list that will + * only be discarded, so there's no need to do the same check again when + * going to queue the event. + */ + void QueueUncheckedEvent(const EventHandlerPtr& h, zeek::Args vl, + SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0, + TimerMgr* mgr = nullptr, BroObj* obj = nullptr); + + /** + * Queues an event if it has an event handler or remote consumer. + */ + void QueueCheckedEvent(const EventHandlerPtr& h, zeek::Args vl, + SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0, + TimerMgr* mgr = nullptr, BroObj* obj = nullptr); void Dispatch(Event* event, bool no_remote = false); diff --git a/src/EventHandler.cc b/src/EventHandler.cc index 9a5cba56b1..8f35d47ed5 100644 --- a/src/EventHandler.cc +++ b/src/EventHandler.cc @@ -60,7 +60,7 @@ void EventHandler::SetLocalHandler(Func* f) local = f; } -void EventHandler::Call(val_list* vl, bool no_remote) +void EventHandler::Call(const zeek::Args& vl, bool no_remote) { #ifdef PROFILE_BRO_FUNCTIONS DEBUG_MSG("Event: %s\n", Name()); @@ -75,12 +75,12 @@ void EventHandler::Call(val_list* vl, bool no_remote) { // Send event in form [name, xs...] where xs represent the arguments. broker::vector xs; - xs.reserve(vl->length()); + xs.reserve(vl.size()); bool valid_args = true; - for ( auto i = 0; i < vl->length(); ++i ) + for ( auto i = 0u; i < vl.size(); ++i ) { - auto opt_data = bro_broker::val_to_data((*vl)[i]); + auto opt_data = bro_broker::val_to_data(vl[i].get()); if ( opt_data ) xs.emplace_back(move(*opt_data)); @@ -115,14 +115,9 @@ void EventHandler::Call(val_list* vl, bool no_remote) if ( local ) // No try/catch here; we pass exceptions upstream. local->Call(vl); - else - { - for ( auto v : *vl ) - Unref(v); - } } -void EventHandler::NewEvent(val_list* vl) +void EventHandler::NewEvent(const zeek::Args& vl) { if ( ! new_event ) return; @@ -132,7 +127,7 @@ void EventHandler::NewEvent(val_list* vl) return; RecordType* args = FType()->Args(); - VectorVal* vargs = new VectorVal(call_argument_vector); + auto vargs = make_intrusive(call_argument_vector); for ( int i = 0; i < args->NumFields(); i++ ) { @@ -151,19 +146,15 @@ void EventHandler::NewEvent(val_list* vl) if ( fdefault ) rec->Assign(2, std::move(fdefault)); - if ( i < vl->length() && (*vl)[i] ) - { - Val* val = (*vl)[i]; - Ref(val); - rec->Assign(3, val); - } + if ( i < static_cast(vl.size()) && vl[i] ) + rec->Assign(3, vl[i]); vargs->Assign(i, std::move(rec)); } Event* ev = new Event(new_event, { - new StringVal(name), - vargs, + make_intrusive(name), + std::move(vargs), }); mgr.Dispatch(ev); } diff --git a/src/EventHandler.h b/src/EventHandler.h index ed01bf18a3..effafb134e 100644 --- a/src/EventHandler.h +++ b/src/EventHandler.h @@ -3,6 +3,7 @@ #pragma once #include "BroList.h" +#include "ZeekArgs.h" #include #include @@ -31,7 +32,7 @@ public: auto_publish.erase(topic); } - void Call(val_list* vl, bool no_remote = false); + void Call(const zeek::Args& vl, bool no_remote = false); // Returns true if there is at least one local or remote handler. explicit operator bool() const; @@ -52,7 +53,7 @@ public: bool GenerateAlways() { return generate_always; } private: - void NewEvent(val_list* vl); // Raise new_event() meta event. + void NewEvent(const zeek::Args& vl); // Raise new_event() meta event. const char* name; Func* local; diff --git a/src/Expr.cc b/src/Expr.cc index ad6c18432c..09a0c63fc0 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3884,12 +3884,11 @@ IntrusivePtr FlattenExpr::Fold(Val* v) const return l; } -ScheduleTimer::ScheduleTimer(EventHandlerPtr arg_event, val_list* arg_args, +ScheduleTimer::ScheduleTimer(EventHandlerPtr arg_event, zeek::Args arg_args, double t, TimerMgr* arg_tmgr) : Timer(t, TIMER_SCHEDULE), - event(arg_event), args(std::move(*arg_args)), tmgr(arg_tmgr) + event(arg_event), args(std::move(arg_args)), tmgr(arg_tmgr) { - delete arg_args; } ScheduleTimer::~ScheduleTimer() @@ -3898,7 +3897,7 @@ ScheduleTimer::~ScheduleTimer() void ScheduleTimer::Dispatch(double /* t */, int /* is_expire */) { - mgr.QueueEvent(event, std::move(args), SOURCE_LOCAL, 0, tmgr); + mgr.QueueUncheckedEvent(event, std::move(args), SOURCE_LOCAL, 0, tmgr); } ScheduleExpr::ScheduleExpr(IntrusivePtr arg_when, @@ -3937,7 +3936,7 @@ IntrusivePtr ScheduleExpr::Eval(Frame* f) const if ( when->Type()->Tag() == TYPE_INTERVAL ) dt += network_time; - val_list* args = eval_list(f, event->Args()); + auto args = eval_list(f, event->Args()); if ( args ) { @@ -3946,7 +3945,7 @@ IntrusivePtr ScheduleExpr::Eval(Frame* f) const if ( ! tmgr ) tmgr = timer_mgr; - tmgr->Add(new ScheduleTimer(event->Handler(), args, dt, tmgr)); + tmgr->Add(new ScheduleTimer(event->Handler(), std::move(*args), dt, tmgr)); } return nullptr; @@ -4236,7 +4235,7 @@ IntrusivePtr CallExpr::Eval(Frame* f) const IntrusivePtr ret; auto func_val = func->Eval(f); - val_list* v = eval_list(f, args.get()); + auto v = eval_list(f, args.get()); if ( func_val && v ) { @@ -4246,16 +4245,11 @@ IntrusivePtr CallExpr::Eval(Frame* f) const if ( f ) f->SetCall(this); - ret = func->Call(v, f); + ret = func->Call(*v, f); if ( f ) f->SetCall(current_call); - - // Don't Unref() the arguments, as Func::Call already did that. - delete v; } - else - delete_vals(v); return ret; } @@ -4448,10 +4442,8 @@ IntrusivePtr EventExpr::Eval(Frame* f) const if ( IsError() ) return nullptr; - val_list* v = eval_list(f, args.get()); - mgr.QueueEvent(handler, std::move(*v)); - delete v; - + auto v = eval_list(f, args.get()); + mgr.QueueUncheckedEvent(handler, std::move(*v)); return nullptr; } @@ -5176,36 +5168,23 @@ int check_and_promote_exprs_to_type(ListExpr* const elements, BroType* type) return 1; } -val_list* eval_list(Frame* f, const ListExpr* l) +std::optional>> eval_list(Frame* f, const ListExpr* l) { const expr_list& e = l->Exprs(); - val_list* v = new val_list(e.length()); - bool success = true; + auto rval = std::make_optional>>(); + rval->reserve(e.length()); for ( const auto& expr : e ) { auto ev = expr->Eval(f); if ( ! ev ) - { - success = false; - break; - } + return {}; - v->push_back(ev.release()); + rval->emplace_back(std::move(ev)); } - if ( ! success ) - { - for ( const auto& val : *v ) - Unref(val); - - delete v; - return nullptr; - } - - else - return v; + return rval; } bool expr_greater(const Expr* e1, const Expr* e2) diff --git a/src/Expr.h b/src/Expr.h index 95c1167abe..48f02cd90e 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -9,10 +9,13 @@ #include "EventHandler.h" #include "TraverseTypes.h" #include "Val.h" +#include "ZeekArgs.h" #include #include +#include #include +#include using std::string; @@ -737,15 +740,15 @@ protected: class ScheduleTimer : public Timer { public: - ScheduleTimer(EventHandlerPtr event, val_list* args, double t, - TimerMgr* tmgr); + ScheduleTimer(EventHandlerPtr event, zeek::Args args, + double t, TimerMgr* tmgr); ~ScheduleTimer() override; void Dispatch(double t, int is_expire) override; protected: EventHandlerPtr event; - val_list args; + zeek::Args args; TimerMgr* tmgr; }; @@ -936,9 +939,9 @@ extern int check_and_promote_exprs(ListExpr* elements, TypeList* types); extern int check_and_promote_args(ListExpr* args, RecordType* types); extern int check_and_promote_exprs_to_type(ListExpr* elements, BroType* type); -// Returns a ListExpr simplified down to a list a values, or a nil -// pointer if they couldn't all be reduced. -val_list* eval_list(Frame* f, const ListExpr* l); +// Returns a ListExpr simplified down to a list a values, or nil +// if they couldn't all be reduced. +std::optional>> eval_list(Frame* f, const ListExpr* l); // Returns true if e1 is "greater" than e2 - here "greater" is just // a heuristic, used with commutative operators to put them into diff --git a/src/File.cc b/src/File.cc index 27702f0658..9e01c144ff 100644 --- a/src/File.cc +++ b/src/File.cc @@ -325,7 +325,7 @@ void BroFile::RaiseOpenEvent() return; Ref(this); - Event* event = new ::Event(::file_opened, {new Val(this)}); + Event* event = new ::Event(::file_opened, {make_intrusive(this)}); mgr.Dispatch(event, true); } diff --git a/src/Frame.cc b/src/Frame.cc index 88a60e3b1f..1c093398dc 100644 --- a/src/Frame.cc +++ b/src/Frame.cc @@ -14,7 +14,7 @@ vector g_frame_stack; -Frame::Frame(int arg_size, const BroFunc* func, const val_list* fn_args) +Frame::Frame(int arg_size, const BroFunc* func, const zeek::Args* fn_args) { size = arg_size; frame = new Val*[size]; diff --git a/src/Frame.h b/src/Frame.h index d999b6f3ed..0961290ab1 100644 --- a/src/Frame.h +++ b/src/Frame.h @@ -5,6 +5,7 @@ #include "BroList.h" // for typedef val_list #include "Obj.h" #include "IntrusivePtr.h" +#include "ZeekArgs.h" #include #include @@ -28,7 +29,7 @@ public: * @param func the function that is creating this frame * @param fn_args the arguments being passed to that function. */ - Frame(int size, const BroFunc* func, const val_list *fn_args); + Frame(int size, const BroFunc* func, const zeek::Args* fn_args); /** * Deletes the frame. Unrefs its trigger, the values that it @@ -100,7 +101,7 @@ public: * @return the arguments passed to the function that this frame * is associated with. */ - const val_list* GetFuncArgs() const { return func_args; } + const zeek::Args* GetFuncArgs() const { return func_args; } /** * Change the function that the frame is associated with. @@ -283,7 +284,7 @@ private: /** The function this frame is associated with. */ const BroFunc* function; /** The arguments to the function that this Frame is associated with. */ - const val_list* func_args; + const zeek::Args* func_args; /** The next statement to be evaluted in the context of this frame. */ Stmt* next_stmt; diff --git a/src/Func.cc b/src/Func.cc index e54a4c4ac4..0f4b9ca376 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -79,19 +79,16 @@ std::string render_call_stack() auto name = ci.func->Name(); std::string arg_desc; - if ( ci.args ) + for ( const auto& arg : ci.args ) { - for ( const auto& arg : *ci.args ) - { - ODesc d; - d.SetShort(); - arg->Describe(&d); + ODesc d; + d.SetShort(); + arg->Describe(&d); - if ( ! arg_desc.empty() ) - arg_desc += ", "; + if ( ! arg_desc.empty() ) + arg_desc += ", "; - arg_desc += d.Description(); - } + arg_desc += d.Description(); } rval += fmt("#%d %s(%s)", lvl, name, arg_desc.data()); @@ -143,7 +140,7 @@ IntrusivePtr Func::DoClone() return {NewRef{}, this}; } -void Func::DescribeDebug(ODesc* d, const val_list* args) const +void Func::DescribeDebug(ODesc* d, const zeek::Args* args) const { d->Add(Name()); @@ -153,10 +150,10 @@ void Func::DescribeDebug(ODesc* d, const val_list* args) const { d->Add("("); - for ( int i = 0; i < args->length(); ++i ) + for ( auto i = 0u; i < args->size(); ++i ) { // Handle varargs case (more args than formals). - if ( i >= func_args->NumFields() ) + if ( i >= static_cast(func_args->NumFields()) ) { d->Add("vararg"); d->Add(i - func_args->NumFields()); @@ -167,7 +164,7 @@ void Func::DescribeDebug(ODesc* d, const val_list* args) const d->Add(" = '"); (*args)[i]->Describe(d); - if ( i < args->length() - 1 ) + if ( i < args->size() - 1 ) d->Add("', "); else d->Add("'"); @@ -217,7 +214,7 @@ void Func::CopyStateInto(Func* other) const other->unique_id = unique_id; } -std::pair Func::HandlePluginResult(std::pair plugin_result, val_list* args, function_flavor flavor) const +std::pair Func::HandlePluginResult(std::pair plugin_result, function_flavor flavor) const { // Helper function factoring out this code from BroFunc:Call() for // better readability. @@ -265,9 +262,6 @@ std::pair Func::HandlePluginResult(std::pair plugin_resu } } - for ( const auto& arg : *args ) - Unref(arg); - return plugin_result; } @@ -300,7 +294,12 @@ int BroFunc::IsPure() const [](const Body& b) { return b.stmts->IsPure(); }); } -IntrusivePtr BroFunc::Call(val_list* args, Frame* parent) const +IntrusivePtr Func::Call(val_list* args, Frame* parent) const + { + return Call(zeek::val_list_to_args(args), parent); + } + +IntrusivePtr BroFunc::Call(const zeek::Args& args, Frame* parent) const { #ifdef PROFILE_BRO_FUNCTIONS DEBUG_MSG("Function: %s\n", Name()); @@ -312,7 +311,7 @@ IntrusivePtr BroFunc::Call(val_list* args, Frame* parent) const std::pair plugin_result = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, HookCallFunction(this, parent, args), empty_hook_result); - plugin_result = HandlePluginResult(plugin_result, args, Flavor()); + plugin_result = HandlePluginResult(plugin_result, Flavor()); if( plugin_result.first ) return {AdoptRef{}, plugin_result.second}; @@ -321,13 +320,10 @@ IntrusivePtr BroFunc::Call(val_list* args, Frame* parent) const { // Can only happen for events and hooks. assert(Flavor() == FUNC_FLAVOR_EVENT || Flavor() == FUNC_FLAVOR_HOOK); - for ( const auto& arg : *args ) - Unref(arg); - return Flavor() == FUNC_FLAVOR_HOOK ? IntrusivePtr{AdoptRef{}, val_mgr->GetTrue()} : nullptr; } - auto f = make_intrusive(frame_size, this, args); + auto f = make_intrusive(frame_size, this, &args); if ( closure ) f->CaptureClosure(closure, outer_ids); @@ -346,7 +342,7 @@ IntrusivePtr BroFunc::Call(val_list* args, Frame* parent) const if ( g_trace_state.DoTrace() ) { ODesc d; - DescribeDebug(&d, args); + DescribeDebug(&d, &args); g_trace_state.LogTrace("%s called: %s\n", FType()->FlavorString().c_str(), d.Description()); @@ -362,19 +358,16 @@ IntrusivePtr BroFunc::Call(val_list* args, Frame* parent) const body.stmts->GetLocationInfo()); // Fill in the rest of the frame with the function's arguments. - loop_over_list(*args, j) + for ( auto j = 0u; j < args.size(); ++j ) { - Val* arg = (*args)[j]; + Val* arg = args[j].get(); if ( f->NthElement(j) != arg ) - { // Either not yet set, or somebody reassigned the frame slot. - Ref(arg); - f->SetElement(j, arg); - } + f->SetElement(j, arg->Ref()); } - f->Reset(args->length()); + f->Reset(args.size()); try { @@ -421,11 +414,6 @@ IntrusivePtr BroFunc::Call(val_list* args, Frame* parent) const call_stack.pop_back(); - // We have an extra Ref for each argument (so that they don't get - // deleted between bodies), release that. - for ( const auto& arg : *args ) - Unref(arg); - if ( Flavor() == FUNC_FLAVOR_HOOK ) { if ( ! result ) @@ -612,7 +600,7 @@ int BuiltinFunc::IsPure() const return is_pure; } -IntrusivePtr BuiltinFunc::Call(val_list* args, Frame* parent) const +IntrusivePtr BuiltinFunc::Call(const zeek::Args& args, Frame* parent) const { #ifdef PROFILE_BRO_FUNCTIONS DEBUG_MSG("Function: %s\n", Name()); @@ -624,7 +612,7 @@ IntrusivePtr BuiltinFunc::Call(val_list* args, Frame* parent) const std::pair plugin_result = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, HookCallFunction(this, parent, args), empty_hook_result); - plugin_result = HandlePluginResult(plugin_result, args, FUNC_FLAVOR_FUNCTION); + plugin_result = HandlePluginResult(plugin_result, FUNC_FLAVOR_FUNCTION); if ( plugin_result.first ) return {AdoptRef{}, plugin_result.second}; @@ -632,20 +620,16 @@ IntrusivePtr BuiltinFunc::Call(val_list* args, Frame* parent) const if ( g_trace_state.DoTrace() ) { ODesc d; - DescribeDebug(&d, args); + DescribeDebug(&d, &args); g_trace_state.LogTrace("\tBuiltin Function called: %s\n", d.Description()); } const CallExpr* call_expr = parent ? parent->GetCall() : nullptr; call_stack.emplace_back(CallInfo{call_expr, this, args}); - IntrusivePtr result{AdoptRef{}, func(parent, args)}; + IntrusivePtr result{AdoptRef{}, func(parent, &args)}; call_stack.pop_back(); - for ( const auto& arg : *args ) - Unref(arg); - - // Don't Unref() args, that's the caller's responsibility. if ( result && g_trace_state.DoTrace() ) { ODesc d; @@ -663,6 +647,16 @@ void BuiltinFunc::Describe(ODesc* d) const d->AddCount(is_pure); } +void builtin_error(const char* msg) + { + builtin_error(msg, IntrusivePtr{}); + } + +void builtin_error(const char* msg, IntrusivePtr arg) + { + builtin_error(msg, arg.get()); + } + void builtin_error(const char* msg, BroObj* arg) { auto emit = [=](const CallExpr* ce) diff --git a/src/Func.h b/src/Func.h index 2bed2f2d94..a5ac9f3454 100644 --- a/src/Func.h +++ b/src/Func.h @@ -7,6 +7,7 @@ #include "IntrusivePtr.h" #include "Type.h" /* for function_flavor */ #include "TraverseTypes.h" +#include "ZeekArgs.h" #include #include @@ -30,7 +31,6 @@ class Scope; class Func : public BroObj { public: - enum Kind { BRO_FUNC, BUILTIN_FUNC }; explicit Func(Kind arg_kind); @@ -50,7 +50,9 @@ public: const vector& GetBodies() const { return bodies; } bool HasBodies() const { return bodies.size(); } - virtual IntrusivePtr Call(val_list* args, Frame* parent = 0) const = 0; + // TODO: deprecate + virtual IntrusivePtr Call(val_list* args, Frame* parent = nullptr) const; + virtual IntrusivePtr Call(const zeek::Args& args, Frame* parent = nullptr) const = 0; // Add a new event handler to an existing function (event). virtual void AddBody(IntrusivePtr new_body, id_list* new_inits, @@ -67,7 +69,7 @@ public: void SetName(const char* arg_name) { name = arg_name; } void Describe(ODesc* d) const override = 0; - virtual void DescribeDebug(ODesc* d, const val_list* args) const; + virtual void DescribeDebug(ODesc* d, const zeek::Args* args) const; virtual IntrusivePtr DoClone(); @@ -84,7 +86,7 @@ protected: void CopyStateInto(Func* other) const; // Helper function for handling result of plugin hook. - std::pair HandlePluginResult(std::pair plugin_result, val_list* args, function_flavor flavor) const; + std::pair HandlePluginResult(std::pair plugin_result, function_flavor flavor) const; vector bodies; IntrusivePtr scope; @@ -102,7 +104,7 @@ public: ~BroFunc() override; int IsPure() const override; - IntrusivePtr Call(val_list* args, Frame* parent) const override; + IntrusivePtr Call(const zeek::Args& args, Frame* parent) const override; /** * Adds adds a closure to the function. Closures are cloned and @@ -169,7 +171,7 @@ private: bool weak_closure_ref = false; }; -typedef Val* (*built_in_func)(Frame* frame, val_list* args); +using built_in_func = Val* (*)(Frame* frame, const zeek::Args* args); class BuiltinFunc : public Func { public: @@ -177,7 +179,7 @@ public: ~BuiltinFunc() override; int IsPure() const override; - IntrusivePtr Call(val_list* args, Frame* parent) const override; + IntrusivePtr Call(const zeek::Args& args, Frame* parent) const override; built_in_func TheFunc() const { return func; } void Describe(ODesc* d) const override; @@ -190,7 +192,9 @@ protected: }; -extern void builtin_error(const char* msg, BroObj* arg = 0); +extern void builtin_error(const char* msg); +extern void builtin_error(const char* msg, IntrusivePtr); +extern void builtin_error(const char* msg, BroObj* arg); extern void init_builtin_funcs(); extern void init_builtin_funcs_subdirs(); @@ -199,7 +203,7 @@ extern bool check_built_in_call(BuiltinFunc* f, CallExpr* call); struct CallInfo { const CallExpr* call; const Func* func; - const val_list* args; + const zeek::Args& args; }; // Struct that collects all the specifics defining a Func. Used for BroFuncs diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index 0d2d0a8887..ecaa245fb7 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -221,6 +221,26 @@ MD5Val::~MD5Val() EVP_MD_CTX_free(ctx); } +void HashVal::digest_one(EVP_MD_CTX* h, const Val* v) + { + if ( v->Type()->Tag() == TYPE_STRING ) + { + const BroString* str = v->AsString(); + hash_update(h, str->Bytes(), str->Len()); + } + else + { + ODesc d(DESC_BINARY); + v->Describe(&d); + hash_update(h, (const u_char *) d.Bytes(), d.Len()); + } + } + +void HashVal::digest_one(EVP_MD_CTX* h, const IntrusivePtr& v) + { + digest_one(h, v.get()); + } + IntrusivePtr MD5Val::DoClone(CloneState* state) { auto out = make_intrusive(); @@ -236,39 +256,6 @@ IntrusivePtr MD5Val::DoClone(CloneState* state) return state->NewClone(this, std::move(out)); } -void MD5Val::digest(val_list& vlist, u_char result[MD5_DIGEST_LENGTH]) - { - EVP_MD_CTX* h = hash_init(Hash_MD5); - - for ( const auto& v : vlist ) - { - if ( v->Type()->Tag() == TYPE_STRING ) - { - const BroString* str = v->AsString(); - hash_update(h, str->Bytes(), str->Len()); - } - else - { - ODesc d(DESC_BINARY); - v->Describe(&d); - hash_update(h, (const u_char *) d.Bytes(), d.Len()); - } - } - - hash_final(h, result); - } - -void MD5Val::hmac(val_list& vlist, - u_char key[MD5_DIGEST_LENGTH], - u_char result[MD5_DIGEST_LENGTH]) - { - digest(vlist, result); - for ( int i = 0; i < MD5_DIGEST_LENGTH; ++i ) - result[i] ^= key[i]; - - internal_md5(result, MD5_DIGEST_LENGTH, result); - } - bool MD5Val::DoInit() { assert(! IsValid()); @@ -389,28 +376,6 @@ IntrusivePtr SHA1Val::DoClone(CloneState* state) return state->NewClone(this, std::move(out)); } -void SHA1Val::digest(val_list& vlist, u_char result[SHA_DIGEST_LENGTH]) - { - EVP_MD_CTX* h = hash_init(Hash_SHA1); - - for ( const auto& v : vlist ) - { - if ( v->Type()->Tag() == TYPE_STRING ) - { - const BroString* str = v->AsString(); - hash_update(h, str->Bytes(), str->Len()); - } - else - { - ODesc d(DESC_BINARY); - v->Describe(&d); - hash_update(h, (const u_char *) d.Bytes(), d.Len()); - } - } - - hash_final(h, result); - } - bool SHA1Val::DoInit() { assert(! IsValid()); @@ -535,28 +500,6 @@ IntrusivePtr SHA256Val::DoClone(CloneState* state) return state->NewClone(this, std::move(out)); } -void SHA256Val::digest(val_list& vlist, u_char result[SHA256_DIGEST_LENGTH]) - { - EVP_MD_CTX* h = hash_init(Hash_SHA256); - - for ( const auto& v : vlist ) - { - if ( v->Type()->Tag() == TYPE_STRING ) - { - const BroString* str = v->AsString(); - hash_update(h, str->Bytes(), str->Len()); - } - else - { - ODesc d(DESC_BINARY); - v->Describe(&d); - hash_update(h, (const u_char *) d.Bytes(), d.Len()); - } - } - - hash_final(h, result); - } - bool SHA256Val::DoInit() { assert( ! IsValid() ); diff --git a/src/OpaqueVal.h b/src/OpaqueVal.h index ff90344954..288e94a7db 100644 --- a/src/OpaqueVal.h +++ b/src/OpaqueVal.h @@ -162,12 +162,26 @@ namespace probabilistic { class HashVal : public OpaqueVal { public: + template + static void digest_all(HashAlgorithm alg, const T& vlist, u_char* result) + { + auto h = hash_init(alg); + + for ( const auto& v : vlist ) + digest_one(h, v); + + hash_final(h, result); + } + bool IsValid() const; bool Init(); bool Feed(const void* data, size_t size); IntrusivePtr Get(); protected: + static void digest_one(EVP_MD_CTX* h, const Val* v); + static void digest_one(EVP_MD_CTX* h, const IntrusivePtr& v); + HashVal() { valid = false; } explicit HashVal(OpaqueType* t); @@ -182,11 +196,22 @@ private: class MD5Val : public HashVal { public: - static void digest(val_list& vlist, u_char result[MD5_DIGEST_LENGTH]); + template + static void digest(const T& vlist, u_char result[MD5_DIGEST_LENGTH]) + { digest_all(Hash_MD5, vlist, result); } - static void hmac(val_list& vlist, - u_char key[MD5_DIGEST_LENGTH], - u_char result[MD5_DIGEST_LENGTH]); + template + static void hmac(const T& vlist, + u_char key[MD5_DIGEST_LENGTH], + u_char result[MD5_DIGEST_LENGTH]) + { + digest(vlist, result); + + for ( int i = 0; i < MD5_DIGEST_LENGTH; ++i ) + result[i] ^= key[i]; + + internal_md5(result, MD5_DIGEST_LENGTH, result); + } MD5Val(); ~MD5Val(); @@ -207,7 +232,9 @@ private: class SHA1Val : public HashVal { public: - static void digest(val_list& vlist, u_char result[SHA_DIGEST_LENGTH]); + template + static void digest(const T& vlist, u_char result[SHA_DIGEST_LENGTH]) + { digest_all(Hash_SHA1, vlist, result); } SHA1Val(); ~SHA1Val(); @@ -228,7 +255,9 @@ private: class SHA256Val : public HashVal { public: - static void digest(val_list& vlist, u_char result[SHA256_DIGEST_LENGTH]); + template + static void digest(const T& vlist, u_char result[SHA256_DIGEST_LENGTH]) + { digest_all(Hash_SHA256, vlist, result); } SHA256Val(); ~SHA256Val(); diff --git a/src/Stats.cc b/src/Stats.cc index 4ab911507e..f584ed7a23 100644 --- a/src/Stats.cc +++ b/src/Stats.cc @@ -314,8 +314,8 @@ void ProfileLogger::Log() { Ref(file); mgr.Dispatch(new Event(profiling_update, { - new Val(file), - val_mgr->GetBool(expensive), + make_intrusive(file), + {AdoptRef{}, val_mgr->GetBool(expensive)}, })); } } diff --git a/src/Stmt.cc b/src/Stmt.cc index 172f54014b..2e90592dd6 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -151,15 +151,12 @@ IntrusivePtr ExprListStmt::Exec(Frame* f, stmt_flow_type& flow) const last_access = network_time; flow = FLOW_NEXT; - val_list* vals = eval_list(f, l.get()); + auto vals = eval_list(f, l.get()); + if ( vals ) - { - auto result = DoExec(vals, flow); - delete_vals(vals); - return result; - } - else - return nullptr; + return DoExec(std::move(*vals), flow); + + return nullptr; } void ExprListStmt::Describe(ODesc* d) const @@ -169,11 +166,6 @@ void ExprListStmt::Describe(ODesc* d) const DescribeDone(d); } -void ExprListStmt::PrintVals(ODesc* d, val_list* vals, int offset) const - { - describe_vals(vals, d, offset); - } - TraversalCode ExprListStmt::Traverse(TraversalCallback* cb) const { TraversalCode tc = cb->PreStmt(this); @@ -206,13 +198,13 @@ static IntrusivePtr lookup_enum_val(const char* module_name, const char return et->GetVal(index); } -static void print_log(val_list* vals) +static void print_log(const std::vector>& vals) { auto plval = lookup_enum_val("Log", "PRINTLOG"); auto record = make_intrusive(internal_type("Log::PrintLogInfo")->AsRecordType()); auto vec = make_intrusive(internal_type("string_vec")->AsVectorType()); - for ( const auto& val : *vals ) + for ( const auto& val : vals ) { ODesc d(DESC_READABLE); val->Describe(&d); @@ -224,7 +216,8 @@ static void print_log(val_list* vals) log_mgr->Write(plval.get(), record.get()); } -IntrusivePtr PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) const +IntrusivePtr PrintStmt::DoExec(std::vector> vals, + stmt_flow_type& /* flow */) const { RegisterAccess(); @@ -234,9 +227,9 @@ IntrusivePtr PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) BroFile* f = print_stdout; int offset = 0; - if ( vals->length() > 0 && (*vals)[0]->Type()->Tag() == TYPE_FILE ) + if ( vals.size() > 0 && (vals)[0]->Type()->Tag() == TYPE_FILE ) { - f = (*vals)[0]->AsFile(); + f = (vals)[0]->AsFile(); if ( ! f->IsOpen() ) return nullptr; @@ -277,7 +270,7 @@ IntrusivePtr PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) d.SetFlush(0); d.SetStyle(style); - PrintVals(&d, vals, offset); + describe_vals(vals, &d, offset); f->Write(d.Description(), d.Len()); } else @@ -286,7 +279,7 @@ IntrusivePtr PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) d.SetFlush(0); d.SetStyle(style); - PrintVals(&d, vals, offset); + describe_vals(vals, &d, offset); f->Write("\n", 1); } @@ -966,13 +959,10 @@ EventStmt::EventStmt(IntrusivePtr arg_e) IntrusivePtr EventStmt::Exec(Frame* f, stmt_flow_type& flow) const { RegisterAccess(); - val_list* args = eval_list(f, event_expr->Args()); + auto args = eval_list(f, event_expr->Args()); if ( args ) - { - mgr.QueueEvent(event_expr->Handler(), std::move(*args)); - delete args; - } + mgr.QueueUncheckedEvent(event_expr->Handler(), std::move(*args)); flow = FLOW_NEXT; return nullptr; diff --git a/src/Stmt.h b/src/Stmt.h index 950d733d78..78cb91ae29 100644 --- a/src/Stmt.h +++ b/src/Stmt.h @@ -95,10 +95,10 @@ protected: ~ExprListStmt() override; IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; - virtual IntrusivePtr DoExec(val_list* vals, stmt_flow_type& flow) const = 0; + virtual IntrusivePtr DoExec(std::vector> vals, + stmt_flow_type& flow) const = 0; void Describe(ODesc* d) const override; - void PrintVals(ODesc* d, val_list* vals, int offset) const; IntrusivePtr l; }; @@ -109,7 +109,8 @@ public: explicit PrintStmt(L&& l) : ExprListStmt(STMT_PRINT, std::forward(l)) { } protected: - IntrusivePtr DoExec(val_list* vals, stmt_flow_type& flow) const override; + IntrusivePtr DoExec(std::vector> vals, + stmt_flow_type& flow) const override; }; class ExprStmt : public Stmt { diff --git a/src/Val.cc b/src/Val.cc index b72d9d7e95..a366b8bcd7 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -3292,6 +3292,24 @@ void describe_vals(const val_list* vals, ODesc* d, int offset) } } +void describe_vals(const std::vector>& vals, + ODesc* d, size_t offset) + { + if ( ! d->IsReadable() ) + { + d->Add(vals.size()); + d->SP(); + } + + for ( auto i = offset; i < vals.size(); ++i ) + { + if ( i > offset && d->IsReadable() && d->Style() != RAW_STYLE ) + d->Add(", "); + + vals[i]->Describe(d); + } + } + void delete_vals(val_list* vals) { if ( vals ) diff --git a/src/Val.h b/src/Val.h index 7d944e9760..da5d9afba5 100644 --- a/src/Val.h +++ b/src/Val.h @@ -1042,6 +1042,8 @@ extern int same_val(const Val* v1, const Val* v2); extern int same_atomic_val(const Val* v1, const Val* v2); extern bool is_atomic_val(const Val* v); extern void describe_vals(const val_list* vals, ODesc* d, int offset=0); +extern void describe_vals(const std::vector>& vals, + ODesc* d, size_t offset = 0); extern void delete_vals(val_list* vals); // True if the given Val* has a vector type. diff --git a/src/ZeekArgs.cc b/src/ZeekArgs.cc new file mode 100644 index 0000000000..810da7f1dc --- /dev/null +++ b/src/ZeekArgs.cc @@ -0,0 +1,15 @@ +#include "ZeekArgs.h" +#include "IntrusivePtr.h" +#include "Val.h" + +zeek::Args zeek::val_list_to_args(const val_list* vl) + { + zeek::Args rval; + rval.reserve(vl->length()); + + for ( auto& v : *vl ) + rval.emplace_back(AdoptRef{}, v); + + return rval; + } + diff --git a/src/ZeekArgs.h b/src/ZeekArgs.h new file mode 100644 index 0000000000..a18d186863 --- /dev/null +++ b/src/ZeekArgs.h @@ -0,0 +1,27 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include "BroList.h" + +#include + +class Val; +template class IntrusivePtr; + +namespace zeek { + +using Args = std::vector>; + +/** + * Converts a legacy-style argument list for use in modern Zeek function + * calling or event queueing APIs. + * @param vl the argument list to convert, the returned value takes ownership + * of a reference to each element in the list, but not ownership of the list + * itself. + * @return the converted argument list + * + */ +Args val_list_to_args(const val_list* vl); + +} // namespace zeek diff --git a/src/broker/messaging.bif b/src/broker/messaging.bif index 95fe80c0a1..6217facb41 100644 --- a/src/broker/messaging.bif +++ b/src/broker/messaging.bif @@ -83,7 +83,13 @@ type Broker::Event: record; function Broker::make_event%(...%): Broker::Event %{ bro_broker::Manager::ScriptScopeGuard ssg; - auto rval = broker_mgr->MakeEvent(@ARGS@, frame); + const auto& bif_args = @ARGS@; + val_list args(bif_args->size()); + + for ( auto i = 0u; i < bif_args->size(); ++i ) + args.push_back((*bif_args)[i].get()); + + auto rval = broker_mgr->MakeEvent(&args, frame); return rval; %} @@ -98,11 +104,11 @@ function Broker::make_event%(...%): Broker::Event ## Returns: true if the message is sent. function Broker::publish%(topic: string, ...%): bool %{ - val_list* bif_args = @ARGS@; - val_list args(bif_args->length() - 1); + const auto& bif_args = @ARGS@; + val_list args(bif_args->size() - 1); - for ( auto i = 1; i < bif_args->length(); ++i ) - args.push_back((*bif_args)[i]); + for ( auto i = 1u; i < bif_args->size(); ++i ) + args.push_back((*bif_args)[i].get()); auto rval = publish_event_args(args, topic->AsString(), frame); return val_mgr->GetBool(rval); @@ -188,11 +194,11 @@ function Cluster::publish_rr%(pool: Pool, key: string, ...%): bool if ( ! topic->AsString()->Len() ) return val_mgr->GetFalse(); - val_list* bif_args = @ARGS@; - val_list args(bif_args->length() - 2); + const auto& bif_args = @ARGS@; + val_list args(bif_args->size() - 2); - for ( auto i = 2; i < bif_args->length(); ++i ) - args.push_back((*bif_args)[i]); + for ( auto i = 2u; i < bif_args->size(); ++i ) + args.push_back((*bif_args)[i].get()); auto rval = publish_event_args(args, topic->AsString(), frame); return val_mgr->GetBool(rval); @@ -225,11 +231,11 @@ function Cluster::publish_hrw%(pool: Pool, key: any, ...%): bool if ( ! topic->AsString()->Len() ) return val_mgr->GetFalse(); - val_list* bif_args = @ARGS@; - val_list args(bif_args->length() - 2); + const auto& bif_args = @ARGS@; + val_list args(bif_args->size() - 2); - for ( auto i = 2; i < bif_args->length(); ++i ) - args.push_back((*bif_args)[i]); + for ( auto i = 2u; i < bif_args->size(); ++i ) + args.push_back((*bif_args)[i].get()); auto rval = publish_event_args(args, topic->AsString(), frame); return val_mgr->GetBool(rval); diff --git a/src/main.cc b/src/main.cc index 0c4e22e28a..76be15b2d7 100644 --- a/src/main.cc +++ b/src/main.cc @@ -218,7 +218,7 @@ void done_with_network() mgr.Drain(); // Don't propagate this event to remote clients. mgr.Dispatch(new Event(net_done, - {new Val(timer_mgr->Time(), TYPE_TIME)}), + {make_intrusive(timer_mgr->Time(), TYPE_TIME)}), true); } diff --git a/src/plugin/Manager.cc b/src/plugin/Manager.cc index c7d52a3100..60be0212d7 100644 --- a/src/plugin/Manager.cc +++ b/src/plugin/Manager.cc @@ -1,5 +1,6 @@ // See the file "COPYING" in the main distribution directory for copyright. +#include #include #include #include @@ -619,15 +620,21 @@ int Manager::HookLoadFile(const Plugin::LoadType type, const string& file, const return rc; } -std::pair Manager::HookCallFunction(const Func* func, Frame* parent, val_list* vargs) const +std::pair Manager::HookCallFunction(const Func* func, Frame* parent, const zeek::Args& vecargs) const { HookArgumentList args; + std::optional vargs; if ( HavePluginForHook(META_HOOK_PRE) ) { + vargs = val_list(vecargs.size()); + + for ( const auto& v : vecargs ) + vargs->push_back(v.get()); + args.push_back(HookArgument(func)); args.push_back(HookArgument(parent)); - args.push_back(HookArgument(vargs)); + args.push_back(HookArgument(&vargs.value())); MetaHookPre(HOOK_CALL_FUNCTION, args); } @@ -637,11 +644,19 @@ std::pair Manager::HookCallFunction(const Func* func, Frame* parent, if ( l ) { + if ( ! vargs ) + { + vargs = val_list(vecargs.size()); + + for ( const auto& v : vecargs ) + vargs->push_back(v.get()); + } + for ( hook_list::iterator i = l->begin(); i != l->end(); ++i ) { Plugin* p = (*i).second; - v = p->HookCallFunction(func, parent, vargs); + v = p->HookCallFunction(func, parent, &vargs.value()); if ( v.first ) break; diff --git a/src/plugin/Manager.h b/src/plugin/Manager.h index 8127a77369..25c0235ebf 100644 --- a/src/plugin/Manager.h +++ b/src/plugin/Manager.h @@ -6,11 +6,11 @@ #include #include - #include "Plugin.h" #include "Component.h" #include "../Reporter.h" +#include "../ZeekArgs.h" namespace plugin { @@ -253,7 +253,7 @@ public: * functions and events, it may be any Val and must be ignored). If no * plugin handled the call, the method returns null. */ - std::pair HookCallFunction(const Func* func, Frame *parent, val_list* args) const; + std::pair HookCallFunction(const Func* func, Frame* parent, const zeek::Args& args) const; /** * Hook that filters the queuing of an event. diff --git a/src/plugin/Plugin.h b/src/plugin/Plugin.h index 7e8a35427c..b218c693d7 100644 --- a/src/plugin/Plugin.h +++ b/src/plugin/Plugin.h @@ -19,6 +19,7 @@ class ODesc; class Frame; class Func; class Event; +template class IntrusivePtr; namespace threading { struct Field; diff --git a/src/zeek.bif b/src/zeek.bif index cbd7bc0b54..9b41b98397 100644 --- a/src/zeek.bif +++ b/src/zeek.bif @@ -267,7 +267,7 @@ static void do_fmt(const char*& fmt, Val* v, ODesc* d) ++fmt; } -static int next_fmt(const char*& fmt, val_list* args, ODesc* d, int& n) +static int next_fmt(const char*& fmt, const zeek::Args* args, ODesc* d, int& n) { const char* fp = fmt; @@ -290,10 +290,10 @@ static int next_fmt(const char*& fmt, val_list* args, ODesc* d, int& n) return next_fmt(fmt, args, d, n); } - if ( ++n >= args->length() ) + if ( ++n >= static_cast(args->size()) ) return 0; - do_fmt(fmt, (*args)[n], d); + do_fmt(fmt, (*args)[n].get(), d); return *fmt != '\0'; } @@ -1413,12 +1413,12 @@ function sort%(v: any, ...%) : any BroType* elt_type = v->Type()->YieldType(); Func* comp = 0; - if ( @ARG@.length() > 2 ) + if ( @ARG@.size() > 2 ) builtin_error("sort() called with extraneous argument"); - if ( @ARG@.length() == 2 ) + if ( @ARG@.size() == 2 ) { - Val* comp_val = @ARG@[1]; + Val* comp_val = @ARG@[1].get(); if ( ! IsFunc(comp_val->Type()->Tag()) ) { builtin_error("second argument to sort() needs to be comparison function"); @@ -1483,12 +1483,12 @@ function order%(v: any, ...%) : index_vec BroType* elt_type = v->Type()->YieldType(); Func* comp = 0; - if ( @ARG@.length() > 2 ) + if ( @ARG@.size() > 2 ) builtin_error("order() called with extraneous argument"); - if ( @ARG@.length() == 2 ) + if ( @ARG@.size() == 2 ) { - Val* comp_val = @ARG@[1]; + Val* comp_val = @ARG@[1].get(); if ( ! IsFunc(comp_val->Type()->Tag()) ) { builtin_error("second argument to order() needs to be comparison function"); @@ -1595,7 +1595,7 @@ function cat_sep%(sep: string, def: string, ...%): string int pre_size = 0; - loop_over_list(@ARG@, i) + for ( auto i = 0u; i < @ARG@.size(); ++i ) { // Skip named parameters. if ( i < 2 ) @@ -1604,7 +1604,7 @@ function cat_sep%(sep: string, def: string, ...%): string if ( i > 2 ) d.Add(sep->CheckString(), 0); - Val* v = @ARG@[i]; + Val* v = @ARG@[i].get(); if ( v->Type()->Tag() == TYPE_STRING && ! v->AsString()->Len() ) v = def; @@ -1660,7 +1660,7 @@ function fmt%(...%): string if ( @ARGC@ == 0 ) return val_mgr->GetEmptyString(); - Val* fmt_v = @ARG@[0]; + Val* fmt_v = @ARG@[0].get(); // Type of fmt_v will be string here, check_built_in_call() in Func.cc // checks that. @@ -1674,13 +1674,13 @@ function fmt%(...%): string while ( next_fmt(fmt, @ARGS@, &d, n) ) ; - if ( n < @ARGC@ - 1 ) + if ( n < static_cast(@ARGC@) - 1 ) { builtin_error("too many arguments for format", fmt_v); return val_mgr->GetEmptyString(); } - else if ( n >= @ARGC@ ) + else if ( n >= static_cast(@ARGC@) ) { builtin_error("too few arguments for format", fmt_v); return val_mgr->GetEmptyString(); @@ -1703,7 +1703,7 @@ function print_raw%(...%): bool %{ ODesc d(DESC_READABLE); d.SetStyle(RAW_STYLE); - describe_vals(&@ARG@, &d, 0); + describe_vals(@ARG@, &d, 0); printf("%.*s", d.Len(), d.Description()); return val_mgr->GetBool(true); %}