------------------------------------------------------------ revno: 11796 revision-id: squid3@treenet.co.nz-20130308020611-e57qtsxe9yt93x23 parent: squid3@treenet.co.nz-20130302014531-7ayfknnrx8nshp1o committer: Amos Jeffries branch nick: 3.2 timestamp: Thu 2013-03-07 19:06:11 -0700 message: Regression fix: Accept-Language header parse 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. ------------------------------------------------------------ # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: squid3@treenet.co.nz-20130308020611-e57qtsxe9yt93x23 # target_branch: http://bzr.squid-cache.org/bzr/squid3/branches\ # /SQUID_3_2 # testament_sha1: f44a5d33022ff3ba5fbcd53e146f6f38e2093eb6 # timestamp: 2013-03-08 02:06:30 +0000 # source_branch: http://bzr.squid-cache.org/bzr/squid3/branches\ # /SQUID_3_2 # base_revision_id: squid3@treenet.co.nz-20130302014531-\ # 7ayfknnrx8nshp1o # # Begin patch === modified file 'src/errorpage.cc' --- src/errorpage.cc 2012-07-28 05:38:50 +0000 +++ src/errorpage.cc 2013-03-08 02:06:11 +0000 @@ -376,17 +376,9 @@ 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: @@ -417,6 +409,13 @@ *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. */ === modified file 'src/errorpage.h' --- src/errorpage.h 2012-02-05 11:37:57 +0000 +++ src/errorpage.h 2013-03-08 02:06:11 +0000 @@ -307,11 +307,16 @@ /** * 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 */