You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by jo...@apache.org on 2004/11/04 15:50:31 UTC
cvs commit: httpd-2.0/server protocol.c
jorton 2004/11/04 06:50:31
Modified: server protocol.c
Log:
Fix for memory consumption DoS, CVE CAN-2004-0942:
* server/protocol.c (ap_rgetline_core): Don't trim trailing whitespace
from the buffer here.
(ap_get_mime_headers_core): Trim trailing whitespace here, after
reading a complete field including continuation lines. Also simplify
code to remove whitespace between field-name and colon.
Reviewed by: André Malo, Bill Stoddard
Revision Changes Path
1.159 +22 -47 httpd-2.0/server/protocol.c
Index: protocol.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/protocol.c,v
retrieving revision 1.158
retrieving revision 1.159
diff -d -w -u -r1.158 -r1.159
--- protocol.c 25 Oct 2004 15:59:43 -0000 1.158
+++ protocol.c 4 Nov 2004 14:50:31 -0000 1.159
@@ -306,35 +306,13 @@
}
}
- /* We now go backwards over any CR (if present) or white spaces.
- *
- * Trim any extra trailing spaces or tabs except for the first
- * space or tab at the beginning of a blank string. This makes
- * it much easier to check field values for exact matches, and
- * saves memory as well. Terminate string at end of line.
- */
- pos = last_char;
- if (pos > *s && *(pos - 1) == APR_ASCII_CR) {
- --pos;
- }
-
- /* Trim any extra trailing spaces or tabs except for the first
- * space or tab at the beginning of a blank string. This makes
- * it much easier to check field values for exact matches, and
- * saves memory as well.
- */
- while (pos > ((*s) + 1)
- && (*(pos - 1) == APR_ASCII_BLANK || *(pos - 1) == APR_ASCII_TAB)) {
- --pos;
+ /* Now NUL-terminate the string at the end of the line;
+ * if the last-but-one character is a CR, terminate there */
+ if (last_char > *s && last_char[-1] == APR_ASCII_CR) {
+ last_char--;
}
-
- /* Since we want to remove the LF from the line, we'll go ahead
- * and set this last character to be the term NULL and reset
- * bytes_handled accordingly.
- */
- *pos = '\0';
- last_char = pos;
- bytes_handled = pos - *s;
+ *last_char = '\0';
+ bytes_handled = last_char - *s;
/* If we're folding, we have more work to do.
*
@@ -760,7 +738,7 @@
last_len += len;
folded = 1;
}
- else {
+ else /* not a continuation line */ {
if (r->server->limit_req_fields
&& (++fields_read > r->server->limit_req_fields)) {
@@ -784,28 +762,25 @@
return;
}
- *value = '\0';
- tmp_field = value; /* used to trim the whitespace between key
- * token and separator
- */
- ++value;
+ tmp_field = value - 1; /* last character of field-name */
+
+ *value++ = '\0'; /* NUL-terminate at colon */
+
while (*value == ' ' || *value == '\t') {
++value; /* Skip to start of value */
}
- /* This check is to avoid any invalid memory reference while
- * traversing backwards in the key. To avoid a case where
- * the header starts with ':' (or with just some white
- * space and the ':') followed by the value
- */
- if (tmp_field > last_field) {
- --tmp_field;
- while ((tmp_field > last_field) &&
- (*tmp_field == ' ' || *tmp_field == '\t')) {
- --tmp_field; /* Removing LWS between key and ':' */
+ /* Strip LWS after field-name: */
+ while (tmp_field > last_field
+ && (*tmp_field == ' ' || *tmp_field == '\t')) {
+ *tmp_field-- = '\0';
}
- ++tmp_field;
- *tmp_field = '\0';
+
+ /* Strip LWS after field-value: */
+ tmp_field = last_field + last_len - 1;
+ while (tmp_field > value
+ && (*tmp_field == ' ' || *tmp_field == '\t')) {
+ *tmp_field-- = '\0';
}
apr_table_addn(r->headers_in, last_field, value);