Use vector<IntrusivePtr<Val>> for Func::Call and Event queuing args

This change may break BIFs that use @ARGS@, @ARG@, or @ARGC@ since their
types have changed.
This commit is contained in:
Jon Siwek 2020-03-20 18:03:04 -07:00
parent 94656c2308
commit 4e1ac4e124
29 changed files with 367 additions and 305 deletions

6
NEWS
View file

@ -27,10 +27,14 @@ Changed Functionality
--------------------- ---------------------
- Several C++ functions have been changed to pass smart pointers - 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 code more robust. External plugins may need to be updated to this
API change. 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<IntrusivePtr<Val>>``
rather than a ``val_list`` (i.e. ``List<Val*>``).
Removed Functionality Removed Functionality
--------------------- ---------------------

@ -1 +1 @@
Subproject commit b3a5d01c041b78a9e50544ac891c5e0d35c116f7 Subproject commit 75f645ac9bdfd141f549b7e1a197459f2ad518be

View file

@ -282,6 +282,7 @@ set(MAIN_SRCS
Val.cc Val.cc
Var.cc Var.cc
WeirdState.cc WeirdState.cc
ZeekArgs.cc
bsd-getopt-long.c bsd-getopt-long.c
bro_inet_ntop.c bro_inet_ntop.c
cq.c cq.c

View file

@ -18,7 +18,7 @@ EventMgr mgr;
uint64_t num_events_queued = 0; uint64_t num_events_queued = 0;
uint64_t num_events_dispatched = 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, SourceID arg_src, analyzer::ID arg_aid, TimerMgr* arg_mgr,
BroObj* arg_obj) BroObj* arg_obj)
: handler(arg_handler), : handler(arg_handler),
@ -33,14 +33,6 @@ Event::Event(EventHandlerPtr arg_handler, val_list arg_args,
Ref(obj); 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 void Event::Describe(ODesc* d) const
{ {
if ( d->IsReadable() ) if ( d->IsReadable() )
@ -53,7 +45,7 @@ void Event::Describe(ODesc* d) const
if ( ! d->IsBinary() ) if ( ! d->IsBinary() )
d->Add("("); d->Add("(");
describe_vals(&args, d); describe_vals(args, d);
if ( ! d->IsBinary() ) if ( ! d->IsBinary() )
d->Add("("); d->Add("(");
} }
@ -68,7 +60,7 @@ void Event::Dispatch(bool no_remote)
try try
{ {
handler->Call(&args, no_remote); handler->Call(args, no_remote);
} }
catch ( InterpreterException& e ) catch ( InterpreterException& e )
@ -106,12 +98,19 @@ EventMgr::~EventMgr()
Unref(src_val); 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, void EventMgr::QueueEvent(const EventHandlerPtr &h, val_list vl,
SourceID src, analyzer::ID aid, SourceID src, analyzer::ID aid,
TimerMgr* mgr, BroObj* obj) TimerMgr* mgr, BroObj* obj)
{ {
if ( h ) 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 else
{ {
for ( const auto& v : vl ) 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) void EventMgr::QueueEvent(Event* event)
{ {
bool done = PLUGIN_HOOK_WITH_RESULT(HOOK_QUEUE_EVENT, HookQueueEvent(event), false); bool done = PLUGIN_HOOK_WITH_RESULT(HOOK_QUEUE_EVENT, HookQueueEvent(event), false);

View file

@ -6,20 +6,15 @@
#include "analyzer/Analyzer.h" #include "analyzer/Analyzer.h"
#include "iosource/IOSource.h" #include "iosource/IOSource.h"
#include "Flare.h" #include "Flare.h"
#include "ZeekArgs.h"
class EventMgr; 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 { class Event : public BroObj {
public: public:
Event(EventHandlerPtr handler, val_list args, Event(EventHandlerPtr handler, zeek::Args args,
SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0, SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0,
TimerMgr* mgr = 0, BroObj* obj = 0); TimerMgr* mgr = nullptr, BroObj* obj = nullptr);
Event(EventHandlerPtr handler, val_list* args,
SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0,
TimerMgr* mgr = 0, BroObj* obj = 0);
void SetNext(Event* n) { next_event = n; } void SetNext(Event* n) { next_event = n; }
Event* NextEvent() const { return next_event; } Event* NextEvent() const { return next_event; }
@ -28,7 +23,7 @@ public:
analyzer::ID Analyzer() const { return aid; } analyzer::ID Analyzer() const { return aid; }
TimerMgr* Mgr() const { return mgr; } TimerMgr* Mgr() const { return mgr; }
EventHandlerPtr Handler() const { return handler; } 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; void Describe(ODesc* d) const override;
@ -40,7 +35,7 @@ protected:
void Dispatch(bool no_remote = false); void Dispatch(bool no_remote = false);
EventHandlerPtr handler; EventHandlerPtr handler;
val_list args; zeek::Args args;
SourceID src; SourceID src;
analyzer::ID aid; analyzer::ID aid;
TimerMgr* mgr; TimerMgr* mgr;
@ -64,12 +59,11 @@ public:
// against the case where there's no handlers (one usually also does that // 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 // because it would be a waste of effort to construct all the event
// arguments when there's no handlers to consume them). // 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, void QueueEventFast(const EventHandlerPtr &h, val_list vl,
SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0, SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0,
TimerMgr* mgr = 0, BroObj* obj = 0) TimerMgr* mgr = 0, BroObj* obj = 0);
{
QueueEvent(new Event(h, std::move(vl), src, aid, mgr, obj));
}
// Queues an event if there's an event handler (or remote consumer). This // Queues an event if there's an event handler (or remote consumer). This
// function always takes ownership of decrementing the reference count of // 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 // checked for event handler existence, you may wish to call
// QueueEventFast() instead of this function to prevent the redundant // QueueEventFast() instead of this function to prevent the redundant
// existence check. // existence check.
// TODO: deprecate
/* [[deprecated("Remove in v4.1. Use IntrusivePtr overload instead.")]] */
void QueueEvent(const EventHandlerPtr &h, val_list vl, void QueueEvent(const EventHandlerPtr &h, val_list vl,
SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0, SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0,
TimerMgr* mgr = 0, BroObj* obj = 0); TimerMgr* mgr = 0, BroObj* obj = 0);
@ -85,13 +81,32 @@ public:
// pointer instead of by value. This function takes ownership of the // pointer instead of by value. This function takes ownership of the
// memory pointed to by 'vl' as well as decrementing the reference count of // memory pointed to by 'vl' as well as decrementing the reference count of
// each of its elements. // each of its elements.
// TODO: deprecate
/* [[deprecated("Remove in v4.1. Use IntrusivePtr overload instead.")]] */
void QueueEvent(const EventHandlerPtr &h, val_list* vl, void QueueEvent(const EventHandlerPtr &h, val_list* vl,
SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0, SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0,
TimerMgr* mgr = 0, BroObj* obj = 0) TimerMgr* mgr = 0, BroObj* obj = 0);
{
QueueEvent(h, std::move(*vl), src, aid, mgr, obj); /**
delete vl; * 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); void Dispatch(Event* event, bool no_remote = false);

View file

@ -60,7 +60,7 @@ void EventHandler::SetLocalHandler(Func* f)
local = 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 #ifdef PROFILE_BRO_FUNCTIONS
DEBUG_MSG("Event: %s\n", Name()); 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. // Send event in form [name, xs...] where xs represent the arguments.
broker::vector xs; broker::vector xs;
xs.reserve(vl->length()); xs.reserve(vl.size());
bool valid_args = true; 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 ) if ( opt_data )
xs.emplace_back(move(*opt_data)); xs.emplace_back(move(*opt_data));
@ -115,14 +115,9 @@ void EventHandler::Call(val_list* vl, bool no_remote)
if ( local ) if ( local )
// No try/catch here; we pass exceptions upstream. // No try/catch here; we pass exceptions upstream.
local->Call(vl); 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 ) if ( ! new_event )
return; return;
@ -132,7 +127,7 @@ void EventHandler::NewEvent(val_list* vl)
return; return;
RecordType* args = FType()->Args(); RecordType* args = FType()->Args();
VectorVal* vargs = new VectorVal(call_argument_vector); auto vargs = make_intrusive<VectorVal>(call_argument_vector);
for ( int i = 0; i < args->NumFields(); i++ ) for ( int i = 0; i < args->NumFields(); i++ )
{ {
@ -151,19 +146,15 @@ void EventHandler::NewEvent(val_list* vl)
if ( fdefault ) if ( fdefault )
rec->Assign(2, std::move(fdefault)); rec->Assign(2, std::move(fdefault));
if ( i < vl->length() && (*vl)[i] ) if ( i < static_cast<int>(vl.size()) && vl[i] )
{ rec->Assign(3, vl[i]);
Val* val = (*vl)[i];
Ref(val);
rec->Assign(3, val);
}
vargs->Assign(i, std::move(rec)); vargs->Assign(i, std::move(rec));
} }
Event* ev = new Event(new_event, { Event* ev = new Event(new_event, {
new StringVal(name), make_intrusive<StringVal>(name),
vargs, std::move(vargs),
}); });
mgr.Dispatch(ev); mgr.Dispatch(ev);
} }

View file

@ -3,6 +3,7 @@
#pragma once #pragma once
#include "BroList.h" #include "BroList.h"
#include "ZeekArgs.h"
#include <unordered_set> #include <unordered_set>
#include <string> #include <string>
@ -31,7 +32,7 @@ public:
auto_publish.erase(topic); 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. // Returns true if there is at least one local or remote handler.
explicit operator bool() const; explicit operator bool() const;
@ -52,7 +53,7 @@ public:
bool GenerateAlways() { return generate_always; } bool GenerateAlways() { return generate_always; }
private: 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; const char* name;
Func* local; Func* local;

View file

@ -3884,12 +3884,11 @@ IntrusivePtr<Val> FlattenExpr::Fold(Val* v) const
return l; 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) double t, TimerMgr* arg_tmgr)
: Timer(t, TIMER_SCHEDULE), : 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() ScheduleTimer::~ScheduleTimer()
@ -3898,7 +3897,7 @@ ScheduleTimer::~ScheduleTimer()
void ScheduleTimer::Dispatch(double /* t */, int /* is_expire */) 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<Expr> arg_when, ScheduleExpr::ScheduleExpr(IntrusivePtr<Expr> arg_when,
@ -3937,7 +3936,7 @@ IntrusivePtr<Val> ScheduleExpr::Eval(Frame* f) const
if ( when->Type()->Tag() == TYPE_INTERVAL ) if ( when->Type()->Tag() == TYPE_INTERVAL )
dt += network_time; dt += network_time;
val_list* args = eval_list(f, event->Args()); auto args = eval_list(f, event->Args());
if ( args ) if ( args )
{ {
@ -3946,7 +3945,7 @@ IntrusivePtr<Val> ScheduleExpr::Eval(Frame* f) const
if ( ! tmgr ) if ( ! tmgr )
tmgr = timer_mgr; 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; return nullptr;
@ -4236,7 +4235,7 @@ IntrusivePtr<Val> CallExpr::Eval(Frame* f) const
IntrusivePtr<Val> ret; IntrusivePtr<Val> ret;
auto func_val = func->Eval(f); 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 ) if ( func_val && v )
{ {
@ -4246,16 +4245,11 @@ IntrusivePtr<Val> CallExpr::Eval(Frame* f) const
if ( f ) if ( f )
f->SetCall(this); f->SetCall(this);
ret = func->Call(v, f); ret = func->Call(*v, f);
if ( f ) if ( f )
f->SetCall(current_call); f->SetCall(current_call);
// Don't Unref() the arguments, as Func::Call already did that.
delete v;
} }
else
delete_vals(v);
return ret; return ret;
} }
@ -4448,10 +4442,8 @@ IntrusivePtr<Val> EventExpr::Eval(Frame* f) const
if ( IsError() ) if ( IsError() )
return nullptr; return nullptr;
val_list* v = eval_list(f, args.get()); auto v = eval_list(f, args.get());
mgr.QueueEvent(handler, std::move(*v)); mgr.QueueUncheckedEvent(handler, std::move(*v));
delete v;
return nullptr; return nullptr;
} }
@ -5176,36 +5168,23 @@ int check_and_promote_exprs_to_type(ListExpr* const elements, BroType* type)
return 1; return 1;
} }
val_list* eval_list(Frame* f, const ListExpr* l) std::optional<std::vector<IntrusivePtr<Val>>> eval_list(Frame* f, const ListExpr* l)
{ {
const expr_list& e = l->Exprs(); const expr_list& e = l->Exprs();
val_list* v = new val_list(e.length()); auto rval = std::make_optional<std::vector<IntrusivePtr<Val>>>();
bool success = true; rval->reserve(e.length());
for ( const auto& expr : e ) for ( const auto& expr : e )
{ {
auto ev = expr->Eval(f); auto ev = expr->Eval(f);
if ( ! ev ) if ( ! ev )
{ return {};
success = false;
break;
}
v->push_back(ev.release()); rval->emplace_back(std::move(ev));
} }
if ( ! success ) return rval;
{
for ( const auto& val : *v )
Unref(val);
delete v;
return nullptr;
}
else
return v;
} }
bool expr_greater(const Expr* e1, const Expr* e2) bool expr_greater(const Expr* e1, const Expr* e2)

View file

@ -9,10 +9,13 @@
#include "EventHandler.h" #include "EventHandler.h"
#include "TraverseTypes.h" #include "TraverseTypes.h"
#include "Val.h" #include "Val.h"
#include "ZeekArgs.h"
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#include <utility> #include <utility>
#include <optional>
using std::string; using std::string;
@ -737,15 +740,15 @@ protected:
class ScheduleTimer : public Timer { class ScheduleTimer : public Timer {
public: public:
ScheduleTimer(EventHandlerPtr event, val_list* args, double t, ScheduleTimer(EventHandlerPtr event, zeek::Args args,
TimerMgr* tmgr); double t, TimerMgr* tmgr);
~ScheduleTimer() override; ~ScheduleTimer() override;
void Dispatch(double t, int is_expire) override; void Dispatch(double t, int is_expire) override;
protected: protected:
EventHandlerPtr event; EventHandlerPtr event;
val_list args; zeek::Args args;
TimerMgr* tmgr; 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_args(ListExpr* args, RecordType* types);
extern int check_and_promote_exprs_to_type(ListExpr* elements, BroType* type); 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 // Returns a ListExpr simplified down to a list a values, or nil
// pointer if they couldn't all be reduced. // if they couldn't all be reduced.
val_list* eval_list(Frame* f, const ListExpr* l); std::optional<std::vector<IntrusivePtr<Val>>> eval_list(Frame* f, const ListExpr* l);
// Returns true if e1 is "greater" than e2 - here "greater" is just // Returns true if e1 is "greater" than e2 - here "greater" is just
// a heuristic, used with commutative operators to put them into // a heuristic, used with commutative operators to put them into

View file

@ -325,7 +325,7 @@ void BroFile::RaiseOpenEvent()
return; return;
Ref(this); Ref(this);
Event* event = new ::Event(::file_opened, {new Val(this)}); Event* event = new ::Event(::file_opened, {make_intrusive<Val>(this)});
mgr.Dispatch(event, true); mgr.Dispatch(event, true);
} }

View file

@ -14,7 +14,7 @@
vector<Frame*> g_frame_stack; vector<Frame*> 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; size = arg_size;
frame = new Val*[size]; frame = new Val*[size];

View file

@ -5,6 +5,7 @@
#include "BroList.h" // for typedef val_list #include "BroList.h" // for typedef val_list
#include "Obj.h" #include "Obj.h"
#include "IntrusivePtr.h" #include "IntrusivePtr.h"
#include "ZeekArgs.h"
#include <unordered_map> #include <unordered_map>
#include <string> #include <string>
@ -28,7 +29,7 @@ public:
* @param func the function that is creating this frame * @param func the function that is creating this frame
* @param fn_args the arguments being passed to that function. * @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 * 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 * @return the arguments passed to the function that this frame
* is associated with. * 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. * Change the function that the frame is associated with.
@ -283,7 +284,7 @@ private:
/** The function this frame is associated with. */ /** The function this frame is associated with. */
const BroFunc* function; const BroFunc* function;
/** The arguments to the function that this Frame is associated with. */ /** 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. */ /** The next statement to be evaluted in the context of this frame. */
Stmt* next_stmt; Stmt* next_stmt;

View file

@ -79,19 +79,16 @@ std::string render_call_stack()
auto name = ci.func->Name(); auto name = ci.func->Name();
std::string arg_desc; std::string arg_desc;
if ( ci.args ) for ( const auto& arg : ci.args )
{ {
for ( const auto& arg : *ci.args ) ODesc d;
{ d.SetShort();
ODesc d; arg->Describe(&d);
d.SetShort();
arg->Describe(&d);
if ( ! arg_desc.empty() ) if ( ! arg_desc.empty() )
arg_desc += ", "; arg_desc += ", ";
arg_desc += d.Description(); arg_desc += d.Description();
}
} }
rval += fmt("#%d %s(%s)", lvl, name, arg_desc.data()); rval += fmt("#%d %s(%s)", lvl, name, arg_desc.data());
@ -143,7 +140,7 @@ IntrusivePtr<Func> Func::DoClone()
return {NewRef{}, this}; 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()); d->Add(Name());
@ -153,10 +150,10 @@ void Func::DescribeDebug(ODesc* d, const val_list* args) const
{ {
d->Add("("); 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). // Handle varargs case (more args than formals).
if ( i >= func_args->NumFields() ) if ( i >= static_cast<size_t>(func_args->NumFields()) )
{ {
d->Add("vararg"); d->Add("vararg");
d->Add(i - func_args->NumFields()); d->Add(i - func_args->NumFields());
@ -167,7 +164,7 @@ void Func::DescribeDebug(ODesc* d, const val_list* args) const
d->Add(" = '"); d->Add(" = '");
(*args)[i]->Describe(d); (*args)[i]->Describe(d);
if ( i < args->length() - 1 ) if ( i < args->size() - 1 )
d->Add("', "); d->Add("', ");
else else
d->Add("'"); d->Add("'");
@ -217,7 +214,7 @@ void Func::CopyStateInto(Func* other) const
other->unique_id = unique_id; other->unique_id = unique_id;
} }
std::pair<bool, Val*> Func::HandlePluginResult(std::pair<bool, Val*> plugin_result, val_list* args, function_flavor flavor) const std::pair<bool, Val*> Func::HandlePluginResult(std::pair<bool, Val*> plugin_result, function_flavor flavor) const
{ {
// Helper function factoring out this code from BroFunc:Call() for // Helper function factoring out this code from BroFunc:Call() for
// better readability. // better readability.
@ -265,9 +262,6 @@ std::pair<bool, Val*> Func::HandlePluginResult(std::pair<bool, Val*> plugin_resu
} }
} }
for ( const auto& arg : *args )
Unref(arg);
return plugin_result; return plugin_result;
} }
@ -300,7 +294,12 @@ int BroFunc::IsPure() const
[](const Body& b) { return b.stmts->IsPure(); }); [](const Body& b) { return b.stmts->IsPure(); });
} }
IntrusivePtr<Val> BroFunc::Call(val_list* args, Frame* parent) const IntrusivePtr<Val> Func::Call(val_list* args, Frame* parent) const
{
return Call(zeek::val_list_to_args(args), parent);
}
IntrusivePtr<Val> BroFunc::Call(const zeek::Args& args, Frame* parent) const
{ {
#ifdef PROFILE_BRO_FUNCTIONS #ifdef PROFILE_BRO_FUNCTIONS
DEBUG_MSG("Function: %s\n", Name()); DEBUG_MSG("Function: %s\n", Name());
@ -312,7 +311,7 @@ IntrusivePtr<Val> BroFunc::Call(val_list* args, Frame* parent) const
std::pair<bool, Val*> plugin_result = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, HookCallFunction(this, parent, args), empty_hook_result); std::pair<bool, Val*> 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 ) if( plugin_result.first )
return {AdoptRef{}, plugin_result.second}; return {AdoptRef{}, plugin_result.second};
@ -321,13 +320,10 @@ IntrusivePtr<Val> BroFunc::Call(val_list* args, Frame* parent) const
{ {
// Can only happen for events and hooks. // Can only happen for events and hooks.
assert(Flavor() == FUNC_FLAVOR_EVENT || Flavor() == FUNC_FLAVOR_HOOK); 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; return Flavor() == FUNC_FLAVOR_HOOK ? IntrusivePtr{AdoptRef{}, val_mgr->GetTrue()} : nullptr;
} }
auto f = make_intrusive<Frame>(frame_size, this, args); auto f = make_intrusive<Frame>(frame_size, this, &args);
if ( closure ) if ( closure )
f->CaptureClosure(closure, outer_ids); f->CaptureClosure(closure, outer_ids);
@ -346,7 +342,7 @@ IntrusivePtr<Val> BroFunc::Call(val_list* args, Frame* parent) const
if ( g_trace_state.DoTrace() ) if ( g_trace_state.DoTrace() )
{ {
ODesc d; ODesc d;
DescribeDebug(&d, args); DescribeDebug(&d, &args);
g_trace_state.LogTrace("%s called: %s\n", g_trace_state.LogTrace("%s called: %s\n",
FType()->FlavorString().c_str(), d.Description()); FType()->FlavorString().c_str(), d.Description());
@ -362,19 +358,16 @@ IntrusivePtr<Val> BroFunc::Call(val_list* args, Frame* parent) const
body.stmts->GetLocationInfo()); body.stmts->GetLocationInfo());
// Fill in the rest of the frame with the function's arguments. // 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 ) if ( f->NthElement(j) != arg )
{
// Either not yet set, or somebody reassigned the frame slot. // Either not yet set, or somebody reassigned the frame slot.
Ref(arg); f->SetElement(j, arg->Ref());
f->SetElement(j, arg);
}
} }
f->Reset(args->length()); f->Reset(args.size());
try try
{ {
@ -421,11 +414,6 @@ IntrusivePtr<Val> BroFunc::Call(val_list* args, Frame* parent) const
call_stack.pop_back(); 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 ( Flavor() == FUNC_FLAVOR_HOOK )
{ {
if ( ! result ) if ( ! result )
@ -612,7 +600,7 @@ int BuiltinFunc::IsPure() const
return is_pure; return is_pure;
} }
IntrusivePtr<Val> BuiltinFunc::Call(val_list* args, Frame* parent) const IntrusivePtr<Val> BuiltinFunc::Call(const zeek::Args& args, Frame* parent) const
{ {
#ifdef PROFILE_BRO_FUNCTIONS #ifdef PROFILE_BRO_FUNCTIONS
DEBUG_MSG("Function: %s\n", Name()); DEBUG_MSG("Function: %s\n", Name());
@ -624,7 +612,7 @@ IntrusivePtr<Val> BuiltinFunc::Call(val_list* args, Frame* parent) const
std::pair<bool, Val*> plugin_result = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, HookCallFunction(this, parent, args), empty_hook_result); std::pair<bool, Val*> 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 ) if ( plugin_result.first )
return {AdoptRef{}, plugin_result.second}; return {AdoptRef{}, plugin_result.second};
@ -632,20 +620,16 @@ IntrusivePtr<Val> BuiltinFunc::Call(val_list* args, Frame* parent) const
if ( g_trace_state.DoTrace() ) if ( g_trace_state.DoTrace() )
{ {
ODesc d; ODesc d;
DescribeDebug(&d, args); DescribeDebug(&d, &args);
g_trace_state.LogTrace("\tBuiltin Function called: %s\n", d.Description()); g_trace_state.LogTrace("\tBuiltin Function called: %s\n", d.Description());
} }
const CallExpr* call_expr = parent ? parent->GetCall() : nullptr; const CallExpr* call_expr = parent ? parent->GetCall() : nullptr;
call_stack.emplace_back(CallInfo{call_expr, this, args}); call_stack.emplace_back(CallInfo{call_expr, this, args});
IntrusivePtr<Val> result{AdoptRef{}, func(parent, args)}; IntrusivePtr<Val> result{AdoptRef{}, func(parent, &args)};
call_stack.pop_back(); 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() ) if ( result && g_trace_state.DoTrace() )
{ {
ODesc d; ODesc d;
@ -663,6 +647,16 @@ void BuiltinFunc::Describe(ODesc* d) const
d->AddCount(is_pure); d->AddCount(is_pure);
} }
void builtin_error(const char* msg)
{
builtin_error(msg, IntrusivePtr<Val>{});
}
void builtin_error(const char* msg, IntrusivePtr<Val> arg)
{
builtin_error(msg, arg.get());
}
void builtin_error(const char* msg, BroObj* arg) void builtin_error(const char* msg, BroObj* arg)
{ {
auto emit = [=](const CallExpr* ce) auto emit = [=](const CallExpr* ce)

View file

@ -7,6 +7,7 @@
#include "IntrusivePtr.h" #include "IntrusivePtr.h"
#include "Type.h" /* for function_flavor */ #include "Type.h" /* for function_flavor */
#include "TraverseTypes.h" #include "TraverseTypes.h"
#include "ZeekArgs.h"
#include <utility> #include <utility>
#include <memory> #include <memory>
@ -30,7 +31,6 @@ class Scope;
class Func : public BroObj { class Func : public BroObj {
public: public:
enum Kind { BRO_FUNC, BUILTIN_FUNC }; enum Kind { BRO_FUNC, BUILTIN_FUNC };
explicit Func(Kind arg_kind); explicit Func(Kind arg_kind);
@ -50,7 +50,9 @@ public:
const vector<Body>& GetBodies() const { return bodies; } const vector<Body>& GetBodies() const { return bodies; }
bool HasBodies() const { return bodies.size(); } bool HasBodies() const { return bodies.size(); }
virtual IntrusivePtr<Val> Call(val_list* args, Frame* parent = 0) const = 0; // TODO: deprecate
virtual IntrusivePtr<Val> Call(val_list* args, Frame* parent = nullptr) const;
virtual IntrusivePtr<Val> Call(const zeek::Args& args, Frame* parent = nullptr) const = 0;
// Add a new event handler to an existing function (event). // Add a new event handler to an existing function (event).
virtual void AddBody(IntrusivePtr<Stmt> new_body, id_list* new_inits, virtual void AddBody(IntrusivePtr<Stmt> new_body, id_list* new_inits,
@ -67,7 +69,7 @@ public:
void SetName(const char* arg_name) { name = arg_name; } void SetName(const char* arg_name) { name = arg_name; }
void Describe(ODesc* d) const override = 0; 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<Func> DoClone(); virtual IntrusivePtr<Func> DoClone();
@ -84,7 +86,7 @@ protected:
void CopyStateInto(Func* other) const; void CopyStateInto(Func* other) const;
// Helper function for handling result of plugin hook. // Helper function for handling result of plugin hook.
std::pair<bool, Val*> HandlePluginResult(std::pair<bool, Val*> plugin_result, val_list* args, function_flavor flavor) const; std::pair<bool, Val*> HandlePluginResult(std::pair<bool, Val*> plugin_result, function_flavor flavor) const;
vector<Body> bodies; vector<Body> bodies;
IntrusivePtr<Scope> scope; IntrusivePtr<Scope> scope;
@ -102,7 +104,7 @@ public:
~BroFunc() override; ~BroFunc() override;
int IsPure() const override; int IsPure() const override;
IntrusivePtr<Val> Call(val_list* args, Frame* parent) const override; IntrusivePtr<Val> Call(const zeek::Args& args, Frame* parent) const override;
/** /**
* Adds adds a closure to the function. Closures are cloned and * Adds adds a closure to the function. Closures are cloned and
@ -169,7 +171,7 @@ private:
bool weak_closure_ref = false; 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 { class BuiltinFunc : public Func {
public: public:
@ -177,7 +179,7 @@ public:
~BuiltinFunc() override; ~BuiltinFunc() override;
int IsPure() const override; int IsPure() const override;
IntrusivePtr<Val> Call(val_list* args, Frame* parent) const override; IntrusivePtr<Val> Call(const zeek::Args& args, Frame* parent) const override;
built_in_func TheFunc() const { return func; } built_in_func TheFunc() const { return func; }
void Describe(ODesc* d) const override; 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<Val>);
extern void builtin_error(const char* msg, BroObj* arg);
extern void init_builtin_funcs(); extern void init_builtin_funcs();
extern void init_builtin_funcs_subdirs(); extern void init_builtin_funcs_subdirs();
@ -199,7 +203,7 @@ extern bool check_built_in_call(BuiltinFunc* f, CallExpr* call);
struct CallInfo { struct CallInfo {
const CallExpr* call; const CallExpr* call;
const Func* func; const Func* func;
const val_list* args; const zeek::Args& args;
}; };
// Struct that collects all the specifics defining a Func. Used for BroFuncs // Struct that collects all the specifics defining a Func. Used for BroFuncs

View file

@ -221,6 +221,26 @@ MD5Val::~MD5Val()
EVP_MD_CTX_free(ctx); 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<Val>& v)
{
digest_one(h, v.get());
}
IntrusivePtr<Val> MD5Val::DoClone(CloneState* state) IntrusivePtr<Val> MD5Val::DoClone(CloneState* state)
{ {
auto out = make_intrusive<MD5Val>(); auto out = make_intrusive<MD5Val>();
@ -236,39 +256,6 @@ IntrusivePtr<Val> MD5Val::DoClone(CloneState* state)
return state->NewClone(this, std::move(out)); 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() bool MD5Val::DoInit()
{ {
assert(! IsValid()); assert(! IsValid());
@ -389,28 +376,6 @@ IntrusivePtr<Val> SHA1Val::DoClone(CloneState* state)
return state->NewClone(this, std::move(out)); 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() bool SHA1Val::DoInit()
{ {
assert(! IsValid()); assert(! IsValid());
@ -535,28 +500,6 @@ IntrusivePtr<Val> SHA256Val::DoClone(CloneState* state)
return state->NewClone(this, std::move(out)); 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() bool SHA256Val::DoInit()
{ {
assert( ! IsValid() ); assert( ! IsValid() );

View file

@ -162,12 +162,26 @@ namespace probabilistic {
class HashVal : public OpaqueVal { class HashVal : public OpaqueVal {
public: public:
template <class T>
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 IsValid() const;
bool Init(); bool Init();
bool Feed(const void* data, size_t size); bool Feed(const void* data, size_t size);
IntrusivePtr<StringVal> Get(); IntrusivePtr<StringVal> Get();
protected: protected:
static void digest_one(EVP_MD_CTX* h, const Val* v);
static void digest_one(EVP_MD_CTX* h, const IntrusivePtr<Val>& v);
HashVal() { valid = false; } HashVal() { valid = false; }
explicit HashVal(OpaqueType* t); explicit HashVal(OpaqueType* t);
@ -182,11 +196,22 @@ private:
class MD5Val : public HashVal { class MD5Val : public HashVal {
public: public:
static void digest(val_list& vlist, u_char result[MD5_DIGEST_LENGTH]); template <class T>
static void digest(const T& vlist, u_char result[MD5_DIGEST_LENGTH])
{ digest_all(Hash_MD5, vlist, result); }
static void hmac(val_list& vlist, template <class T>
u_char key[MD5_DIGEST_LENGTH], static void hmac(const T& vlist,
u_char result[MD5_DIGEST_LENGTH]); 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();
~MD5Val(); ~MD5Val();
@ -207,7 +232,9 @@ private:
class SHA1Val : public HashVal { class SHA1Val : public HashVal {
public: public:
static void digest(val_list& vlist, u_char result[SHA_DIGEST_LENGTH]); template <class T>
static void digest(const T& vlist, u_char result[SHA_DIGEST_LENGTH])
{ digest_all(Hash_SHA1, vlist, result); }
SHA1Val(); SHA1Val();
~SHA1Val(); ~SHA1Val();
@ -228,7 +255,9 @@ private:
class SHA256Val : public HashVal { class SHA256Val : public HashVal {
public: public:
static void digest(val_list& vlist, u_char result[SHA256_DIGEST_LENGTH]); template <class T>
static void digest(const T& vlist, u_char result[SHA256_DIGEST_LENGTH])
{ digest_all(Hash_SHA256, vlist, result); }
SHA256Val(); SHA256Val();
~SHA256Val(); ~SHA256Val();

View file

@ -314,8 +314,8 @@ void ProfileLogger::Log()
{ {
Ref(file); Ref(file);
mgr.Dispatch(new Event(profiling_update, { mgr.Dispatch(new Event(profiling_update, {
new Val(file), make_intrusive<Val>(file),
val_mgr->GetBool(expensive), {AdoptRef{}, val_mgr->GetBool(expensive)},
})); }));
} }
} }

View file

@ -151,15 +151,12 @@ IntrusivePtr<Val> ExprListStmt::Exec(Frame* f, stmt_flow_type& flow) const
last_access = network_time; last_access = network_time;
flow = FLOW_NEXT; flow = FLOW_NEXT;
val_list* vals = eval_list(f, l.get()); auto vals = eval_list(f, l.get());
if ( vals ) if ( vals )
{ return DoExec(std::move(*vals), flow);
auto result = DoExec(vals, flow);
delete_vals(vals); return nullptr;
return result;
}
else
return nullptr;
} }
void ExprListStmt::Describe(ODesc* d) const void ExprListStmt::Describe(ODesc* d) const
@ -169,11 +166,6 @@ void ExprListStmt::Describe(ODesc* d) const
DescribeDone(d); 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 ExprListStmt::Traverse(TraversalCallback* cb) const
{ {
TraversalCode tc = cb->PreStmt(this); TraversalCode tc = cb->PreStmt(this);
@ -206,13 +198,13 @@ static IntrusivePtr<EnumVal> lookup_enum_val(const char* module_name, const char
return et->GetVal(index); return et->GetVal(index);
} }
static void print_log(val_list* vals) static void print_log(const std::vector<IntrusivePtr<Val>>& vals)
{ {
auto plval = lookup_enum_val("Log", "PRINTLOG"); auto plval = lookup_enum_val("Log", "PRINTLOG");
auto record = make_intrusive<RecordVal>(internal_type("Log::PrintLogInfo")->AsRecordType()); auto record = make_intrusive<RecordVal>(internal_type("Log::PrintLogInfo")->AsRecordType());
auto vec = make_intrusive<VectorVal>(internal_type("string_vec")->AsVectorType()); auto vec = make_intrusive<VectorVal>(internal_type("string_vec")->AsVectorType());
for ( const auto& val : *vals ) for ( const auto& val : vals )
{ {
ODesc d(DESC_READABLE); ODesc d(DESC_READABLE);
val->Describe(&d); val->Describe(&d);
@ -224,7 +216,8 @@ static void print_log(val_list* vals)
log_mgr->Write(plval.get(), record.get()); log_mgr->Write(plval.get(), record.get());
} }
IntrusivePtr<Val> PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) const IntrusivePtr<Val> PrintStmt::DoExec(std::vector<IntrusivePtr<Val>> vals,
stmt_flow_type& /* flow */) const
{ {
RegisterAccess(); RegisterAccess();
@ -234,9 +227,9 @@ IntrusivePtr<Val> PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */)
BroFile* f = print_stdout; BroFile* f = print_stdout;
int offset = 0; 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() ) if ( ! f->IsOpen() )
return nullptr; return nullptr;
@ -277,7 +270,7 @@ IntrusivePtr<Val> PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */)
d.SetFlush(0); d.SetFlush(0);
d.SetStyle(style); d.SetStyle(style);
PrintVals(&d, vals, offset); describe_vals(vals, &d, offset);
f->Write(d.Description(), d.Len()); f->Write(d.Description(), d.Len());
} }
else else
@ -286,7 +279,7 @@ IntrusivePtr<Val> PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */)
d.SetFlush(0); d.SetFlush(0);
d.SetStyle(style); d.SetStyle(style);
PrintVals(&d, vals, offset); describe_vals(vals, &d, offset);
f->Write("\n", 1); f->Write("\n", 1);
} }
@ -966,13 +959,10 @@ EventStmt::EventStmt(IntrusivePtr<EventExpr> arg_e)
IntrusivePtr<Val> EventStmt::Exec(Frame* f, stmt_flow_type& flow) const IntrusivePtr<Val> EventStmt::Exec(Frame* f, stmt_flow_type& flow) const
{ {
RegisterAccess(); RegisterAccess();
val_list* args = eval_list(f, event_expr->Args()); auto args = eval_list(f, event_expr->Args());
if ( args ) if ( args )
{ mgr.QueueUncheckedEvent(event_expr->Handler(), std::move(*args));
mgr.QueueEvent(event_expr->Handler(), std::move(*args));
delete args;
}
flow = FLOW_NEXT; flow = FLOW_NEXT;
return nullptr; return nullptr;

View file

@ -95,10 +95,10 @@ protected:
~ExprListStmt() override; ~ExprListStmt() override;
IntrusivePtr<Val> Exec(Frame* f, stmt_flow_type& flow) const override; IntrusivePtr<Val> Exec(Frame* f, stmt_flow_type& flow) const override;
virtual IntrusivePtr<Val> DoExec(val_list* vals, stmt_flow_type& flow) const = 0; virtual IntrusivePtr<Val> DoExec(std::vector<IntrusivePtr<Val>> vals,
stmt_flow_type& flow) const = 0;
void Describe(ODesc* d) const override; void Describe(ODesc* d) const override;
void PrintVals(ODesc* d, val_list* vals, int offset) const;
IntrusivePtr<ListExpr> l; IntrusivePtr<ListExpr> l;
}; };
@ -109,7 +109,8 @@ public:
explicit PrintStmt(L&& l) : ExprListStmt(STMT_PRINT, std::forward<L>(l)) { } explicit PrintStmt(L&& l) : ExprListStmt(STMT_PRINT, std::forward<L>(l)) { }
protected: protected:
IntrusivePtr<Val> DoExec(val_list* vals, stmt_flow_type& flow) const override; IntrusivePtr<Val> DoExec(std::vector<IntrusivePtr<Val>> vals,
stmt_flow_type& flow) const override;
}; };
class ExprStmt : public Stmt { class ExprStmt : public Stmt {

View file

@ -3292,6 +3292,24 @@ void describe_vals(const val_list* vals, ODesc* d, int offset)
} }
} }
void describe_vals(const std::vector<IntrusivePtr<Val>>& 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) void delete_vals(val_list* vals)
{ {
if ( vals ) if ( vals )

View file

@ -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 int same_atomic_val(const Val* v1, const Val* v2);
extern bool is_atomic_val(const Val* v); 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 val_list* vals, ODesc* d, int offset=0);
extern void describe_vals(const std::vector<IntrusivePtr<Val>>& vals,
ODesc* d, size_t offset = 0);
extern void delete_vals(val_list* vals); extern void delete_vals(val_list* vals);
// True if the given Val* has a vector type. // True if the given Val* has a vector type.

15
src/ZeekArgs.cc Normal file
View file

@ -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;
}

27
src/ZeekArgs.h Normal file
View file

@ -0,0 +1,27 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include "BroList.h"
#include <vector>
class Val;
template <class T> class IntrusivePtr;
namespace zeek {
using Args = std::vector<IntrusivePtr<Val>>;
/**
* 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

View file

@ -83,7 +83,13 @@ type Broker::Event: record;
function Broker::make_event%(...%): Broker::Event function Broker::make_event%(...%): Broker::Event
%{ %{
bro_broker::Manager::ScriptScopeGuard ssg; 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; return rval;
%} %}
@ -98,11 +104,11 @@ function Broker::make_event%(...%): Broker::Event
## Returns: true if the message is sent. ## Returns: true if the message is sent.
function Broker::publish%(topic: string, ...%): bool function Broker::publish%(topic: string, ...%): bool
%{ %{
val_list* bif_args = @ARGS@; const auto& bif_args = @ARGS@;
val_list args(bif_args->length() - 1); val_list args(bif_args->size() - 1);
for ( auto i = 1; i < bif_args->length(); ++i ) for ( auto i = 1u; i < bif_args->size(); ++i )
args.push_back((*bif_args)[i]); args.push_back((*bif_args)[i].get());
auto rval = publish_event_args(args, topic->AsString(), frame); auto rval = publish_event_args(args, topic->AsString(), frame);
return val_mgr->GetBool(rval); return val_mgr->GetBool(rval);
@ -188,11 +194,11 @@ function Cluster::publish_rr%(pool: Pool, key: string, ...%): bool
if ( ! topic->AsString()->Len() ) if ( ! topic->AsString()->Len() )
return val_mgr->GetFalse(); return val_mgr->GetFalse();
val_list* bif_args = @ARGS@; const auto& bif_args = @ARGS@;
val_list args(bif_args->length() - 2); val_list args(bif_args->size() - 2);
for ( auto i = 2; i < bif_args->length(); ++i ) for ( auto i = 2u; i < bif_args->size(); ++i )
args.push_back((*bif_args)[i]); args.push_back((*bif_args)[i].get());
auto rval = publish_event_args(args, topic->AsString(), frame); auto rval = publish_event_args(args, topic->AsString(), frame);
return val_mgr->GetBool(rval); return val_mgr->GetBool(rval);
@ -225,11 +231,11 @@ function Cluster::publish_hrw%(pool: Pool, key: any, ...%): bool
if ( ! topic->AsString()->Len() ) if ( ! topic->AsString()->Len() )
return val_mgr->GetFalse(); return val_mgr->GetFalse();
val_list* bif_args = @ARGS@; const auto& bif_args = @ARGS@;
val_list args(bif_args->length() - 2); val_list args(bif_args->size() - 2);
for ( auto i = 2; i < bif_args->length(); ++i ) for ( auto i = 2u; i < bif_args->size(); ++i )
args.push_back((*bif_args)[i]); args.push_back((*bif_args)[i].get());
auto rval = publish_event_args(args, topic->AsString(), frame); auto rval = publish_event_args(args, topic->AsString(), frame);
return val_mgr->GetBool(rval); return val_mgr->GetBool(rval);

View file

@ -218,7 +218,7 @@ void done_with_network()
mgr.Drain(); mgr.Drain();
// Don't propagate this event to remote clients. // Don't propagate this event to remote clients.
mgr.Dispatch(new Event(net_done, mgr.Dispatch(new Event(net_done,
{new Val(timer_mgr->Time(), TYPE_TIME)}), {make_intrusive<Val>(timer_mgr->Time(), TYPE_TIME)}),
true); true);
} }

View file

@ -1,5 +1,6 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include <optional>
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
#include <dirent.h> #include <dirent.h>
@ -619,15 +620,21 @@ int Manager::HookLoadFile(const Plugin::LoadType type, const string& file, const
return rc; return rc;
} }
std::pair<bool, Val*> Manager::HookCallFunction(const Func* func, Frame* parent, val_list* vargs) const std::pair<bool, Val*> Manager::HookCallFunction(const Func* func, Frame* parent, const zeek::Args& vecargs) const
{ {
HookArgumentList args; HookArgumentList args;
std::optional<val_list> vargs;
if ( HavePluginForHook(META_HOOK_PRE) ) 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(func));
args.push_back(HookArgument(parent)); args.push_back(HookArgument(parent));
args.push_back(HookArgument(vargs)); args.push_back(HookArgument(&vargs.value()));
MetaHookPre(HOOK_CALL_FUNCTION, args); MetaHookPre(HOOK_CALL_FUNCTION, args);
} }
@ -637,11 +644,19 @@ std::pair<bool, Val*> Manager::HookCallFunction(const Func* func, Frame* parent,
if ( l ) 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 ) for ( hook_list::iterator i = l->begin(); i != l->end(); ++i )
{ {
Plugin* p = (*i).second; Plugin* p = (*i).second;
v = p->HookCallFunction(func, parent, vargs); v = p->HookCallFunction(func, parent, &vargs.value());
if ( v.first ) if ( v.first )
break; break;

View file

@ -6,11 +6,11 @@
#include <map> #include <map>
#include <string_view> #include <string_view>
#include "Plugin.h" #include "Plugin.h"
#include "Component.h" #include "Component.h"
#include "../Reporter.h" #include "../Reporter.h"
#include "../ZeekArgs.h"
namespace plugin { namespace plugin {
@ -253,7 +253,7 @@ public:
* functions and events, it may be any Val and must be ignored). If no * functions and events, it may be any Val and must be ignored). If no
* plugin handled the call, the method returns null. * plugin handled the call, the method returns null.
*/ */
std::pair<bool, Val*> HookCallFunction(const Func* func, Frame *parent, val_list* args) const; std::pair<bool, Val*> HookCallFunction(const Func* func, Frame* parent, const zeek::Args& args) const;
/** /**
* Hook that filters the queuing of an event. * Hook that filters the queuing of an event.

View file

@ -19,6 +19,7 @@ class ODesc;
class Frame; class Frame;
class Func; class Func;
class Event; class Event;
template <class T> class IntrusivePtr;
namespace threading { namespace threading {
struct Field; struct Field;

View file

@ -267,7 +267,7 @@ static void do_fmt(const char*& fmt, Val* v, ODesc* d)
++fmt; ++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; 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); return next_fmt(fmt, args, d, n);
} }
if ( ++n >= args->length() ) if ( ++n >= static_cast<int>(args->size()) )
return 0; return 0;
do_fmt(fmt, (*args)[n], d); do_fmt(fmt, (*args)[n].get(), d);
return *fmt != '\0'; return *fmt != '\0';
} }
@ -1413,12 +1413,12 @@ function sort%(v: any, ...%) : any
BroType* elt_type = v->Type()->YieldType(); BroType* elt_type = v->Type()->YieldType();
Func* comp = 0; Func* comp = 0;
if ( @ARG@.length() > 2 ) if ( @ARG@.size() > 2 )
builtin_error("sort() called with extraneous argument"); 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()) ) if ( ! IsFunc(comp_val->Type()->Tag()) )
{ {
builtin_error("second argument to sort() needs to be comparison function"); 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(); BroType* elt_type = v->Type()->YieldType();
Func* comp = 0; Func* comp = 0;
if ( @ARG@.length() > 2 ) if ( @ARG@.size() > 2 )
builtin_error("order() called with extraneous argument"); 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()) ) if ( ! IsFunc(comp_val->Type()->Tag()) )
{ {
builtin_error("second argument to order() needs to be comparison function"); 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; int pre_size = 0;
loop_over_list(@ARG@, i) for ( auto i = 0u; i < @ARG@.size(); ++i )
{ {
// Skip named parameters. // Skip named parameters.
if ( i < 2 ) if ( i < 2 )
@ -1604,7 +1604,7 @@ function cat_sep%(sep: string, def: string, ...%): string
if ( i > 2 ) if ( i > 2 )
d.Add(sep->CheckString(), 0); d.Add(sep->CheckString(), 0);
Val* v = @ARG@[i]; Val* v = @ARG@[i].get();
if ( v->Type()->Tag() == TYPE_STRING && ! v->AsString()->Len() ) if ( v->Type()->Tag() == TYPE_STRING && ! v->AsString()->Len() )
v = def; v = def;
@ -1660,7 +1660,7 @@ function fmt%(...%): string
if ( @ARGC@ == 0 ) if ( @ARGC@ == 0 )
return val_mgr->GetEmptyString(); 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 // Type of fmt_v will be string here, check_built_in_call() in Func.cc
// checks that. // checks that.
@ -1674,13 +1674,13 @@ function fmt%(...%): string
while ( next_fmt(fmt, @ARGS@, &d, n) ) while ( next_fmt(fmt, @ARGS@, &d, n) )
; ;
if ( n < @ARGC@ - 1 ) if ( n < static_cast<int>(@ARGC@) - 1 )
{ {
builtin_error("too many arguments for format", fmt_v); builtin_error("too many arguments for format", fmt_v);
return val_mgr->GetEmptyString(); return val_mgr->GetEmptyString();
} }
else if ( n >= @ARGC@ ) else if ( n >= static_cast<int>(@ARGC@) )
{ {
builtin_error("too few arguments for format", fmt_v); builtin_error("too few arguments for format", fmt_v);
return val_mgr->GetEmptyString(); return val_mgr->GetEmptyString();
@ -1703,7 +1703,7 @@ function print_raw%(...%): bool
%{ %{
ODesc d(DESC_READABLE); ODesc d(DESC_READABLE);
d.SetStyle(RAW_STYLE); d.SetStyle(RAW_STYLE);
describe_vals(&@ARG@, &d, 0); describe_vals(@ARG@, &d, 0);
printf("%.*s", d.Len(), d.Description()); printf("%.*s", d.Len(), d.Description());
return val_mgr->GetBool(true); return val_mgr->GetBool(true);
%} %}