Skip to content

Commit 64d4769

Browse files
authored
HRW: Bug where after an elif an else may be required (#12536)
This also fixes a small bug in run-plugin
1 parent cfdcfbf commit 64d4769

4 files changed

Lines changed: 56 additions & 18 deletions

File tree

plugins/header_rewrite/conditions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,12 @@ class ConditionGroup : public Condition
786786
}
787787
}
788788

789+
bool
790+
has_conditions() const
791+
{
792+
return _cond != nullptr;
793+
}
794+
789795
private:
790796
Condition *_cond = nullptr; // First pre-condition (linked list)
791797
bool _end = false;

plugins/header_rewrite/header_rewrite.cc

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

plugins/header_rewrite/operators.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1289,7 +1289,7 @@ OperatorRunPlugin::initialize(Parser &p)
12891289
argv[0] = p.from_url();
12901290
argv[1] = p.to_url();
12911291

1292-
for (int i = 0; i < argc; ++i) {
1292+
for (size_t i = 0; i < tokens.size(); ++i) {
12931293
argv[i + 2] = const_cast<char *>(tokens[i].c_str());
12941294
}
12951295

plugins/header_rewrite/parser.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ Parser::parse_line(const std::string &original_line)
164164
}
165165

166166
// This is the main "parser", a helper function to the above tokenizer. NOTE: this modifies (possibly) the tokens list,
167-
// therefore, we pass in a copy of the parsers tokens here, such that the original token list is retained (useful for tests etc.).
167+
// therefore, we pass in a copy of the parser's tokens here, such that the original token list is retained.
168168
bool
169169
Parser::preprocess(std::vector<std::string> tokens)
170170
{
@@ -178,6 +178,7 @@ Parser::preprocess(std::vector<std::string> tokens)
178178
if (m.find_first_of(',') != std::string::npos) {
179179
std::istringstream iss(m);
180180
std::string t;
181+
181182
while (getline(iss, t, ',')) {
182183
_mods.push_back(t);
183184
}
@@ -186,7 +187,6 @@ Parser::preprocess(std::vector<std::string> tokens)
186187
}
187188
tokens.pop_back(); // consume it, so we don't concatenate it into the value
188189
} else {
189-
// Syntax error
190190
TSError("[%s] mods have to be enclosed in []", PLUGIN_NAME);
191191
return false;
192192
}

0 commit comments

Comments
 (0)