------------------------------------------------------------------------
r1869 | jan | 2007-06-15 16:08:32 +0200 (Fri, 15 Jun 2007) | 2 lines
Changed paths:
   M /branches/lighttpd-1.4.x/src/request.c
   M /branches/lighttpd-1.4.x/tests/core-request.t

fixed remote crash on duplicate header keys with line-wrapping (fixes #1230)

------------------------------------------------------------------------
Index: src/request.c
===================================================================
--- src/request.c	(revision 1868)
+++ src/request.c	(revision 1870)
@@ -284,8 +284,6 @@
 
 	int done = 0;
 
-	data_string *ds = NULL;
-
 	/*
 	 * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
 	 * Option : "^([-a-zA-Z]+): (.+)$"
@@ -715,12 +713,24 @@
 			switch(*cur) {
 			case '\r':
 				if (con->parse_request->ptr[i+1] == '\n') {
+					data_string *ds = NULL;
+
 					/* End of Headerline */
 					con->parse_request->ptr[i] = '\0';
 					con->parse_request->ptr[i+1] = '\0';
 
 					if (in_folding) {
-						if (!ds) {
+						buffer *key_b;
+						/**
+						 * we use a evil hack to handle the line-folding
+						 * 
+						 * As array_insert_unique() deletes 'ds' in the case of a duplicate
+						 * ds points somewhere and we get a evil crash. As a solution we keep the old
+						 * "key" and get the current value from the hash and append us
+						 *
+						 * */
+
+						if (!key || !key_len) {
 							/* 400 */
 
 							if (srv->srvconf.log_request_header_on_error) {
@@ -737,7 +747,15 @@
 							con->response.keep_alive = 0;
 							return 0;
 						}
-						buffer_append_string(ds->value, value);
+
+						key_b = buffer_init();
+						buffer_copy_string_len(key_b, key, key_len);
+
+						if (NULL != (ds = (data_string *)array_get_element(con->request.headers, key_b->ptr))) {
+							buffer_append_string(ds->value, value);
+						}
+
+						buffer_free(key_b);
 					} else {
 						int s_len;
 						key = con->parse_request->ptr + first;
@@ -969,7 +987,12 @@
 					first = i+1;
 					is_key = 1;
 					value = 0;
-					key_len = 0;
+#if 0
+					/**
+					 * for Bug 1230 keep the key_len a live
+					 */
+					key_len = 0; 
+#endif
 					in_folding = 0;
 				} else {
 					if (srv->srvconf.log_request_header_on_error) {
Index: tests/core-request.t
===================================================================
--- tests/core-request.t	(revision 1868)
+++ tests/core-request.t	(revision 1870)
@@ -8,7 +8,7 @@
 
 use strict;
 use IO::Socket;
-use Test::More tests => 33;
+use Test::More tests => 36;
 use LightyTest;
 
 my $tf = LightyTest->new();
@@ -273,6 +273,38 @@
 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
 ok($tf->handle_http($t) == 0, 'uppercase filenames');
 
+$t->{REQUEST}  = ( <<EOF
+GET / HTTP/1.0
+Location: foo
+Location: foobar
+  baz
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+ok($tf->handle_http($t) == 0, '#1232 - duplicate headers with line-wrapping');
 
+$t->{REQUEST}  = ( <<EOF
+GET / HTTP/1.0
+Location: 
+Location: foobar
+  baz
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+ok($tf->handle_http($t) == 0, '#1232 - duplicate headers with line-wrapping - test 2');
+
+$t->{REQUEST}  = ( <<EOF
+GET / HTTP/1.0
+A: 
+Location: foobar
+  baz
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+ok($tf->handle_http($t) == 0, '#1232 - duplicate headers with line-wrapping - test 3');
+
+
+
+
 ok($tf->stop_proc == 0, "Stopping lighttpd");
 
