From a32e76448fcd75ff4da6f0dd51fdf6d7c07a5214 Mon Sep 17 00:00:00 2001 From: Amos Jeffries Date: Fri, 8 Mar 2013 12:40:02 +1300 Subject: [PATCH] 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. --- src/errorpage.cc | 21 ++++++++++----------- src/errorpage.h | 11 ++++++++--- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/errorpage.cc b/src/errorpage.cc index a8d4f452c5..2ea0226424 100644 --- a/src/errorpage.cc +++ b/src/errorpage.cc @@ -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. */ diff --git a/src/errorpage.h b/src/errorpage.h index dd7bdc1ffe..46c15e8465 100644 --- a/src/errorpage.h +++ b/src/errorpage.h @@ -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 */ -- 2.47.2