@@ -137,6 +137,39 @@ RulesConfig::add_rule(std::unique_ptr<RuleSet> rule)
137137 }
138138}
139139
140+ // Helper function to validate rule completion
141+ static bool
142+ validate_rule_completion (RuleSet *rule, const std::string &fname, int lineno)
143+ {
144+ // Early return if rule has operators - no validation errors possible
145+ if (!rule || rule->has_operator ()) {
146+ return true ;
147+ }
148+
149+ switch (rule->get_clause ()) {
150+ case Parser::CondClause::ELIF :
151+ if (rule->cur_section ()->group .has_conditions ()) {
152+ TSError (" [%s] ELIF conditions without operators are not allowed in file: %s, lineno: %d" , PLUGIN_NAME , fname.c_str (), lineno);
153+ return false ;
154+ }
155+ break ;
156+
157+ case Parser::CondClause::ELSE :
158+ TSError (" [%s] conditions not allowed in ELSE clause in file: %s, lineno: %d" , PLUGIN_NAME , fname.c_str (), lineno);
159+ return false ;
160+
161+ case Parser::CondClause::OPER :
162+ TSError (" [%s] conditions without operators are not allowed in file: %s, lineno: %d" , PLUGIN_NAME , fname.c_str (), lineno);
163+ return false ;
164+
165+ case Parser::CondClause::COND :
166+ // COND clause without operators - potentially valid in some cases
167+ break ;
168+ }
169+
170+ return true ;
171+ }
172+
140173// /////////////////////////////////////////////////////////////////////////////
141174// Config parser, use to parse both the global, and per-remap, configurations.
142175//
@@ -220,21 +253,14 @@ RulesConfig::parse_config(const std::string &fname, TSHttpHookID default_hook, c
220253 }
221254
222255 // If we are at the beginning of a new condition, save away the previous rule (but only if it has operators).
223- if (p.is_cond () && rule) {
224- bool transfer = rule-> cur_section ()-> has_operator ();
225- auto rule_clause = rule->get_clause ();
256+ if (p.is_cond () && rule && is_hook ) {
257+ // Only validate and save when starting a NEW rule (hook condition)
258+ bool transfer = rule->cur_section ()-> has_operator ();
226259
227- if (rule_clause == Parser::CondClause::ELIF ) {
228- if (is_hook) {
229- TSError (" [%s] ELIF without operators are not allowed in file: %s, lineno: %d" , PLUGIN_NAME , fname.c_str (), lineno);
230- return false ;
231- }
232- } else if (rule_clause == Parser::CondClause::ELSE ) {
233- if (!transfer) {
234- TSError (" [%s] conditions not allowed in ELSE clause in file: %s, lineno: %d" , PLUGIN_NAME , fname.c_str (), lineno);
235- return false ;
236- }
260+ if (!validate_rule_completion (rule.get (), fname, lineno)) {
261+ return false ;
237262 }
263+
238264 if (transfer) {
239265 add_rule (std::move (rule));
240266 }
@@ -327,8 +353,14 @@ RulesConfig::parse_config(const std::string &fname, TSHttpHookID default_hook, c
327353 }
328354
329355 // Add the last rule (possibly the only rule)
330- if (rule && rule->has_operator ()) {
331- add_rule (std::move (rule));
356+ if (rule) {
357+ if (!validate_rule_completion (rule.get (), fname, lineno)) {
358+ return false ;
359+ }
360+
361+ if (rule->has_operator ()) {
362+ add_rule (std::move (rule));
363+ }
332364 }
333365
334366 // Collect all resource IDs that we need
0 commit comments