php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login

Patch 0001-Fixed-bug-61605-header_remove-does-not-remove-all-headers for HTTP related Bug #61605

Patch version 2012-04-03 17:44 UTC

Return to Bug #61605 | Download this patch
Patch Revisions:

Developer: reeze.xia@gmail.com

From 447d05ff8dd4d8b2bd3249e46c8d78c1f6a617d5 Mon Sep 17 00:00:00 2001
From: reeze <reeze.xia@gmail.com>
Date: Wed, 4 Apr 2012 01:35:35 +0800
Subject: [PATCH] Fixed bug #61605 header_remove() does not remove all headers

---
 NEWS                         |    1 +
 main/SAPI.c                  |   38 ++++++++++++++++++++++----
 sapi/cgi/tests/bug61605.phpt |   61 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 95 insertions(+), 5 deletions(-)
 create mode 100644 sapi/cgi/tests/bug61605.phpt

diff --git a/NEWS b/NEWS
index c7cd2c7..361e4ea 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,7 @@ PHP                                                                        NEWS
 (merge after 5.3.11 release)
 
 - Core:
+  . Fixed bug #61605 header_remove() does not remove all headers. (Reeze)
   . Fixed bug #61273 (call_user_func_array with more than 16333 arguments
     leaks / crashes). (Laruence)
   . Fixed bug #61165 (Segfault - strip_tags()). (Laruence)
diff --git a/main/SAPI.c b/main/SAPI.c
index 693cad3..ca71f33 100644
--- a/main/SAPI.c
+++ b/main/SAPI.c
@@ -501,10 +501,38 @@ static void sapi_update_response_code(int ncode TSRMLS_DC)
 	SG(sapi_headers).http_response_code = ncode;
 }
 
-static int sapi_find_matching_header(void *element1, void *element2)
+static void sapi_remove_all_matching_headers_by_name(zend_llist *headers, char *name)
 {
-	int len = strlen((char*)element2);
-	return strncasecmp(((sapi_header_struct*)element1)->header, (char*)element2, len) == 0 && ((sapi_header_struct*)element1)->header[len] == ':';
+	zend_llist_element *element, *next;
+	int len = strlen(name);
+	char *header;
+
+	element = headers->head;
+	while (element) {
+		next = element->next;
+		header = (char *)((sapi_header_struct *)element->data)->header;
+
+		if (strncasecmp(header, name, len) == 0 && header[len] == ':') {
+			if (element->prev) {
+				element->prev->next = (element)->next;
+			} else {
+				headers->head = element->next;
+			}
+			if (element->next) {
+				element->next->prev = (element)->prev;
+			} else {
+				headers->tail = element->prev;
+			}
+			if (headers->dtor) {
+				headers->dtor(element->data);
+			}
+
+			pefree(element, headers->persistent);
+			--headers->count;
+		}
+
+		element = next;
+	}
 }
 
 SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bool duplicate, zend_bool replace TSRMLS_DC)
@@ -611,7 +639,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
 		if (sapi_module.header_handler) {
 			sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers) TSRMLS_CC);
 		}
-		zend_llist_del_element(&SG(sapi_headers).headers, sapi_header.header, (int(*)(void*, void*))sapi_find_matching_header);
+		sapi_remove_all_matching_headers_by_name(&SG(sapi_headers).headers, sapi_header.header);
 		sapi_free_header(&sapi_header);
 		return SUCCESS;
 	}
@@ -769,7 +797,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
 				char sav;
 				sav = *colon_offset;
 				*colon_offset = 0;
-				zend_llist_del_element(&SG(sapi_headers).headers, sapi_header.header, (int(*)(void*, void*))sapi_find_matching_header);
+				sapi_remove_all_matching_headers_by_name(&SG(sapi_headers).headers, sapi_header.header);
 				*colon_offset = sav;
 			}
 		}
diff --git a/sapi/cgi/tests/bug61605.phpt b/sapi/cgi/tests/bug61605.phpt
new file mode 100644
index 0000000..b152a20
--- /dev/null
+++ b/sapi/cgi/tests/bug61605.phpt
@@ -0,0 +1,61 @@
+--TEST--
+header_remove() should handle multiple same key headers
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$php = get_cgi_path();
+reset_env_vars();
+
+$f = tempnam(sys_get_temp_dir(), 'cgitest');
+
+function test($script) {
+	file_put_contents($GLOBALS['f'], $script);
+	$cmd = escapeshellcmd($GLOBALS['php']);
+	$cmd .= ' -n -dreport_zend_debug=0 -dhtml_errors=0 ' . escapeshellarg($GLOBALS['f']);
+	echo "----------\n";
+	echo rtrim($script) . "\n";
+	echo "----------\n";
+	passthru($cmd);
+}
+
+test('<?php
+header("X-Foo: Bar");
+header("X-Foo: Bar2", false);
+
+header_remove("X-Foo");
+?>');
+
+test('<?php
+header("X-Foo: Bar");
+header("X-Foo: Baz", false);
+header("X-Foo: Baz2");
+?>');
+
+@unlink($f);
+?>
+--EXPECTF--
+----------
+<?php
+header("X-Foo: Bar");
+header("X-Foo: Bar2", false);
+
+header_remove("X-Foo");
+?>
+----------
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+----------
+<?php
+header("X-Foo: Bar");
+header("X-Foo: Baz", false);
+header("X-Foo: Baz2");
+?>
+----------
+X-Powered-By: PHP/%s
+X-Foo: Baz2
+Content-type: text/html
-- 
1.7.9.3

 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Thu Apr 17 03:01:55 2014 UTC