On 03/02/12 21:44, Ángel González wrote:
> On 03/02/12 15:01, Gustavo Lopes wrote:
>> I've committed a different version that also forbids \0 (since, as
>> Stefan says, a NUL byte can result in the truncation of the rest of
>> the header) and that accepts a CRLF:
>>
>> http://svn.php.net/viewvc/php/php-src/trunk/main/SAPI.c?r1=323043&r2=323042&pathrev=323043
>>
> Looks good. But given that the goal is to make this robust, I would go
> further:
> a) Replace any CRLF + [ \r] with SP
> (rfc2616 allows us "A recipient MAY replace any linear white space
> with a single SP before forwarding the message downstream.", and
> this also protects UAs not following the spec)
>
> b) Bail out on any header_line[i] < ' ' (ie. fail on any special char)
I've gone ahead and written code for that feature. Comments welcome.


Index: main/SAPI.c
===================================================================
--- main/SAPI.c	(revision 323049)
+++ main/SAPI.c	(working copy)
@@ -710,27 +710,30 @@
 		efree(header_line);
 		return SUCCESS;
 	} else {
-		/* new line/NUL character safety check */
-		int i;
-		for (i = 0; i < header_line_len; i++) {
-			/* RFC 2616 allows new lines if followed by SP or HT */
-			int illegal_break =
-					(header_line[i+1] != ' ' && header_line[i+1] != '\t')
-					&& (
-						header_line[i] == '\n'
-						|| (header_line[i] == '\r' && header_line[i+1] != '\n'));
-			if (illegal_break) {
-				efree(header_line);
-				sapi_module.sapi_error(E_WARNING, "Header may not contain "
-						"more than a single header, new line detected");
-				return FAILURE;
+		/* Forbid new lines or control characters in the headers */
+		int i, j;
+		for (i = 0, j = 0; i < header_line_len; i++, j++) {
+			header[i] = header[j];
+			if (i < header_line_len - 2 &&
+				header_line[i] == '\r' && header_line[i+1] == '\n' &&
+				(header_line[i+2] == ' ' || header_line[i+2] == '\t')) {
+				
+				/* This is a line continuation. Collapse this little-known 
+				 * feature into a single SP, as allowed by RFC 2616
+				 */
+				header_line[i] = ' ';
+				j = i + 2;
 			}
-			if (header_line[i] == '\0') {
+			
+			if (header_line[i] < 32) {
 				efree(header_line);
-				sapi_module.sapi_error(E_WARNING, "Header may not contain NUL bytes");
+				sapi_module.sapi_error(E_WARNING, "header() accepts only a single header, "
+						"new lines and control characters are forbidden");
 				return FAILURE;
 			}
 		}
+		header_line[j] = '\0';
+		header_line_len = j;
 	}
 
 	sapi_header.header = header_line;

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to