extended script validation to be call-able on a per-function basis

This commit is contained in:
Vern Paxson 2023-04-01 12:55:29 -07:00
parent 5718046b96
commit 3a99e60d1c
2 changed files with 42 additions and 16 deletions

View file

@ -12,6 +12,8 @@ namespace zeek::detail
class BreakNextScriptValidation : public TraversalCallback class BreakNextScriptValidation : public TraversalCallback
{ {
public: public:
BreakNextScriptValidation(bool _report) : report(_report) { }
TraversalCode PreStmt(const Stmt* stmt) TraversalCode PreStmt(const Stmt* stmt)
{ {
if ( ! StmtIsRelevant(stmt) ) if ( ! StmtIsRelevant(stmt) )
@ -20,21 +22,13 @@ public:
stmt_depths[stmt->Tag()] += 1; stmt_depths[stmt->Tag()] += 1;
if ( stmt->Tag() == STMT_BREAK && ! BreakStmtIsValid() ) if ( stmt->Tag() == STMT_BREAK && ! BreakStmtIsValid() )
{ Report(stmt, "break statement used outside of for, while or "
zeek::reporter->PushLocation(stmt->GetLocationInfo()); "switch statement and not within a hook. "
zeek::reporter->Warning("break statement used outside of for, while or " "With v6.1 this will become an error.");
"switch statement and not within a hook. "
"With v6.1 this will become an error.");
zeek::reporter->PopLocation();
}
if ( stmt->Tag() == STMT_NEXT && ! NextStmtIsValid() ) if ( stmt->Tag() == STMT_NEXT && ! NextStmtIsValid() )
{ Report(stmt, "next statement used outside of for or while statement. "
zeek::reporter->PushLocation(stmt->GetLocationInfo()); "With v6.1 this will become an error.");
zeek::reporter->Warning("next statement used outside of for or while statement. "
"With v6.1 this will become an error.");
zeek::reporter->PopLocation();
}
return TC_CONTINUE; return TC_CONTINUE;
} }
@ -71,6 +65,8 @@ public:
return TC_CONTINUE; return TC_CONTINUE;
} }
bool IsValid() const { return valid_script; }
private: private:
bool StmtIsRelevant(const Stmt* stmt) bool StmtIsRelevant(const Stmt* stmt)
{ {
@ -87,13 +83,35 @@ private:
bool NextStmtIsValid() { return stmt_depths[STMT_FOR] > 0 || stmt_depths[STMT_WHILE] > 0; } bool NextStmtIsValid() { return stmt_depths[STMT_FOR] > 0 || stmt_depths[STMT_WHILE] > 0; }
void Report(const Stmt* stmt, const char* msg)
{
if ( report )
{
zeek::reporter->PushLocation(stmt->GetLocationInfo());
zeek::reporter->Warning("%s", msg);
zeek::reporter->PopLocation();
}
valid_script = false;
}
std::unordered_map<StmtTag, int> stmt_depths; std::unordered_map<StmtTag, int> stmt_depths;
int hook_depth = 0; int hook_depth = 0;
bool report; // whether to report problems via "reporter"
bool valid_script = true;
}; };
void script_validation() void script_validation()
{ {
zeek::detail::BreakNextScriptValidation bn_cb; BreakNextScriptValidation bn_cb(true);
zeek::detail::traverse_all(&bn_cb); traverse_all(&bn_cb);
} }
bool script_is_valid(const Stmt* stmt)
{
BreakNextScriptValidation bn_cb(false);
stmt->Traverse(&bn_cb);
return bn_cb.IsValid();
}
} }

View file

@ -4,9 +4,17 @@
namespace zeek::detail namespace zeek::detail
{ {
class Stmt;
/** /**
* Run extra validations on the parsed AST after everything is initialized * Run extra validations on the parsed AST after everything is initialized
* and report any errors via zeek::reporter->Error(). * and report any errors via deprecation warnings or zeek::reporter->Error().
*/ */
void script_validation(); void script_validation();
/**
* Returns true if the given script statement (body) is valid.
*/
bool script_is_valid(const Stmt* s);
} }