[php] - update to 5.5.7, fix for CVE-2013-6420 - fix zend_register_functions breaks reflection, php bug 66

Remi Collet remi at fedoraproject.org
Wed Dec 11 06:22:23 UTC 2013


commit 3807d6335052731f453683b77af80350a2ccc762
Author: Remi Collet <remi at fedoraproject.org>
Date:   Wed Dec 11 07:22:21 2013 +0100

    - update to 5.5.7, fix for CVE-2013-6420
    - fix zend_register_functions breaks reflection, php bug 66218
    - fix Heap buffer over-read in DateInterval, php bug 66060
    - fix fix overflow handling bug in non-x86

 .gitignore         |    1 +
 php-bug66060.patch |   40 ++++++++
 php-bug66218.patch |  251 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 php-bugarm.patch   |   41 +++++++++
 php.spec           |   20 ++++-
 sources            |    2 +-
 6 files changed, 353 insertions(+), 2 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index fc1d4d9..f1f1973 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,4 @@ php-5.4.*.bz2
 /php-5.5.4-strip.tar.xz
 /php-5.5.5-strip.tar.xz
 /php-5.5.6-strip.tar.xz
+/php-5.5.7-strip.tar.xz
diff --git a/php-bug66060.patch b/php-bug66060.patch
new file mode 100644
index 0000000..553f708
--- /dev/null
+++ b/php-bug66060.patch
@@ -0,0 +1,40 @@
+From 12fe4e90be7bfa2a763197079f68f5568a14e071 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi at php.net>
+Date: Wed, 27 Nov 2013 11:13:16 +0100
+Subject: [PATCH] Fixed bug #66060 (Heap buffer over-read in DateInterval)
+
+---
+ NEWS                                | 3 +++
+ ext/date/lib/parse_iso_intervals.c  | 4 ++--
+ ext/date/lib/parse_iso_intervals.re | 2 +-
+ 3 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/ext/date/lib/parse_iso_intervals.c b/ext/date/lib/parse_iso_intervals.c
+index bd1ad05..480ea38 100644
+--- a/ext/date/lib/parse_iso_intervals.c
++++ b/ext/date/lib/parse_iso_intervals.c
+@@ -380,7 +380,7 @@ yy6:
+ 					break;
+ 			}
+ 			ptr++;
+-		} while (*ptr);
++		} while (!s->errors->error_count && *ptr);
+ 		s->have_period = 1;
+ 		TIMELIB_DEINIT;
+ 		return TIMELIB_PERIOD;
+diff --git a/ext/date/lib/parse_iso_intervals.re b/ext/date/lib/parse_iso_intervals.re
+index 56aa34d..c5e9f67 100644
+--- a/ext/date/lib/parse_iso_intervals.re
++++ b/ext/date/lib/parse_iso_intervals.re
+@@ -348,7 +348,7 @@ isoweek          = year4 "-"? "W" weekofyear;
+ 					break;
+ 			}
+ 			ptr++;
+-		} while (*ptr);
++		} while (!s->errors->error_count && *ptr);
+ 		s->have_period = 1;
+ 		TIMELIB_DEINIT;
+ 		return TIMELIB_PERIOD;
+-- 
+1.8.4.3
+
diff --git a/php-bug66218.patch b/php-bug66218.patch
new file mode 100644
index 0000000..848ab5a
--- /dev/null
+++ b/php-bug66218.patch
@@ -0,0 +1,251 @@
+From 3e963f8eb44863ef3d758eabe791190b0fd7bb9a Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi at php.net>
+Date: Tue, 10 Dec 2013 16:07:16 +0100
+Subject: [PATCH] Fixed Bug #66218 zend_register_functions breaks reflection
+
+Functions registered using zend_register_functions instead of zend_module_entry.functions are not seen on reflection.
+
+Ex: additional_functions from api_module_entry.
+Ex: in CLI, dl, cli_set_process_title and cli_get_process_title
+
+Note:
+- also affects functions overrided in extension
+  (should be be reported in extension, where overrided, not in original extension)
+- also allow extension to call zend_register_functions for various list
+  (instead of having a single bug list)
+---
+ NEWS                                               |  1 +
+ Zend/tests/bug66218.phpt                           | 21 +++++++
+ Zend/zend_builtin_functions.c                      | 51 ++++++++++-------
+ ext/reflection/php_reflection.c                    | 66 +++++++++-------------
+ .../tests/ReflectionExtension_bug66218.phpt        | 21 +++++++
+ 5 files changed, 101 insertions(+), 59 deletions(-)
+ create mode 100644 Zend/tests/bug66218.phpt
+ create mode 100644 ext/reflection/tests/ReflectionExtension_bug66218.phpt
+
+diff --git a/Zend/tests/bug66218.phpt b/Zend/tests/bug66218.phpt
+new file mode 100644
+index 0000000..af7a5ab
+--- /dev/null
++++ b/Zend/tests/bug66218.phpt
+@@ -0,0 +1,21 @@
++--TEST--
++Bug #66218 zend_register_functions breaks reflection
++--SKIPIF--
++<?php
++if (PHP_SAPI != "cli") die("skip CLI only test");
++if (!function_exists("dl")) die("skip need dl");
++?>
++--FILE--
++<?php
++$tab = get_extension_funcs("standard");
++$fcts = array("dl");
++foreach ($fcts as $fct) {
++	if (in_array($fct, $tab)) {
++		echo "$fct Ok\n";
++	}
++}
++?>
++Done
++--EXPECTF--
++dl Ok
++Done
+diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
+index 04f4ebe..12a8fb2 100644
+--- a/Zend/zend_builtin_functions.c
++++ b/Zend/zend_builtin_functions.c
+@@ -2442,36 +2442,49 @@ ZEND_FUNCTION(extension_loaded)
+    Returns an array with the names of functions belonging to the named extension */
+ ZEND_FUNCTION(get_extension_funcs)
+ {
+-	char *extension_name;
+-	int extension_name_len;
++	char *extension_name, *lcname;
++	int extension_name_len, array;
+ 	zend_module_entry *module;
+-	const zend_function_entry *func;
+-
++	HashPosition iterator;
++	zend_function *zif;
+ 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &extension_name, &extension_name_len) == FAILURE) {
+ 		return;
+ 	}
+-
+ 	if (strncasecmp(extension_name, "zend", sizeof("zend"))) {
+-		char *lcname = zend_str_tolower_dup(extension_name, extension_name_len);
+-		if (zend_hash_find(&module_registry, lcname,
+-			extension_name_len+1, (void**)&module) == FAILURE) {
+-			efree(lcname);
+-			RETURN_FALSE;
+-		}
++		lcname = zend_str_tolower_dup(extension_name, extension_name_len);
++	} else {
++		lcname = estrdup("core");
++	}
++	if (zend_hash_find(&module_registry, lcname,
++		extension_name_len+1, (void**)&module) == FAILURE) {
+ 		efree(lcname);
++		RETURN_FALSE;
++	}
+ 
+-		if (!(func = module->functions)) {
+-			RETURN_FALSE;
+-		}
++	zend_hash_internal_pointer_reset_ex(CG(function_table), &iterator);
++	if (module->functions) {
++		/* avoid BC break, if functions list is empty, will return an empty array */
++		array_init(return_value);
++		array = 1;
+ 	} else {
+-		func = builtin_functions;
++		array = 0;
++	}
++	while (zend_hash_get_current_data_ex(CG(function_table), (void **) &zif, &iterator) == SUCCESS) {
++		if (zif->common.type==ZEND_INTERNAL_FUNCTION
++			&& zif->internal_function.module == module) {
++			if (!array) {
++				array_init(return_value);
++				array = 1;
++			}
++			add_next_index_string(return_value, zif->common.function_name, 1);
++		}
++		zend_hash_move_forward_ex(CG(function_table), &iterator);
+ 	}
+ 
+-	array_init(return_value);
++	efree(lcname);
+ 
+-	while (func->fname) {
+-		add_next_index_string(return_value, func->fname, 1);
+-		func++;
++	if (!array) {
++		RETURN_FALSE;
+ 	}
+ }
+ /* }}} */
+diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
+index c4a7c55..803b12b 100644
+--- a/ext/reflection/php_reflection.c
++++ b/ext/reflection/php_reflection.c
+@@ -1105,29 +1105,26 @@
+ 		string_free(&str_constants);
+ 	}
+ 
+-	if (module->functions && module->functions->fname) {
++	{
++		HashPosition iterator;
+ 		zend_function *fptr;
+-		const zend_function_entry *func = module->functions;
+-
+-		string_printf(str, "\n  - Functions {\n");
++		int first = 1;
+ 
+-		/* Is there a better way of doing this? */
+-		while (func->fname) {
+-			int fname_len = strlen(func->fname);
+-			char *lc_name = zend_str_tolower_dup(func->fname, fname_len);
+-		
+-			if (zend_hash_find(EG(function_table), lc_name, fname_len + 1, (void**) &fptr) == FAILURE) {
+-				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname);
+-				func++;
+-				efree(lc_name);
+-				continue;
++		zend_hash_internal_pointer_reset_ex(CG(function_table), &iterator);
++		while (zend_hash_get_current_data_ex(CG(function_table), (void **) &fptr, &iterator) == SUCCESS) {
++			if (fptr->common.type==ZEND_INTERNAL_FUNCTION
++				&& fptr->internal_function.module == module) {
++				if (first) {
++					string_printf(str, "\n  - Functions {\n");
++					first = 0;
++				}
++				_function_string(str, fptr, NULL, "    " TSRMLS_CC);
+ 			}
+-
+-			_function_string(str, fptr, NULL, "    " TSRMLS_CC);
+-			efree(lc_name);
+-			func++;
++			zend_hash_move_forward_ex(CG(function_table), &iterator);
++		}
++		if (!first) {
++			string_printf(str, "%s  }\n", indent);
+ 		}
+-		string_printf(str, "%s  }\n", indent);
+ 	}
+ 
+ 	{
+@@ -5264,6 +5261,9 @@
+ {
+ 	reflection_object *intern;
+ 	zend_module_entry *module;
++	HashPosition iterator;
++	zval *function;
++	zend_function *fptr;
+ 
+ 	if (zend_parse_parameters_none() == FAILURE) {
+ 		return;
+@@ -5271,29 +5271,15 @@
+ 	GET_REFLECTION_OBJECT_PTR(module);
+ 
+ 	array_init(return_value);
+-	if (module->functions) {
+-		zval *function;
+-		zend_function *fptr;
+-		const zend_function_entry *func = module->functions;
+-
+-		/* Is there a better way of doing this? */
+-		while (func->fname) {
+-			int fname_len = strlen(func->fname);
+-			char *lc_name = zend_str_tolower_dup(func->fname, fname_len);
+-			
+-			if (zend_hash_find(EG(function_table), lc_name, fname_len + 1, (void**) &fptr) == FAILURE) {
+-				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname);
+-				func++;
+-				efree(lc_name);
+-				continue;
+-			}
+-
++	zend_hash_internal_pointer_reset_ex(CG(function_table), &iterator);
++	while (zend_hash_get_current_data_ex(CG(function_table), (void **) &fptr, &iterator) == SUCCESS) {
++		if (fptr->common.type==ZEND_INTERNAL_FUNCTION
++			&& fptr->internal_function.module == module) {
+ 			ALLOC_ZVAL(function);
+ 			reflection_function_factory(fptr, NULL, function TSRMLS_CC);
+-			add_assoc_zval_ex(return_value, func->fname, fname_len+1, function);
+-			func++;
+-			efree(lc_name);
++			add_assoc_zval(return_value, fptr->common.function_name, function);
+ 		}
++		zend_hash_move_forward_ex(CG(function_table), &iterator);
+ 	}
+ }
+ /* }}} */
+ diff --git a/ext/reflection/tests/ReflectionExtension_bug66218.phpt b/ext/reflection/tests/ReflectionExtension_bug66218.phpt
+new file mode 100644
+index 0000000..e263624
+--- /dev/null
++++ b/ext/reflection/tests/ReflectionExtension_bug66218.phpt
+@@ -0,0 +1,21 @@
++--TEST--
++ReflectionExtension::getFunctions() ##6218 zend_register_functions breaks reflection
++--SKIPIF--
++<?php
++if (!extension_loaded('reflection')) print 'skip missing reflection extension';
++if (PHP_SAPI != "cli") die("skip CLI only test");
++if (!function_exists("dl")) die("skip need dl");
++?>
++--FILE--
++<?php
++$r = new ReflectionExtension('standard');
++$t = $r->getFunctions();
++var_dump($t['dl']);
++?>
++Done
++--EXPECTF--
++object(ReflectionFunction)#%d (1) {
++  ["name"]=>
++  string(2) "dl"
++}
++Done
+-- 
+1.8.4.3
+
diff --git a/php-bugarm.patch b/php-bugarm.patch
new file mode 100644
index 0000000..6bd63b3
--- /dev/null
+++ b/php-bugarm.patch
@@ -0,0 +1,41 @@
+From 60d2e70c062e436a6c6cd3c8a17469a083a38b46 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date: Tue, 10 Dec 2013 12:07:46 +0100
+Subject: [PATCH] Zend: fix overflow handling bug in non-x86
+ fast_add_function()
+
+The 'result' argument of fast_add_function() may alias with either
+of its operands (or both). Take care not to write to 'result' before
+reading op1 and op2.
+---
+ Zend/zend_operators.h | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
+index 0152e03..5c6fc86 100644
+--- a/Zend/zend_operators.h
++++ b/Zend/zend_operators.h
+@@ -640,13 +640,18 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o
+ 			  "n"(ZVAL_OFFSETOF_TYPE)
+ 			: "rax","cc");
+ #else
+-			Z_LVAL_P(result) = Z_LVAL_P(op1) + Z_LVAL_P(op2);
++			/*
++			 * 'result' may alias with op1 or op2, so we need to
++			 * ensure that 'result' is not updated until after we
++			 * have read the values of op1 and op2.
++			 */
+ 
+ 			if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
+-				&& (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(result) & LONG_SIGN_MASK))) {
++				&& (Z_LVAL_P(op1) & LONG_SIGN_MASK) != ((Z_LVAL_P(op1) + Z_LVAL_P(op2)) & LONG_SIGN_MASK))) {
+ 				Z_DVAL_P(result) = (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2);
+ 				Z_TYPE_P(result) = IS_DOUBLE;
+ 			} else {
++				Z_LVAL_P(result) = Z_LVAL_P(op1) + Z_LVAL_P(op2);
+ 				Z_TYPE_P(result) = IS_LONG;
+ 			}
+ #endif
+-- 
+1.8.4.3
+
diff --git a/php.spec b/php.spec
index 216c332..4832ac3 100644
--- a/php.spec
+++ b/php.spec
@@ -68,7 +68,7 @@
 
 Summary: PHP scripting language for creating dynamic web sites
 Name: php
-Version: 5.5.6
+Version: 5.5.7
 Release: 1%{?dist}
 # All files licensed under PHP version 3.01, except
 # Zend is licensed under Zend
@@ -120,6 +120,14 @@ Patch46: php-5.4.9-fixheader.patch
 # drop "Configure command" from phpinfo output
 Patch47: php-5.4.9-phpinfo.patch
 
+# Upstream fixes
+# 66060 Heap buffer over-read in DateInterval
+Patch100: php-bug66060.patch
+# 66218 zend_register_functions breaks reflection
+Patch101: php-bug66218.patch
+# Zend: fix overflow handling bug in non-x86
+Patch102: php-bugarm.patch
+
 # Security fixes
 
 # Fixes for tests
@@ -728,6 +736,10 @@ support for using the enchant library to PHP.
 %patch46 -p1 -b .fixheader
 %patch47 -p1 -b .phpinfo
 
+%patch100 -p1 -b .bug66060
+%patch101 -p1 -b .bug66218
+%patch102 -p1 -b .bugarm
+
 
 # Prevent %%doc confusion over LICENSE files
 cp Zend/LICENSE Zend/ZEND_LICENSE
@@ -1538,6 +1550,12 @@ exit 0
 
 
 %changelog
+* Wed Dec 11 2013 Remi Collet <rcollet at redhat.com> 5.5.7-1
+- update to 5.5.7, fix for CVE-2013-6420
+- fix zend_register_functions breaks reflection, php bug 66218
+- fix Heap buffer over-read in DateInterval, php bug 66060
+- fix fix overflow handling bug in non-x86
+
 * Wed Nov 13 2013 Remi Collet <remi at fedoraproject.org> 5.5.6-1
 - update to 5.5.6
 
diff --git a/sources b/sources
index 5cd1e2e..a9d5afc 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-6bcd5a4d9fcb7ac2368abfd9ae63db79  php-5.5.6-strip.tar.xz
+67f9fa47efea07c6f0216d6229f05c49  php-5.5.7-strip.tar.xz


More information about the scm-commits mailing list