--------------------- PatchSet 11317 Date: 2007/03/11 22:34:22 Author: hno Branch: HEAD Tag: (none) Log: Strengthen the HTTP protocol parser further wrt integer errors Members: src/HttpHeader.c:1.92->1.93 src/HttpHeaderTools.c:1.37->1.38 Index: squid/src/HttpHeader.c =================================================================== RCS file: /cvsroot/squid/squid/src/HttpHeader.c,v retrieving revision 1.92 retrieving revision 1.93 diff -u -r1.92 -r1.93 --- squid/src/HttpHeader.c 21 Jan 2007 12:53:56 -0000 1.92 +++ squid/src/HttpHeader.c 11 Mar 2007 22:34:22 -0000 1.93 @@ -1,6 +1,6 @@ /* - * $Id: HttpHeader.c,v 1.92 2007/01/21 12:53:56 adrian Exp $ + * $Id: HttpHeader.c,v 1.93 2007/03/11 22:34:22 hno Exp $ * * DEBUG: section 55 HTTP Header * AUTHOR: Alex Rousskov @@ -419,7 +419,7 @@ httpHeaderParse(HttpHeader * hdr, const char *header_start, const char *header_end) { const char *field_ptr = header_start; - HttpHeaderEntry *e, *e2; + HttpHeaderEntry *e; assert(hdr); assert(header_start && header_end); @@ -487,21 +487,21 @@ else return httpHeaderReset(hdr); } - if (e->id == HDR_CONTENT_LENGTH && (e2 = httpHeaderFindEntry(hdr, e->id)) != NULL) { - if (strCmp(e->value, strBuf(e2->value)) != 0) { - squid_off_t l1, l2; + if (e->id == HDR_CONTENT_LENGTH) { + squid_off_t l1; + HttpHeaderEntry *e2; + if (!httpHeaderParseSize(strBuf(e->value), &l1)) { + debug(55, 1) ("WARNING: Unparseable content-length '%s'\n", strBuf(e->value)); + httpHeaderEntryDestroy(e); + return httpHeaderReset(hdr); + } + e2 = httpHeaderFindEntry(hdr, e->id); + if (e2 && strCmp(e->value, strBuf(e2->value)) != 0) { + squid_off_t l2; debug(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2) ("WARNING: found two conflicting content-length headers in {%s}\n", getStringPrefix(header_start, header_end)); if (!Config.onoff.relaxed_header_parser) { httpHeaderEntryDestroy(e); return httpHeaderReset(hdr); - } - if (!httpHeaderParseSize(strBuf(e->value), &l1)) { - debug(55, 1) ("WARNING: Unparseable content-length '%s'\n", strBuf(e->value)); - httpHeaderEntryDestroy(e); - continue; - } else if (!httpHeaderParseSize(strBuf(e2->value), &l2)) { - debug(55, 1) ("WARNING: Unparseable content-length '%s'\n", strBuf(e2->value)); - httpHeaderDelById(hdr, e2->id); } else if (l1 > l2) { httpHeaderDelById(hdr, e2->id); } else { Index: squid/src/HttpHeaderTools.c =================================================================== RCS file: /cvsroot/squid/squid/src/HttpHeaderTools.c,v retrieving revision 1.37 retrieving revision 1.38 diff -u -r1.37 -r1.38 --- squid/src/HttpHeaderTools.c 26 Jul 2006 20:09:33 -0000 1.37 +++ squid/src/HttpHeaderTools.c 11 Mar 2007 22:34:22 -0000 1.38 @@ -1,6 +1,6 @@ /* - * $Id: HttpHeaderTools.c,v 1.37 2006/07/26 20:09:33 hno Exp $ + * $Id: HttpHeaderTools.c,v 1.38 2007/03/11 22:34:22 hno Exp $ * * DEBUG: section 66 HTTP Header Tools * AUTHOR: Alex Rousskov @@ -315,10 +315,14 @@ int httpHeaderParseInt(const char *start, int *value) { + char *end; + long v; assert(value); - *value = atoi(start); - if (!*value && !xisdigit(*start)) { + errno = 0; + v = *value = strtol(start, &end, 10); + if (start == end || errno != 0 || v != *value) { debug(66, 2) ("failed to parse an int header field near '%s'\n", start); + *value = -1; return 0; } return 1; @@ -327,14 +331,16 @@ int httpHeaderParseSize(const char *start, squid_off_t * value) { - squid_off_t v; char *end; - int res; - v = strto_off_t(start, &end, 10); - res = start != end; + errno = 0; assert(value); - *value = res ? v : 0; - return res; + *value = strto_off_t(start, &end, 10); + if (start == end || errno != 0) { + debug(66, 2) ("failed to parse an int header field near '%s'\n", start); + *value = -1; + return 0; + } + return 1; }