On 30/07/2013 5:25 a.m., Amos Jeffries wrote:
Looks like nobody actually ran the trivial "-k parse" test using
3.HEAD or the initial quoted strings code.
Attached is a patch which adds a secondary form of undo for handling
incorrectly identified ConfigParser::FunctionNameToken elements.
Instead of aborting Squid on any non-function token containing a '('
we take the wrongly identified assumed function name element and
reform it with the '(' delimiter and trailing element. The resulting
aggregate token which should have been identified initially is then
sent to the upper parser layer.
Amos
Updated patch. This one does all the above plus:
* handles the case where a token starts with '(' as in the default
refresh_pattern for cgi-bin handling.
* removes $macro handling, resolving the case where $ symbols in regex
patterns are placed inside "-quoted strings
* adds debug statemets for NextToken response outputs
* adds debugs statements for parameters("foo") file loading
Amos
=== modified file 'src/ConfigParser.cc'
--- src/ConfigParser.cc 2013-07-22 01:26:09 +0000
+++ src/ConfigParser.cc 2013-07-29 23:56:52 +0000
@@ -54,7 +54,7 @@
if (!CfgFiles.empty()) {
std::ostringstream message;
CfgFile *f = CfgFiles.top();
- message << "Bungled " << f->filePath << " line " << f->lineNo <<
+ message << "Bungled (#1) " << f->filePath << " line " << f->lineNo <<
": " << f->currentLine << std::endl;
CfgFiles.pop();
delete f;
@@ -70,7 +70,7 @@
std::string msg = message.str();
fatalf("%s", msg.c_str());
} else
- fatalf("Bungled %s line %d: %s",
+ fatalf("Bungled (#2) %s line %d: %s",
cfg_filename, config_lineno, config_input_line);
}
@@ -183,9 +183,11 @@
if (*s == '\\' && isalnum(*( s + 1))) {
debugs(3, DBG_CRITICAL, "Unsupported escape sequence: " << s);
self_destruct();
+#if 0 // ${macro} are evaluated before this code and this breaks parsing of
regex tokens
} else if (*s == '$' && quoteChar == '"') {
debugs(3, DBG_CRITICAL, "Unsupported cfg macro: " << s);
self_destruct();
+#endif
} else if (*s == '%' && quoteChar == '"' && (!AllowMacros_ )) {
debugs(3, DBG_CRITICAL, "Macros are not supported here: " << s);
self_destruct();
@@ -232,8 +234,13 @@
const char *sep;
if (legacy)
sep = w_space;
- else
+ else {
sep = w_space "(";
+ // NP: '(' is delimiter for function() name elements
+ // ignore detecting any '(' without a prefix
+ while (*nextToken == '(')
+ ++nextToken;
+ }
nextToken += strcspn(nextToken, sep);
if (!legacy && *nextToken == '(')
@@ -262,8 +269,10 @@
char *
ConfigParser::NextToken()
{
- if ((LastToken = ConfigParser::Undo()))
+ if ((LastToken = ConfigParser::Undo())) {
+ debugs(3, 6, "TOKEN (undone): " << LastToken);
return LastToken;
+ }
char *token = NULL;
do {
@@ -273,6 +282,7 @@
if (!token) {
assert(!wordfile->isOpen());
CfgFiles.pop();
+ debugs(3, 4, "CfgFiles.pop " << wordfile->filePath);
delete wordfile;
}
}
@@ -280,7 +290,8 @@
if (!token)
token = NextElement(LastTokenType);
- if (token && LastTokenType == ConfigParser::FunctionNameToken &&
strcmp("parameters", token) == 0) {
+ if (token && LastTokenType == ConfigParser::FunctionNameToken) {
+ if (strcmp("parameters", token) == 0) {
char *path = NextToken();
if (LastTokenType != ConfigParser::QuotedToken) {
debugs(3, DBG_CRITICAL, "Quoted filename missing: " << token);
@@ -309,15 +320,26 @@
self_destruct();
return NULL;
}
+ debugs(3, 4, "CfgFiles.push " << wordfile->filePath);
CfgFiles.push(wordfile);
token = NULL;
- } else if (token && LastTokenType == ConfigParser::FunctionNameToken)
{
- debugs(3, DBG_CRITICAL, "Unknown cfg function: " << token);
- self_destruct();
- return NULL;
+ } else {
+ debugs(3, 5, "Unknown cfg function: " << token);
+
+ // we have determined tha the whole of this token is not a
built-in function() style token
+ // ignore any further '(' as well
+ // concatenate this token, the '('-delimiter which confused things
and next token.
+ // send to the undo queue for better processing next time around
+ LOCAL_ARRAY(char, tbuf, CONFIG_LINE_LIMIT);
+ const char *temp = NextElement(LastTokenType, false);
+ snprintf(tbuf, sizeof(tbuf)-1, "%s(%s", token, temp);
+ debugs(3, 6, "TOKEN (reconstruct): " << tbuf);
+ return (LastToken = tbuf);
}
+ }
} while (token == NULL && !CfgFiles.empty());
+ debugs(3, 6, "TOKEN: " << token);
return (LastToken = token);
}
@@ -344,6 +366,7 @@
LastTokenType = ConfigParser::SimpleToken;
CfgPos = NULL;
+ debugs(3, 6, "TOKEN (to eol): " << token);
return (LastToken = token);
}
@@ -375,6 +398,7 @@
ConfigParser::CfgFile::startParse(char *path)
{
assert(wordFile == NULL);
+ debugs(3, 3, "Parsing from " << path);
if ((wordFile = fopen(path, "r")) == NULL) {
debugs(3, DBG_CRITICAL, "file :" << path << " not found");
return false;