From 3a99e60d1c4f44ee06a6aec709a3e2f5041abc49 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Sat, 1 Apr 2023 12:55:29 -0700 Subject: [PATCH] extended script validation to be call-able on a per-function basis --- src/ScriptValidation.cc | 48 ++++++++++++++++++++++++++++------------- src/ScriptValidation.h | 10 ++++++++- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/ScriptValidation.cc b/src/ScriptValidation.cc index a0e59b118b..3accd8dbe6 100644 --- a/src/ScriptValidation.cc +++ b/src/ScriptValidation.cc @@ -12,6 +12,8 @@ namespace zeek::detail class BreakNextScriptValidation : public TraversalCallback { public: + BreakNextScriptValidation(bool _report) : report(_report) { } + TraversalCode PreStmt(const Stmt* stmt) { if ( ! StmtIsRelevant(stmt) ) @@ -20,21 +22,13 @@ public: stmt_depths[stmt->Tag()] += 1; if ( stmt->Tag() == STMT_BREAK && ! BreakStmtIsValid() ) - { - zeek::reporter->PushLocation(stmt->GetLocationInfo()); - zeek::reporter->Warning("break statement used outside of for, while or " - "switch statement and not within a hook. " - "With v6.1 this will become an error."); - zeek::reporter->PopLocation(); - } + Report(stmt, "break statement used outside of for, while or " + "switch statement and not within a hook. " + "With v6.1 this will become an error."); if ( stmt->Tag() == STMT_NEXT && ! NextStmtIsValid() ) - { - zeek::reporter->PushLocation(stmt->GetLocationInfo()); - zeek::reporter->Warning("next statement used outside of for or while statement. " - "With v6.1 this will become an error."); - zeek::reporter->PopLocation(); - } + Report(stmt, "next statement used outside of for or while statement. " + "With v6.1 this will become an error."); return TC_CONTINUE; } @@ -71,6 +65,8 @@ public: return TC_CONTINUE; } + bool IsValid() const { return valid_script; } + private: bool StmtIsRelevant(const Stmt* stmt) { @@ -87,13 +83,35 @@ private: 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 stmt_depths; int hook_depth = 0; + bool report; // whether to report problems via "reporter" + bool valid_script = true; }; void script_validation() { - zeek::detail::BreakNextScriptValidation bn_cb; - zeek::detail::traverse_all(&bn_cb); + BreakNextScriptValidation bn_cb(true); + traverse_all(&bn_cb); } + +bool script_is_valid(const Stmt* stmt) + { + BreakNextScriptValidation bn_cb(false); + stmt->Traverse(&bn_cb); + return bn_cb.IsValid(); + } + } diff --git a/src/ScriptValidation.h b/src/ScriptValidation.h index 22c9cb3b4a..05fc3a3ded 100644 --- a/src/ScriptValidation.h +++ b/src/ScriptValidation.h @@ -4,9 +4,17 @@ namespace zeek::detail { +class Stmt; + /** * 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(); + +/** + * Returns true if the given script statement (body) is valid. + */ +bool script_is_valid(const Stmt* s); + }