mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
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:
parent
94656c2308
commit
4e1ac4e124
29 changed files with 367 additions and 305 deletions
6
NEWS
6
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<IntrusivePtr<Val>>``
|
||||
rather than a ``val_list`` (i.e. ``List<Val*>``).
|
||||
|
||||
Removed Functionality
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit b3a5d01c041b78a9e50544ac891c5e0d35c116f7
|
||||
Subproject commit 75f645ac9bdfd141f549b7e1a197459f2ad518be
|
|
@ -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
|
||||
|
|
46
src/Event.cc
46
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)
|
||||
{
|
||||
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);
|
||||
|
|
53
src/Event.h
53
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,
|
||||
Event(EventHandlerPtr handler, zeek::Args 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);
|
||||
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);
|
||||
|
||||
|
|
|
@ -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<VectorVal>(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<int>(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<StringVal>(name),
|
||||
std::move(vargs),
|
||||
});
|
||||
mgr.Dispatch(ev);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "BroList.h"
|
||||
#include "ZeekArgs.h"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
|
@ -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;
|
||||
|
|
53
src/Expr.cc
53
src/Expr.cc
|
@ -3884,12 +3884,11 @@ IntrusivePtr<Val> 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<Expr> arg_when,
|
||||
|
@ -3937,7 +3936,7 @@ IntrusivePtr<Val> 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<Val> 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<Val> CallExpr::Eval(Frame* f) const
|
|||
|
||||
IntrusivePtr<Val> 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<Val> 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<Val> 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<std::vector<IntrusivePtr<Val>>> 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<std::vector<IntrusivePtr<Val>>>();
|
||||
rval->reserve(e.length());
|
||||
|
||||
for ( const auto& expr : e )
|
||||
{
|
||||
auto ev = expr->Eval(f);
|
||||
|
||||
if ( ! ev )
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
return {};
|
||||
|
||||
rval->emplace_back(std::move(ev));
|
||||
}
|
||||
|
||||
v->push_back(ev.release());
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
15
src/Expr.h
15
src/Expr.h
|
@ -9,10 +9,13 @@
|
|||
#include "EventHandler.h"
|
||||
#include "TraverseTypes.h"
|
||||
#include "Val.h"
|
||||
#include "ZeekArgs.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <optional>
|
||||
|
||||
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<std::vector<IntrusivePtr<Val>>> 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
|
||||
|
|
|
@ -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<Val>(this)});
|
||||
mgr.Dispatch(event, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
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;
|
||||
frame = new Val*[size];
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "BroList.h" // for typedef val_list
|
||||
#include "Obj.h"
|
||||
#include "IntrusivePtr.h"
|
||||
#include "ZeekArgs.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
@ -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;
|
||||
|
|
72
src/Func.cc
72
src/Func.cc
|
@ -79,9 +79,7 @@ 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();
|
||||
|
@ -92,7 +90,6 @@ std::string render_call_stack()
|
|||
|
||||
arg_desc += d.Description();
|
||||
}
|
||||
}
|
||||
|
||||
rval += fmt("#%d %s(%s)", lvl, name, arg_desc.data());
|
||||
|
||||
|
@ -143,7 +140,7 @@ IntrusivePtr<Func> 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<size_t>(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<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
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -300,7 +294,12 @@ int BroFunc::IsPure() const
|
|||
[](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
|
||||
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);
|
||||
|
||||
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<Val> 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>(frame_size, this, args);
|
||||
auto f = make_intrusive<Frame>(frame_size, this, &args);
|
||||
|
||||
if ( closure )
|
||||
f->CaptureClosure(closure, outer_ids);
|
||||
|
@ -346,7 +342,7 @@ IntrusivePtr<Val> 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<Val> 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<Val> 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<Val> BuiltinFunc::Call(val_list* args, Frame* parent) const
|
||||
IntrusivePtr<Val> BuiltinFunc::Call(const zeek::Args& args, Frame* parent) const
|
||||
{
|
||||
#ifdef PROFILE_BRO_FUNCTIONS
|
||||
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);
|
||||
|
||||
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<Val> 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<Val> result{AdoptRef{}, func(parent, args)};
|
||||
IntrusivePtr<Val> 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<Val>{});
|
||||
}
|
||||
|
||||
void builtin_error(const char* msg, IntrusivePtr<Val> arg)
|
||||
{
|
||||
builtin_error(msg, arg.get());
|
||||
}
|
||||
|
||||
void builtin_error(const char* msg, BroObj* arg)
|
||||
{
|
||||
auto emit = [=](const CallExpr* ce)
|
||||
|
|
22
src/Func.h
22
src/Func.h
|
@ -7,6 +7,7 @@
|
|||
#include "IntrusivePtr.h"
|
||||
#include "Type.h" /* for function_flavor */
|
||||
#include "TraverseTypes.h"
|
||||
#include "ZeekArgs.h"
|
||||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
@ -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<Body>& GetBodies() const { return bodies; }
|
||||
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).
|
||||
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 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();
|
||||
|
||||
|
@ -84,7 +86,7 @@ protected:
|
|||
void CopyStateInto(Func* other) const;
|
||||
|
||||
// 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;
|
||||
IntrusivePtr<Scope> scope;
|
||||
|
@ -102,7 +104,7 @@ public:
|
|||
~BroFunc() 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
|
||||
|
@ -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<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; }
|
||||
|
||||
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_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
|
||||
|
|
|
@ -221,26 +221,7 @@ MD5Val::~MD5Val()
|
|||
EVP_MD_CTX_free(ctx);
|
||||
}
|
||||
|
||||
IntrusivePtr<Val> MD5Val::DoClone(CloneState* state)
|
||||
{
|
||||
auto out = make_intrusive<MD5Val>();
|
||||
|
||||
if ( IsValid() )
|
||||
{
|
||||
if ( ! out->Init() )
|
||||
return nullptr;
|
||||
|
||||
EVP_MD_CTX_copy_ex(out->ctx, ctx);
|
||||
}
|
||||
|
||||
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 )
|
||||
void HashVal::digest_one(EVP_MD_CTX* h, const Val* v)
|
||||
{
|
||||
if ( v->Type()->Tag() == TYPE_STRING )
|
||||
{
|
||||
|
@ -255,18 +236,24 @@ void MD5Val::digest(val_list& vlist, u_char result[MD5_DIGEST_LENGTH])
|
|||
}
|
||||
}
|
||||
|
||||
hash_final(h, result);
|
||||
void HashVal::digest_one(EVP_MD_CTX* h, const IntrusivePtr<Val>& v)
|
||||
{
|
||||
digest_one(h, v.get());
|
||||
}
|
||||
|
||||
void MD5Val::hmac(val_list& vlist,
|
||||
u_char key[MD5_DIGEST_LENGTH],
|
||||
u_char result[MD5_DIGEST_LENGTH])
|
||||
IntrusivePtr<Val> MD5Val::DoClone(CloneState* state)
|
||||
{
|
||||
digest(vlist, result);
|
||||
for ( int i = 0; i < MD5_DIGEST_LENGTH; ++i )
|
||||
result[i] ^= key[i];
|
||||
auto out = make_intrusive<MD5Val>();
|
||||
|
||||
internal_md5(result, MD5_DIGEST_LENGTH, result);
|
||||
if ( IsValid() )
|
||||
{
|
||||
if ( ! out->Init() )
|
||||
return nullptr;
|
||||
|
||||
EVP_MD_CTX_copy_ex(out->ctx, ctx);
|
||||
}
|
||||
|
||||
return state->NewClone(this, std::move(out));
|
||||
}
|
||||
|
||||
bool MD5Val::DoInit()
|
||||
|
@ -389,28 +376,6 @@ IntrusivePtr<Val> 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<Val> 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() );
|
||||
|
|
|
@ -162,12 +162,26 @@ namespace probabilistic {
|
|||
|
||||
class HashVal : public OpaqueVal {
|
||||
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 Init();
|
||||
bool Feed(const void* data, size_t size);
|
||||
IntrusivePtr<StringVal> Get();
|
||||
|
||||
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; }
|
||||
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 <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>
|
||||
static void hmac(const T& vlist,
|
||||
u_char key[MD5_DIGEST_LENGTH],
|
||||
u_char result[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 <class T>
|
||||
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 <class T>
|
||||
static void digest(const T& vlist, u_char result[SHA256_DIGEST_LENGTH])
|
||||
{ digest_all(Hash_SHA256, vlist, result); }
|
||||
|
||||
SHA256Val();
|
||||
~SHA256Val();
|
||||
|
|
|
@ -314,8 +314,8 @@ void ProfileLogger::Log()
|
|||
{
|
||||
Ref(file);
|
||||
mgr.Dispatch(new Event(profiling_update, {
|
||||
new Val(file),
|
||||
val_mgr->GetBool(expensive),
|
||||
make_intrusive<Val>(file),
|
||||
{AdoptRef{}, val_mgr->GetBool(expensive)},
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
38
src/Stmt.cc
38
src/Stmt.cc
|
@ -151,14 +151,11 @@ IntrusivePtr<Val> 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 DoExec(std::move(*vals), flow);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -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<EnumVal> 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<IntrusivePtr<Val>>& vals)
|
||||
{
|
||||
auto plval = lookup_enum_val("Log", "PRINTLOG");
|
||||
auto record = make_intrusive<RecordVal>(internal_type("Log::PrintLogInfo")->AsRecordType());
|
||||
auto vec = make_intrusive<VectorVal>(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<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();
|
||||
|
||||
|
@ -234,9 +227,9 @@ IntrusivePtr<Val> 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<Val> 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<Val> 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<EventExpr> arg_e)
|
|||
IntrusivePtr<Val> 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;
|
||||
|
|
|
@ -95,10 +95,10 @@ protected:
|
|||
~ExprListStmt() 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 PrintVals(ODesc* d, val_list* vals, int offset) const;
|
||||
|
||||
IntrusivePtr<ListExpr> l;
|
||||
};
|
||||
|
@ -109,7 +109,8 @@ public:
|
|||
explicit PrintStmt(L&& l) : ExprListStmt(STMT_PRINT, std::forward<L>(l)) { }
|
||||
|
||||
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 {
|
||||
|
|
18
src/Val.cc
18
src/Val.cc
|
@ -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)
|
||||
{
|
||||
if ( vals )
|
||||
|
|
|
@ -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<IntrusivePtr<Val>>& vals,
|
||||
ODesc* d, size_t offset = 0);
|
||||
extern void delete_vals(val_list* vals);
|
||||
|
||||
// True if the given Val* has a vector type.
|
||||
|
|
15
src/ZeekArgs.cc
Normal file
15
src/ZeekArgs.cc
Normal 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
27
src/ZeekArgs.h
Normal 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
|
|
@ -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);
|
||||
|
|
|
@ -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<Val>(timer_mgr->Time(), TYPE_TIME)}),
|
||||
true);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <dirent.h>
|
||||
|
@ -619,15 +620,21 @@ int Manager::HookLoadFile(const Plugin::LoadType type, const string& file, const
|
|||
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;
|
||||
std::optional<val_list> 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<bool, Val*> 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;
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
#include <map>
|
||||
#include <string_view>
|
||||
|
||||
|
||||
#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<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.
|
||||
|
|
|
@ -19,6 +19,7 @@ class ODesc;
|
|||
class Frame;
|
||||
class Func;
|
||||
class Event;
|
||||
template <class T> class IntrusivePtr;
|
||||
|
||||
namespace threading {
|
||||
struct Field;
|
||||
|
|
30
src/zeek.bif
30
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<int>(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<int>(@ARGC@) - 1 )
|
||||
{
|
||||
builtin_error("too many arguments for format", fmt_v);
|
||||
return val_mgr->GetEmptyString();
|
||||
}
|
||||
|
||||
else if ( n >= @ARGC@ )
|
||||
else if ( n >= static_cast<int>(@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);
|
||||
%}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue