]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Regression fix: Accept-Language header parse
authorAmos Jeffries <squid3@treenet.co.nz>
Thu, 7 Mar 2013 23:40:02 +0000 (12:40 +1300)
committerAmos Jeffries <squid3@treenet.co.nz>
Thu, 7 Mar 2013 23:40:02 +0000 (12:40 +1300)
When handling error page negotiation the header parse to detect language
code can enter into an infinite loop. Recover the 3.1 series behaviour
and fix an additional pre-existing off-by-1 error.

The errors were introduced in trunk rev.11496 in 3.2.0.9.

src/errorpage.cc
src/errorpage.h

index a8d4f452c5cb5863ead5c4955e9445630955ed0a..2ea02264248b8ed8627488efcd5a53da3e9ccf14 100644 (file)
@@ -381,17 +381,9 @@ bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &p
     while (pos < hdr.size()) {
         char *dt = lang;
 
-        if (!pos) {
-            /* skip any initial whitespace. */
-            while (pos < hdr.size() && xisspace(hdr[pos]))
-                ++pos;
-        } else {
-            // IFF we terminated the tag on whitespace or ';' we need to skip to the next ',' or end of header.
-            while (pos < hdr.size() && hdr[pos] != ',')
-                ++pos;
-            if (hdr[pos] == ',')
-                ++pos;
-        }
+        /* skip any initial whitespace. */
+        while (pos < hdr.size() && xisspace(hdr[pos]))
+            ++pos;
 
         /*
          * Header value format:
@@ -422,6 +414,13 @@ bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &p
         *dt = '\0'; // nul-terminated the filename content string before system use.
         ++dt;
 
+        // if we terminated the tag on garbage or ';' we need to skip to the next ',' or end of header.
+        while (pos < hdr.size() && hdr[pos] != ',')
+            ++pos;
+
+        if (pos < hdr.size() && hdr[pos] == ',')
+            ++pos;
+
         debugs(4, 9, HERE << "STATE: dt='" << dt << "', lang='" << lang << "', pos=" << pos << ", buf='" << ((pos < hdr.size()) ? hdr.substr(pos,hdr.size()) : "") << "'");
 
         /* if we found anything we might use, try it. */
index dd7bdc1ffea72639f854f610c21be51111dc158e..46c15e8465bf3076e2ebd5937b93e9702e11a4a1 100644 (file)
@@ -311,11 +311,16 @@ protected:
 /**
  * Parses the Accept-Language header value and return one language item on
  * each call.
+ * Will ignore any whitespace, q-values, and detectably invalid language
+ * codes in the header.
+ *
  * \param hdr is the Accept-Language header value
- * \param lang a buffer given by the user to store parsed language
+ * \param lang a buffer to store parsed language code in
  * \param langlen the length of the lang buffer
- * \param pos it is used to store the state of parsing. Must be "0" on first call
- * \return true on success, false otherwise
+ * \param pos is used to store the offset state of parsing. Must be "0" on first call.
+ *            Will be altered to point at the start of next field-value.
+ * \return true if something looking like a language token has been placed in lang, false otherwise
  */
 bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &pos);
+
 #endif /* SQUID_ERRORPAGE_H */