mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 23:58:20 +00:00
"if ( ... ) &analyze" language feature
This commit is contained in:
parent
052cda9df0
commit
9f4da24644
6 changed files with 207 additions and 62 deletions
|
@ -3187,7 +3187,7 @@ HasFieldExpr::HasFieldExpr(ExprPtr arg_op, const char* arg_field_name)
|
||||||
|
|
||||||
HasFieldExpr::~HasFieldExpr()
|
HasFieldExpr::~HasFieldExpr()
|
||||||
{
|
{
|
||||||
delete field_name;
|
delete[] field_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
ValPtr HasFieldExpr::Fold(Val* v) const
|
ValPtr HasFieldExpr::Fold(Val* v) const
|
||||||
|
|
66
src/Var.cc
66
src/Var.cc
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "zeek/ActivationManager.h"
|
||||||
#include "zeek/Desc.h"
|
#include "zeek/Desc.h"
|
||||||
#include "zeek/EventRegistry.h"
|
#include "zeek/EventRegistry.h"
|
||||||
#include "zeek/Expr.h"
|
#include "zeek/Expr.h"
|
||||||
|
@ -234,7 +235,7 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init,
|
||||||
{
|
{
|
||||||
if ( IsFunc(id->GetType()->Tag()) )
|
if ( IsFunc(id->GetType()->Tag()) )
|
||||||
add_prototype(id, t.get(), attr.get(), init);
|
add_prototype(id, t.get(), attr.get(), init);
|
||||||
else
|
else if ( activation_mgr->IsActivated() )
|
||||||
id->Error("already defined", init.get());
|
id->Error("already defined", init.get());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -405,7 +406,18 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init,
|
||||||
void add_global(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init,
|
void add_global(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init,
|
||||||
std::unique_ptr<std::vector<AttrPtr>> attr, DeclType dt)
|
std::unique_ptr<std::vector<AttrPtr>> attr, DeclType dt)
|
||||||
{
|
{
|
||||||
make_var(id, std::move(t), c, std::move(init), std::move(attr), dt, true);
|
bool do_init = activation_mgr->IsActivated();
|
||||||
|
|
||||||
|
if ( dt == VAR_REDEF )
|
||||||
|
{
|
||||||
|
activation_mgr->AddingRedef(id, c, init, attr);
|
||||||
|
|
||||||
|
if ( ! do_init )
|
||||||
|
// Don't actually change the attributes.
|
||||||
|
attr = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
make_var(id, std::move(t), c, std::move(init), std::move(attr), dt, do_init);
|
||||||
}
|
}
|
||||||
|
|
||||||
StmtPtr add_local(IDPtr id, TypePtr t, InitClass c, ExprPtr init,
|
StmtPtr add_local(IDPtr id, TypePtr t, InitClass c, ExprPtr init,
|
||||||
|
@ -711,6 +723,8 @@ void begin_func(IDPtr id, const char* module_name, FunctionFlavor flavor, bool i
|
||||||
else if ( is_redef )
|
else if ( is_redef )
|
||||||
id->Error("redef of not-previously-declared value");
|
id->Error("redef of not-previously-declared value");
|
||||||
|
|
||||||
|
bool is_activated = activation_mgr->IsActivated();
|
||||||
|
|
||||||
if ( id->HasVal() )
|
if ( id->HasVal() )
|
||||||
{
|
{
|
||||||
FunctionFlavor id_flavor = id->GetVal()->AsFunc()->Flavor();
|
FunctionFlavor id_flavor = id->GetVal()->AsFunc()->Flavor();
|
||||||
|
@ -724,12 +738,17 @@ void begin_func(IDPtr id, const char* module_name, FunctionFlavor flavor, bool i
|
||||||
case FUNC_FLAVOR_EVENT:
|
case FUNC_FLAVOR_EVENT:
|
||||||
case FUNC_FLAVOR_HOOK:
|
case FUNC_FLAVOR_HOOK:
|
||||||
if ( is_redef )
|
if ( is_redef )
|
||||||
// Clear out value so it will be replaced.
|
{
|
||||||
id->SetVal(nullptr);
|
activation_mgr->RedefingHandler(id);
|
||||||
|
|
||||||
|
if ( ! is_activated )
|
||||||
|
// Clear out value so it will be replaced.
|
||||||
|
id->SetVal(nullptr);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FUNC_FLAVOR_FUNCTION:
|
case FUNC_FLAVOR_FUNCTION:
|
||||||
if ( ! id->IsRedefinable() )
|
if ( ! id->IsRedefinable() && is_activated )
|
||||||
id->Error("already defined", t.get());
|
id->Error("already defined", t.get());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -753,12 +772,15 @@ void begin_func(IDPtr id, const char* module_name, FunctionFlavor flavor, bool i
|
||||||
if ( ! check_params(i, prototype, args, canon_args, module_name) )
|
if ( ! check_params(i, prototype, args, canon_args, module_name) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ( Attr* depr_attr = find_attr(current_scope()->Attrs().get(), ATTR_DEPRECATED) )
|
if ( is_activated )
|
||||||
current_scope()->GetID()->MakeDeprecated(depr_attr->GetExpr());
|
{
|
||||||
|
if ( Attr* depr_attr = find_attr(current_scope()->Attrs().get(), ATTR_DEPRECATED) )
|
||||||
|
current_scope()->GetID()->MakeDeprecated(depr_attr->GetExpr());
|
||||||
|
|
||||||
// Reset the AST node statistics to track afresh for this function.
|
// Reset the AST node statistics to track afresh for this function.
|
||||||
Stmt::ResetNumStmts();
|
Stmt::ResetNumStmts();
|
||||||
Expr::ResetNumExprs();
|
Expr::ResetNumExprs();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OuterIDBindingFinder : public TraversalCallback
|
class OuterIDBindingFinder : public TraversalCallback
|
||||||
|
@ -846,7 +868,7 @@ void end_func(StmtPtr body, const char* module_name, bool free_of_conditionals)
|
||||||
oi->num_stmts = Stmt::GetNumStmts();
|
oi->num_stmts = Stmt::GetNumStmts();
|
||||||
oi->num_exprs = Expr::GetNumExprs();
|
oi->num_exprs = Expr::GetNumExprs();
|
||||||
|
|
||||||
auto ingredients = std::make_unique<FunctionIngredients>(pop_scope(), std::move(body),
|
auto ingredients = std::make_shared<FunctionIngredients>(pop_scope(), std::move(body),
|
||||||
module_name);
|
module_name);
|
||||||
auto id = ingredients->GetID();
|
auto id = ingredients->GetID();
|
||||||
if ( ! id->HasVal() )
|
if ( ! id->HasVal() )
|
||||||
|
@ -854,27 +876,27 @@ void end_func(StmtPtr body, const char* module_name, bool free_of_conditionals)
|
||||||
auto f = make_intrusive<ScriptFunc>(id);
|
auto f = make_intrusive<ScriptFunc>(id);
|
||||||
id->SetVal(make_intrusive<FuncVal>(std::move(f)));
|
id->SetVal(make_intrusive<FuncVal>(std::move(f)));
|
||||||
id->SetConst();
|
id->SetConst();
|
||||||
|
activation_mgr->AddingGlobalVal(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
id->GetVal()->AsFunc()->AddBody(ingredients->Body(), ingredients->Inits(),
|
|
||||||
ingredients->FrameSize(), ingredients->Priority(),
|
|
||||||
ingredients->Groups());
|
|
||||||
|
|
||||||
script_coverage_mgr.AddFunction(id, ingredients->Body());
|
script_coverage_mgr.AddFunction(id, ingredients->Body());
|
||||||
|
|
||||||
auto func_ptr = cast_intrusive<FuncVal>(id->GetVal())->AsFuncPtr();
|
auto func_ptr = cast_intrusive<FuncVal>(id->GetVal())->AsFuncPtr();
|
||||||
auto func = cast_intrusive<ScriptFunc>(func_ptr);
|
auto func = cast_intrusive<ScriptFunc>(func_ptr);
|
||||||
func->SetScope(ingredients->Scope());
|
func->SetScope(ingredients->Scope());
|
||||||
|
|
||||||
for ( const auto& group : ingredients->Groups() )
|
activation_mgr->AddingBody(id, ingredients);
|
||||||
group->AddFunc(func);
|
|
||||||
|
|
||||||
analyze_func(std::move(func));
|
if ( activation_mgr->IsActivated() )
|
||||||
|
{
|
||||||
|
func->AddBody(ingredients->Body(), ingredients->Inits(), ingredients->FrameSize(),
|
||||||
|
ingredients->Priority(), ingredients->Groups());
|
||||||
|
|
||||||
// Note: ideally, something would take ownership of this memory until the
|
for ( const auto& group : ingredients->Groups() )
|
||||||
// end of script execution, but that's essentially the same as the
|
group->AddFunc(func);
|
||||||
// lifetime of the process at the moment, so ok to "leak" it.
|
|
||||||
ingredients.release();
|
analyze_func(std::move(func));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IDPList gather_outer_ids(ScopePtr scope, StmtPtr body)
|
IDPList gather_outer_ids(ScopePtr scope, StmtPtr body)
|
||||||
|
|
|
@ -23,7 +23,7 @@ extern void add_to_name_list(char* s, char delim, zeek::name_list& nl);
|
||||||
|
|
||||||
extern void begin_RE();
|
extern void begin_RE();
|
||||||
|
|
||||||
extern void do_atif(zeek::detail::Expr* expr);
|
extern void do_atif(zeek::detail::Expr* expr, bool is_activate);
|
||||||
extern void do_atifdef(const char* id);
|
extern void do_atifdef(const char* id);
|
||||||
extern void do_atifndef(const char* id);
|
extern void do_atifndef(const char* id);
|
||||||
extern void do_atelse();
|
extern void do_atelse();
|
||||||
|
|
111
src/parse.y
111
src/parse.y
|
@ -5,10 +5,10 @@
|
||||||
// Switching parser table type fixes ambiguity problems.
|
// Switching parser table type fixes ambiguity problems.
|
||||||
%define lr.type ielr
|
%define lr.type ielr
|
||||||
|
|
||||||
%expect 211
|
%expect 212
|
||||||
|
|
||||||
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
|
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
|
||||||
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
|
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATACTIVATEIF TOK_ATIFDEF TOK_ATIFNDEF
|
||||||
%token TOK_BOOL TOK_BREAK TOK_CASE TOK_OPTION TOK_CONST
|
%token TOK_BOOL TOK_BREAK TOK_CASE TOK_OPTION TOK_CONST
|
||||||
%token TOK_CONSTANT TOK_COPY TOK_COUNT TOK_DEFAULT TOK_DELETE
|
%token TOK_CONSTANT TOK_COPY TOK_COUNT TOK_DEFAULT TOK_DELETE
|
||||||
%token TOK_DOUBLE TOK_ELSE TOK_ENUM TOK_EVENT TOK_EXPORT TOK_FALLTHROUGH
|
%token TOK_DOUBLE TOK_ELSE TOK_ENUM TOK_EVENT TOK_EXPORT TOK_FALLTHROUGH
|
||||||
|
@ -31,6 +31,18 @@
|
||||||
%token TOK_ATTR_TYPE_COLUMN TOK_ATTR_DEPRECATED
|
%token TOK_ATTR_TYPE_COLUMN TOK_ATTR_DEPRECATED
|
||||||
%token TOK_ATTR_IS_ASSIGNED TOK_ATTR_IS_USED TOK_ATTR_ORDERED
|
%token TOK_ATTR_IS_ASSIGNED TOK_ATTR_IS_USED TOK_ATTR_ORDERED
|
||||||
|
|
||||||
|
// Heads-up, this one is a weirdo. It combines both the attribute and
|
||||||
|
// a leading ')' before it (the two can be separated by spaces/tabs, but
|
||||||
|
// no newlines). This is necessary because if we use the more natural
|
||||||
|
//
|
||||||
|
// TOK_ATIF '(' expr ')' TOK_ATTR_ANALYZE
|
||||||
|
//
|
||||||
|
// then the parser needs to look ahead past the ')' to see if the attribute
|
||||||
|
// is there. If it *isn't*, then the scanner will return the first token
|
||||||
|
// of the conditional block for the look-ahead ... which will break the parse
|
||||||
|
// if that block should in fact have been skipped.
|
||||||
|
%token TOK_ATTR_ANALYZE
|
||||||
|
|
||||||
%token TOK_DEBUG
|
%token TOK_DEBUG
|
||||||
|
|
||||||
%token TOK_NO_TEST
|
%token TOK_NO_TEST
|
||||||
|
@ -98,6 +110,7 @@
|
||||||
#include "zeek/RE.h"
|
#include "zeek/RE.h"
|
||||||
#include "zeek/Scope.h"
|
#include "zeek/Scope.h"
|
||||||
#include "zeek/Reporter.h"
|
#include "zeek/Reporter.h"
|
||||||
|
#include "zeek/ActivationManager.h"
|
||||||
#include "zeek/ScriptCoverageManager.h"
|
#include "zeek/ScriptCoverageManager.h"
|
||||||
#include "zeek/ScriptValidation.h"
|
#include "zeek/ScriptValidation.h"
|
||||||
#include "zeek/zeekygen/Manager.h"
|
#include "zeek/zeekygen/Manager.h"
|
||||||
|
@ -139,16 +152,19 @@ extern const char* g_curr_debug_error;
|
||||||
extern int in_when_cond;
|
extern int in_when_cond;
|
||||||
|
|
||||||
static int in_hook = 0;
|
static int in_hook = 0;
|
||||||
int in_init = 0;
|
static int in_init = 0;
|
||||||
int in_record = 0;
|
static int in_body = 0;
|
||||||
|
static int in_global_stmts = 0;
|
||||||
|
static int in_record = 0;
|
||||||
static int in_record_redef = 0;
|
static int in_record_redef = 0;
|
||||||
static int in_enum_redef = 0;
|
static int in_enum_redef = 0;
|
||||||
bool resolving_global_ID = false;
|
static bool resolving_global_ID = false;
|
||||||
bool defining_global_ID = false;
|
static bool defining_global_ID = false;
|
||||||
std::vector<int> saved_in_init;
|
static bool is_activated = true;
|
||||||
|
static std::vector<int> saved_in_init;
|
||||||
static int expr_list_has_opt_comma = 0;
|
static int expr_list_has_opt_comma = 0;
|
||||||
|
|
||||||
std::vector<std::set<const ID*>> locals_at_this_scope;
|
static std::vector<std::set<const ID*>> locals_at_this_scope;
|
||||||
static std::unordered_set<const ID*> out_of_scope_locals;
|
static std::unordered_set<const ID*> out_of_scope_locals;
|
||||||
|
|
||||||
static Location func_hdr_location;
|
static Location func_hdr_location;
|
||||||
|
@ -321,6 +337,9 @@ static void build_global(ID* id, Type* t, InitClass ic, Expr* e,
|
||||||
|
|
||||||
add_global(id_ptr, std::move(t_ptr), ic, e_ptr, std::move(attrs_ptr), dt);
|
add_global(id_ptr, std::move(t_ptr), ic, e_ptr, std::move(attrs_ptr), dt);
|
||||||
|
|
||||||
|
if ( ! activation_mgr->IsActivated() )
|
||||||
|
return;
|
||||||
|
|
||||||
if ( dt == VAR_REDEF )
|
if ( dt == VAR_REDEF )
|
||||||
zeekygen_mgr->Redef(id, ::filename, ic, std::move(e_ptr));
|
zeekygen_mgr->Redef(id, ::filename, ic, std::move(e_ptr));
|
||||||
else
|
else
|
||||||
|
@ -392,9 +411,13 @@ zeek:
|
||||||
auto loc = zeek::detail::GetCurrentLocation();
|
auto loc = zeek::detail::GetCurrentLocation();
|
||||||
if ( loc.filename )
|
if ( loc.filename )
|
||||||
set_location(loc);
|
set_location(loc);
|
||||||
|
|
||||||
|
++in_global_stmts;
|
||||||
}
|
}
|
||||||
stmt_list
|
stmt_list
|
||||||
{
|
{
|
||||||
|
--in_global_stmts;
|
||||||
|
|
||||||
if ( stmts )
|
if ( stmts )
|
||||||
stmts->AsStmtList()->Stmts().push_back($3);
|
stmts->AsStmtList()->Stmts().push_back($3);
|
||||||
else
|
else
|
||||||
|
@ -1400,29 +1423,49 @@ decl:
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_REDEF TOK_ENUM global_id TOK_ADD_TO '{'
|
| TOK_REDEF TOK_ENUM global_id TOK_ADD_TO '{'
|
||||||
{ ++in_enum_redef; parse_redef_enum($3); zeekygen_mgr->Redef($3, ::filename); }
|
{
|
||||||
|
++in_enum_redef;
|
||||||
|
parse_redef_enum($3);
|
||||||
|
zeekygen_mgr->Redef($3, ::filename);
|
||||||
|
}
|
||||||
enum_body '}' ';'
|
enum_body '}' ';'
|
||||||
{
|
{
|
||||||
|
if ( activation_mgr->InsideConditional() )
|
||||||
|
reporter->Error("enum redef cannot appear inside @if &analyze");
|
||||||
--in_enum_redef;
|
--in_enum_redef;
|
||||||
// Zeekygen already grabbed new enum IDs as the type created them.
|
// Zeekygen already grabbed new enum IDs as the type created them.
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_REDEF TOK_RECORD global_id '$' TOK_ID
|
| TOK_REDEF TOK_RECORD global_id '$' TOK_ID
|
||||||
{ cur_decl_type_id = $3; zeekygen_mgr->Redef($3, ::filename, INIT_EXTRA); }
|
{
|
||||||
|
cur_decl_type_id = $3;
|
||||||
|
zeekygen_mgr->Redef($3, ::filename, INIT_EXTRA);
|
||||||
|
}
|
||||||
TOK_ADD_TO '{' attr_list '}' ';'
|
TOK_ADD_TO '{' attr_list '}' ';'
|
||||||
{
|
{
|
||||||
|
if ( activation_mgr->InsideConditional() )
|
||||||
|
reporter->Error("record redef cannot appear inside @if &analyze");
|
||||||
cur_decl_type_id = 0;
|
cur_decl_type_id = 0;
|
||||||
parse_redef_record_field($3, $5, INIT_EXTRA, std::unique_ptr<std::vector<AttrPtr>>($9));
|
parse_redef_record_field($3, $5, INIT_EXTRA, std::unique_ptr<std::vector<AttrPtr>>($9));
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_REDEF TOK_RECORD global_id '$' TOK_ID
|
| TOK_REDEF TOK_RECORD global_id '$' TOK_ID
|
||||||
{ cur_decl_type_id = $3; zeekygen_mgr->Redef($3, ::filename, INIT_REMOVE); }
|
{
|
||||||
|
cur_decl_type_id = $3;
|
||||||
|
zeekygen_mgr->Redef($3, ::filename, INIT_REMOVE);
|
||||||
|
}
|
||||||
TOK_REMOVE_FROM '{' attr_list '}' ';'
|
TOK_REMOVE_FROM '{' attr_list '}' ';'
|
||||||
{
|
{
|
||||||
|
if ( activation_mgr->InsideConditional() )
|
||||||
|
reporter->Error("record redef cannot appear inside @if &analyze");
|
||||||
cur_decl_type_id = 0;
|
cur_decl_type_id = 0;
|
||||||
parse_redef_record_field($3, $5, INIT_REMOVE, std::unique_ptr<std::vector<AttrPtr>>($9));
|
parse_redef_record_field($3, $5, INIT_REMOVE, std::unique_ptr<std::vector<AttrPtr>>($9));
|
||||||
}
|
}
|
||||||
| TOK_REDEF TOK_RECORD global_id
|
| TOK_REDEF TOK_RECORD global_id
|
||||||
{ cur_decl_type_id = $3; zeekygen_mgr->Redef($3, ::filename); }
|
{
|
||||||
|
cur_decl_type_id = $3;
|
||||||
|
zeekygen_mgr->Redef($3, ::filename);
|
||||||
|
}
|
||||||
TOK_ADD_TO '{'
|
TOK_ADD_TO '{'
|
||||||
{ ++in_record; ++in_record_redef; }
|
{ ++in_record; ++in_record_redef; }
|
||||||
type_decl_list
|
type_decl_list
|
||||||
|
@ -1433,6 +1476,8 @@ decl:
|
||||||
|
|
||||||
if ( ! $3->GetType() )
|
if ( ! $3->GetType() )
|
||||||
$3->Error("unknown identifier");
|
$3->Error("unknown identifier");
|
||||||
|
else if ( activation_mgr->InsideConditional() )
|
||||||
|
reporter->Error("record redef cannot appear inside @if &analyze");
|
||||||
else
|
else
|
||||||
extend_record($3, std::unique_ptr<type_decl_list>($8),
|
extend_record($3, std::unique_ptr<type_decl_list>($8),
|
||||||
std::unique_ptr<std::vector<AttrPtr>>($11));
|
std::unique_ptr<std::vector<AttrPtr>>($11));
|
||||||
|
@ -1465,7 +1510,19 @@ conditional_list:
|
||||||
|
|
||||||
conditional:
|
conditional:
|
||||||
TOK_ATIF '(' expr ')'
|
TOK_ATIF '(' expr ')'
|
||||||
{ do_atif($3); }
|
{ do_atif($3, false); }
|
||||||
|
| TOK_ATIF '(' expr TOK_ATTR_ANALYZE
|
||||||
|
{
|
||||||
|
if ( in_body )
|
||||||
|
reporter->Error("@if &analyze cannot appear inside a function body");
|
||||||
|
do_atif($3, true);
|
||||||
|
}
|
||||||
|
| TOK_ATACTIVATEIF '(' expr ')'
|
||||||
|
{
|
||||||
|
if ( in_body )
|
||||||
|
reporter->Error("@if &analyze cannot appear inside a function body");
|
||||||
|
do_atif($3, true);
|
||||||
|
}
|
||||||
| TOK_ATIFDEF '(' TOK_ID ')'
|
| TOK_ATIFDEF '(' TOK_ID ')'
|
||||||
{ do_atifdef($3); }
|
{ do_atifdef($3); }
|
||||||
| TOK_ATIFNDEF '(' TOK_ID ')'
|
| TOK_ATIFNDEF '(' TOK_ID ')'
|
||||||
|
@ -1516,6 +1573,7 @@ func_body:
|
||||||
{
|
{
|
||||||
saved_in_init.push_back(in_init);
|
saved_in_init.push_back(in_init);
|
||||||
in_init = 0;
|
in_init = 0;
|
||||||
|
++in_body;
|
||||||
|
|
||||||
locals_at_this_scope.clear();
|
locals_at_this_scope.clear();
|
||||||
out_of_scope_locals.clear();
|
out_of_scope_locals.clear();
|
||||||
|
@ -1525,6 +1583,7 @@ func_body:
|
||||||
{
|
{
|
||||||
in_init = saved_in_init.back();
|
in_init = saved_in_init.back();
|
||||||
saved_in_init.pop_back();
|
saved_in_init.pop_back();
|
||||||
|
--in_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
'}'
|
'}'
|
||||||
|
@ -1545,12 +1604,14 @@ lambda_body:
|
||||||
{
|
{
|
||||||
saved_in_init.push_back(in_init);
|
saved_in_init.push_back(in_init);
|
||||||
in_init = 0;
|
in_init = 0;
|
||||||
|
++in_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt_list
|
stmt_list
|
||||||
{
|
{
|
||||||
in_init = saved_in_init.back();
|
in_init = saved_in_init.back();
|
||||||
saved_in_init.pop_back();
|
saved_in_init.pop_back();
|
||||||
|
--in_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
'}'
|
'}'
|
||||||
|
@ -1963,11 +2024,21 @@ stmt:
|
||||||
;
|
;
|
||||||
|
|
||||||
stmt_list:
|
stmt_list:
|
||||||
stmt_list stmt
|
stmt_list { is_activated = activation_mgr->IsActivated(); } stmt
|
||||||
{
|
{
|
||||||
set_location(@1, @2);
|
set_location(@1, @3);
|
||||||
$1->AsStmtList()->Stmts().push_back($2);
|
|
||||||
$1->UpdateLocationEndInfo(@2);
|
// We can't simply test activation_mgr->IsActivated()
|
||||||
|
// here because the parser can wind up looking ahead
|
||||||
|
// to the @endif token and restoring activation that
|
||||||
|
// in fact was off for the statement. So we capture
|
||||||
|
// the activation state prior to parsing the statement
|
||||||
|
// in "is_activated" and test that instead.
|
||||||
|
if ( ! in_global_stmts || is_activated )
|
||||||
|
{
|
||||||
|
$1->AsStmtList()->Stmts().push_back($3);
|
||||||
|
$1->UpdateLocationEndInfo(@3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
{ $$ = new StmtList(); }
|
{ $$ = new StmtList(); }
|
||||||
|
@ -2207,8 +2278,10 @@ global_or_event_id:
|
||||||
resolving_global_ID ?
|
resolving_global_ID ?
|
||||||
current_module.c_str() : 0;
|
current_module.c_str() : 0;
|
||||||
|
|
||||||
$$ = install_ID($1, module_name,
|
auto gid = install_ID($1, module_name,
|
||||||
true, is_export).release();
|
true, is_export);
|
||||||
|
activation_mgr->CreatingGlobalID(gid);
|
||||||
|
$$ = gid.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
84
src/scan.l
84
src/scan.l
|
@ -29,8 +29,6 @@
|
||||||
#include "zeek/DNS_Mgr.h"
|
#include "zeek/DNS_Mgr.h"
|
||||||
#include "zeek/Expr.h"
|
#include "zeek/Expr.h"
|
||||||
#include "zeek/Func.h"
|
#include "zeek/Func.h"
|
||||||
#include "zeek/Stmt.h"
|
|
||||||
#include "zeek/IntrusivePtr.h"
|
|
||||||
#include "zeek/Val.h"
|
#include "zeek/Val.h"
|
||||||
#include "zeek/Var.h"
|
#include "zeek/Var.h"
|
||||||
#include "zeek/Debug.h"
|
#include "zeek/Debug.h"
|
||||||
|
@ -41,6 +39,7 @@
|
||||||
#include "zeek/Traverse.h"
|
#include "zeek/Traverse.h"
|
||||||
#include "zeek/module_util.h"
|
#include "zeek/module_util.h"
|
||||||
#include "zeek/ScannedFile.h"
|
#include "zeek/ScannedFile.h"
|
||||||
|
#include "zeek/ActivationManager.h"
|
||||||
|
|
||||||
#include "zeek/analyzer/Analyzer.h"
|
#include "zeek/analyzer/Analyzer.h"
|
||||||
#include "zeek/zeekygen/Manager.h"
|
#include "zeek/zeekygen/Manager.h"
|
||||||
|
@ -55,9 +54,10 @@ extern YYLTYPE yylloc; // holds start line and column of token
|
||||||
extern zeek::EnumType* cur_enum_type;
|
extern zeek::EnumType* cur_enum_type;
|
||||||
|
|
||||||
// Track the @if... depth.
|
// Track the @if... depth.
|
||||||
static std::intptr_t conditional_depth = 0;
|
static int conditional_depth = 0;
|
||||||
|
|
||||||
zeek::detail::int_list entry_cond_depth; // @if depth upon starting file
|
zeek::detail::int_list entry_cond_depth; // @if depth upon starting file
|
||||||
|
zeek::detail::int_list entry_act_depth; // @if &analyze depth upon starting file
|
||||||
zeek::detail::int_list entry_pragma_stack_depth; // @pragma push depth upon starting file
|
zeek::detail::int_list entry_pragma_stack_depth; // @pragma push depth upon starting file
|
||||||
static std::vector<std::string> pragma_stack; // stack of @pragma pushes
|
static std::vector<std::string> pragma_stack; // stack of @pragma pushes
|
||||||
|
|
||||||
|
@ -127,6 +127,9 @@ static std::string find_relative_script_file(const std::string& filename)
|
||||||
|
|
||||||
static void start_conditional()
|
static void start_conditional()
|
||||||
{
|
{
|
||||||
|
if ( activation_mgr->InsideConditional() )
|
||||||
|
zeek::reporter->Warning("@conditional inside @if &analyze");
|
||||||
|
|
||||||
++conditional_depth;
|
++conditional_depth;
|
||||||
++conditional_epoch;
|
++conditional_epoch;
|
||||||
|
|
||||||
|
@ -155,17 +158,18 @@ static void do_pragma(const std::string& pragma)
|
||||||
|
|
||||||
if ( parts[0] == "push" )
|
if ( parts[0] == "push" )
|
||||||
{
|
{
|
||||||
if ( parts.size() < 2 )
|
if ( parts.size() < 2 )
|
||||||
{
|
{
|
||||||
zeek::reporter->FatalError("@pragma push without value");
|
zeek::reporter->FatalError("@pragma push without value");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( known_stack_pragmas.count(parts[1]) == 0 )
|
if ( known_stack_pragmas.count(parts[1]) == 0 )
|
||||||
zeek::reporter->Warning("pushing unknown @pragma value '%s'", parts[1].c_str());
|
zeek::reporter->Warning("pushing unknown @pragma value '%s'", parts[1].c_str());
|
||||||
|
|
||||||
pragma_stack.push_back(parts[1]);
|
pragma_stack.push_back(parts[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( parts[0] == "pop" )
|
else if ( parts[0] == "pop" )
|
||||||
{
|
{
|
||||||
if ( pragma_stack.empty() || pragma_stack.size() == entry_pragma_stack_depth.back() )
|
if ( pragma_stack.empty() || pragma_stack.size() == entry_pragma_stack_depth.back() )
|
||||||
|
@ -176,10 +180,11 @@ static void do_pragma(const std::string& pragma)
|
||||||
|
|
||||||
// Popping with a value: Verify it's popping the right thing. Not providing
|
// Popping with a value: Verify it's popping the right thing. Not providing
|
||||||
// a pop value itself is valid. Don't return, probably blows up below anyway.
|
// a pop value itself is valid. Don't return, probably blows up below anyway.
|
||||||
if ( parts.size() > 1 && pragma_stack.back() != parts[1] ) {
|
if ( parts.size() > 1 && pragma_stack.back() != parts[1] )
|
||||||
|
{
|
||||||
zeek::reporter->Error("@pragma pop with unexpected '%s', expected '%s'",
|
zeek::reporter->Error("@pragma pop with unexpected '%s', expected '%s'",
|
||||||
parts[1].c_str(), pragma_stack.back().c_str());
|
parts[1].c_str(), pragma_stack.back().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just pop anything
|
// Just pop anything
|
||||||
pragma_stack.pop_back();
|
pragma_stack.pop_back();
|
||||||
|
@ -397,6 +402,8 @@ when return TOK_WHEN;
|
||||||
&backend return TOK_ATTR_BACKEND;
|
&backend return TOK_ATTR_BACKEND;
|
||||||
&ordered return TOK_ATTR_ORDERED;
|
&ordered return TOK_ATTR_ORDERED;
|
||||||
|
|
||||||
|
")"{OWS}&analyze return TOK_ATTR_ANALYZE; // see parse.y for discussion of weirdness
|
||||||
|
|
||||||
@deprecated.* {
|
@deprecated.* {
|
||||||
auto num_files = file_stack.length();
|
auto num_files = file_stack.length();
|
||||||
auto comment = zeek::util::skip_whitespace(yytext + 11);
|
auto comment = zeek::util::skip_whitespace(yytext + 11);
|
||||||
|
@ -534,11 +541,12 @@ when return TOK_WHEN;
|
||||||
@endif do_atendif();
|
@endif do_atendif();
|
||||||
|
|
||||||
<IGNORE>@if start_conditional();
|
<IGNORE>@if start_conditional();
|
||||||
|
<IGNORE>&analyze zeek::reporter->Warning("@if &analyze inside regular @if");
|
||||||
<IGNORE>@ifdef start_conditional();
|
<IGNORE>@ifdef start_conditional();
|
||||||
<IGNORE>@ifndef start_conditional();
|
<IGNORE>@ifndef start_conditional();
|
||||||
<IGNORE>@else return TOK_ATELSE;
|
<IGNORE>@else return TOK_ATELSE;
|
||||||
<IGNORE>@endif return TOK_ATENDIF;
|
<IGNORE>@endif return TOK_ATENDIF;
|
||||||
<IGNORE>[^@\r\n]+ /* eat */
|
<IGNORE>[^@&\r\n]+ /* eat */
|
||||||
<IGNORE>. /* eat */
|
<IGNORE>. /* eat */
|
||||||
|
|
||||||
T RET_CONST(zeek::val_mgr->True()->Ref())
|
T RET_CONST(zeek::val_mgr->True()->Ref())
|
||||||
|
@ -802,6 +810,7 @@ static int load_files(const char* orig_file)
|
||||||
current_file_has_conditionals = files_with_conditionals.count(filename) > 0;
|
current_file_has_conditionals = files_with_conditionals.count(filename) > 0;
|
||||||
|
|
||||||
entry_cond_depth.push_back(conditional_depth);
|
entry_cond_depth.push_back(conditional_depth);
|
||||||
|
entry_act_depth.push_back(activation_mgr->ActivationDepth());
|
||||||
entry_pragma_stack_depth.push_back(pragma_stack.size());
|
entry_pragma_stack_depth.push_back(pragma_stack.size());
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -846,10 +855,8 @@ static void resume_processing()
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_atif(zeek::detail::Expr* expr)
|
void do_atif(zeek::detail::Expr* expr, bool is_activate)
|
||||||
{
|
{
|
||||||
start_conditional();
|
|
||||||
|
|
||||||
LocalNameFinder cb;
|
LocalNameFinder cb;
|
||||||
expr->Traverse(&cb);
|
expr->Traverse(&cb);
|
||||||
zeek::ValPtr val;
|
zeek::ValPtr val;
|
||||||
|
@ -865,11 +872,28 @@ void do_atif(zeek::detail::Expr* expr)
|
||||||
if ( ! val )
|
if ( ! val )
|
||||||
{
|
{
|
||||||
expr->Error("invalid expression in @if");
|
expr->Error("invalid expression in @if");
|
||||||
|
|
||||||
|
if ( ! is_activate )
|
||||||
|
start_conditional();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! val->AsBool() )
|
bool is_true = val->AsBool();
|
||||||
begin_ignoring();
|
|
||||||
|
if ( is_activate )
|
||||||
|
{
|
||||||
|
if ( conditional_depth > 0 )
|
||||||
|
zeek::reporter->Warning("@if &analyze inside conditional");
|
||||||
|
activation_mgr->Start({zeek::NewRef{}, expr}, is_true, conditional_depth);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start_conditional();
|
||||||
|
|
||||||
|
if ( ! is_true )
|
||||||
|
begin_ignoring();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_atifdef(const char* id)
|
void do_atifdef(const char* id)
|
||||||
|
@ -904,6 +928,12 @@ void do_atifndef(const char *id)
|
||||||
|
|
||||||
void do_atelse()
|
void do_atelse()
|
||||||
{
|
{
|
||||||
|
if ( activation_mgr->InsideConditional(conditional_depth) )
|
||||||
|
{ // This is the @else corresponding to an @if &analyze.
|
||||||
|
activation_mgr->SwitchToElse();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( conditional_depth == 0 )
|
if ( conditional_depth == 0 )
|
||||||
zeek::reporter->Error("@else without @if...");
|
zeek::reporter->Error("@else without @if...");
|
||||||
|
|
||||||
|
@ -918,6 +948,15 @@ void do_atelse()
|
||||||
|
|
||||||
void do_atendif()
|
void do_atendif()
|
||||||
{
|
{
|
||||||
|
if ( activation_mgr->InsideConditional(conditional_depth) )
|
||||||
|
{ // We're ending an @if &analyze.
|
||||||
|
if ( activation_mgr->ActivationDepth() <= entry_act_depth.back() )
|
||||||
|
zeek::reporter->Error("unbalanced @if &analyze... @endif");
|
||||||
|
else
|
||||||
|
activation_mgr->End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( conditional_depth <= entry_cond_depth.back() )
|
if ( conditional_depth <= entry_cond_depth.back() )
|
||||||
zeek::reporter->Error("unbalanced @if... @endif");
|
zeek::reporter->Error("unbalanced @if... @endif");
|
||||||
|
|
||||||
|
@ -1000,6 +1039,13 @@ int yywrap()
|
||||||
entry_cond_depth.pop_back();
|
entry_cond_depth.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( entry_act_depth.size() > 0 )
|
||||||
|
{
|
||||||
|
if ( activation_mgr->ActivationDepth() > entry_act_depth.back() )
|
||||||
|
zeek::reporter->FatalError("unbalanced @if &analyze... @endif");
|
||||||
|
entry_act_depth.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
if ( entry_pragma_stack_depth.size() > 0 )
|
if ( entry_pragma_stack_depth.size() > 0 )
|
||||||
{
|
{
|
||||||
if ( pragma_stack.size() > entry_pragma_stack_depth.back() )
|
if ( pragma_stack.size() > entry_pragma_stack_depth.back() )
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT
|
#define DOCTEST_CONFIG_IMPLEMENT
|
||||||
|
|
||||||
#include "zeek/3rdparty/doctest.h"
|
#include "zeek/3rdparty/doctest.h"
|
||||||
|
#include "zeek/ActivationManager.h"
|
||||||
#include "zeek/Anon.h"
|
#include "zeek/Anon.h"
|
||||||
#include "zeek/DFA.h"
|
#include "zeek/DFA.h"
|
||||||
#include "zeek/DNS_Mgr.h"
|
#include "zeek/DNS_Mgr.h"
|
||||||
|
@ -183,6 +184,7 @@ zeek::plugin::Manager* zeek::plugin_mgr = nullptr;
|
||||||
zeek::detail::RuleMatcher* zeek::detail::rule_matcher = nullptr;
|
zeek::detail::RuleMatcher* zeek::detail::rule_matcher = nullptr;
|
||||||
zeek::detail::DNS_Mgr* zeek::detail::dns_mgr = nullptr;
|
zeek::detail::DNS_Mgr* zeek::detail::dns_mgr = nullptr;
|
||||||
zeek::detail::TimerMgr* zeek::detail::timer_mgr = nullptr;
|
zeek::detail::TimerMgr* zeek::detail::timer_mgr = nullptr;
|
||||||
|
zeek::detail::ActivationManager* zeek::detail::activation_mgr;
|
||||||
|
|
||||||
zeek::logging::Manager* zeek::log_mgr = nullptr;
|
zeek::logging::Manager* zeek::log_mgr = nullptr;
|
||||||
zeek::threading::Manager* zeek::thread_mgr = nullptr;
|
zeek::threading::Manager* zeek::thread_mgr = nullptr;
|
||||||
|
@ -443,6 +445,7 @@ static void terminate_zeek()
|
||||||
delete session_mgr;
|
delete session_mgr;
|
||||||
delete fragment_mgr;
|
delete fragment_mgr;
|
||||||
delete telemetry_mgr;
|
delete telemetry_mgr;
|
||||||
|
delete activation_mgr;
|
||||||
#ifdef HAVE_SPICY
|
#ifdef HAVE_SPICY
|
||||||
delete spicy_mgr;
|
delete spicy_mgr;
|
||||||
#endif
|
#endif
|
||||||
|
@ -673,6 +676,7 @@ SetupResult setup(int argc, char** argv, Options* zopts)
|
||||||
|
|
||||||
auto zeekygen_cfg = options.zeekygen_config_file.value_or("");
|
auto zeekygen_cfg = options.zeekygen_config_file.value_or("");
|
||||||
zeekygen_mgr = new zeekygen::detail::Manager(zeekygen_cfg, zeek_argv[0]);
|
zeekygen_mgr = new zeekygen::detail::Manager(zeekygen_cfg, zeek_argv[0]);
|
||||||
|
activation_mgr = new ActivationManager();
|
||||||
|
|
||||||
add_essential_input_file("base/init-bare.zeek");
|
add_essential_input_file("base/init-bare.zeek");
|
||||||
add_essential_input_file("builtin-plugins/__preload__.zeek");
|
add_essential_input_file("builtin-plugins/__preload__.zeek");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue