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;

Reply via email to