=== modified file 'src/HttpHeaderTools.cc' --- src/HttpHeaderTools.cc 2010-11-02 00:12:43 +0000 +++ src/HttpHeaderTools.cc 2011-05-30 13:29:36 +0000 @@ -325,60 +325,91 @@ /** * Parses a quoted-string field (RFC 2616 section 2.2), complains if * something went wrong, returns non-zero on success. * Un-escapes quoted-pair characters found within the string. * start should point at the first double-quote. */ int httpHeaderParseQuotedString(const char *start, const int len, String *val) { const char *end, *pos; val->clean(); if (*start != '"') { debugs(66, 2, "failed to parse a quoted-string header field near '" << start << "'"); return 0; } pos = start + 1; while (*pos != '"' && len > (pos-start)) { + + if (*pos =='\r') { + pos++; + if ((pos-start) > len || *pos != '\n') { + debugs(66, 2, "failed to parse a quoted-string header field with \'\\r\' octet " << (start-pos) + << " bytes into '" << start << "'"); + val->clean(); + return 0; + } + } + + if (*pos == '\n') { + pos++; + if ( (pos-start) > len || (*pos != ' ' && *pos != '\t')) { + debugs(66, 2, "failed to parse multiline quoted-string header field '" << start << "'"); + val->clean(); + return 0; + } + val->append(" "); + pos++; + debugs(66, 2, "len < pos-start => " << len << " < " << (pos-start)); + continue; + } + bool quoted = (*pos == '\\'); - if (quoted) + if (quoted) { pos++; - if (!*pos || (pos-start) > len) { - debugs(66, 2, "failed to parse a quoted-string header field near '" << start << "'"); - val->clean(); - return 0; + if (!*pos || (pos-start) > len) { + debugs(66, 2, "failed to parse a quoted-string header field near '" << start << "'"); + val->clean(); + return 0; + } } end = pos; - while (end <= (start+len) && *end != '\\' && *end != '\"' && *end > 0x1F && *end != 0x7F) + while (end < (start+len) && *end != '\\' && *end != '\"' && *end > 0x1F && *end != 0x7F) end++; - if (*end <= 0x1F || *end == 0x7F) { + if ((*end <= 0x1F && *end != '\r' && *end != '\n') || *end == 0x7F) { debugs(66, 2, "failed to parse a quoted-string header field with CTL octet " << (start-pos) << " bytes into '" << start << "'"); val->clean(); return 0; } val->append(pos, end-pos); pos = end; } + + if (*pos != '\"') { + debugs(66, 2, "failed to parse a quoted-string header field which did not end with \" "); + val->clean(); + return 0; + } /* Make sure it's defined even if empty "" */ if (!val->defined()) val->limitInit("", 0); return 1; } /** * Checks the anonymizer (header_access) configuration. * * \retval 0 Header is explicitly blocked for removal * \retval 1 Header is explicitly allowed * \retval 1 Header has been replaced, the current version can be used. * \retval 1 Header has no access controls to test */ static int httpHdrMangle(HttpHeaderEntry * e, HttpRequest * request, int req_or_rep) { int retval; /* check with anonymizer tables */