diff options
author | Joe Watkins <krakjoe@php.net> | 2016-03-31 12:40:15 +0100 |
---|---|---|
committer | Joe Watkins <krakjoe@php.net> | 2016-03-31 12:40:15 +0100 |
commit | 3b13206aa9d494af2cf4bde4047250405d5bbfd2 (patch) | |
tree | cbc4eee151d771cfb789fd8095023bd490c9fd41 | |
parent | 233115ea236fd1aa258e8b733d3855d1261fba8b (diff) | |
parent | e6bb7eb3aa4b0be66130b8299a21e94eeeec2368 (diff) | |
download | php-git-3b13206aa9d494af2cf4bde4047250405d5bbfd2.tar.gz |
Merge branch 'PHP-7.0' of https://github.com/php/php-src into PHP-7.0
-rw-r--r-- | NEWS | 10 | ||||
-rw-r--r-- | Zend/tests/closure_invoke_case_insensitive.phpt | 16 | ||||
-rw-r--r-- | Zend/zend_closures.c | 8 | ||||
-rw-r--r-- | ext/fileinfo/libmagic/funcs.c | 2 | ||||
-rw-r--r-- | ext/fileinfo/tests/bug68996.phpt | 7 | ||||
-rw-r--r-- | ext/shmop/shmop.c | 1 | ||||
-rw-r--r-- | ext/shmop/tests/003.phpt | 33 | ||||
-rw-r--r-- | ext/spl/spl_array.c | 45 | ||||
-rw-r--r-- | ext/standard/array.c | 33 | ||||
-rw-r--r-- | ext/standard/tests/array/bug71334.phpt | 38 | ||||
-rw-r--r-- | ext/standard/tests/array/unexpected_array_mod_bug.phpt | 21 | ||||
-rw-r--r-- | ext/standard/tests/array/unexpected_array_mod_bug_variation1.phpt | 33 |
12 files changed, 159 insertions, 88 deletions
@@ -15,6 +15,7 @@ PHP NEWS . Fixed bug #62059 (ArrayObject and isset are not friends). (Nikita) . Fixed bug #71871 (Interfaces allow final and abstract functions). (Nikita) . Fixed bug #71922 (Crash on assert(new class{})). (Nikita) + . Fixed bug #71334 (Cannot access array keys while uksort()). (Nikita) - Curl: . Fixed bug #71831 (CURLOPT_NOPROXY applied as long instead of string). @@ -32,8 +33,8 @@ PHP NEWS (Daniel kalaspuffar, Julien) - Postgres: - . Fixed bug #71820 (pg_fetch_object binds parameters before - call constructor). (Anatol) + . Fixed bug #71820 (pg_fetch_object binds parameters before call + constructor). (Anatol) - SPL: . Fixed bug #71838 (Deserializing serialized SPLObjectStorage-Object can't @@ -116,8 +117,7 @@ PHP NEWS (steven dot lambeth at gmx dot de, Anatol) - Phar: - . Fixed bug #71625 (Crash in php7.dll with bad phar filename). - (Anatol) + . Fixed bug #71625 (Crash in php7.dll with bad phar filename). (Anatol) . Fixed bug #71317 (PharData fails to open specific file). (Jos Elstgeest) . Fixed bug #71860 (Invalid memory write in phar on filename with \0 in name). (Stas) @@ -126,7 +126,7 @@ PHP NEWS . Fixed crash when advancing (except step) inside an internal function. (Bob) - Session: - . Fixed Bug #71683 (Null pointer dereference in zend_hash_str_find_bucket). + . Fixed bug #71683 (Null pointer dereference in zend_hash_str_find_bucket). (Yasuo) - SNMP: diff --git a/Zend/tests/closure_invoke_case_insensitive.phpt b/Zend/tests/closure_invoke_case_insensitive.phpt new file mode 100644 index 0000000000..d41d58a747 --- /dev/null +++ b/Zend/tests/closure_invoke_case_insensitive.phpt @@ -0,0 +1,16 @@ +--TEST-- +Closure::__invoke() is case insensitive +--FILE-- +<?php + +$inc = function(&$n) { + $n++; +}; + +$n = 1; +$inc->__INVOKE($n); +var_dump($n); + +?> +--EXPECT-- +int(2) diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 9b4fb1180e..def114c4ec 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -297,14 +297,10 @@ ZEND_API zval* zend_get_closure_this_ptr(zval *obj) /* {{{ */ static zend_function *zend_closure_get_method(zend_object **object, zend_string *method, const zval *key) /* {{{ */ { - zend_string *lc_name; - - lc_name = zend_string_tolower(method); - if (zend_string_equals_literal(method, ZEND_INVOKE_FUNC_NAME)) { - zend_string_release(lc_name); + if (zend_string_equals_literal_ci(method, ZEND_INVOKE_FUNC_NAME)) { return zend_get_closure_invoke_method(*object); } - zend_string_release(lc_name); + return std_object_handlers.get_method(object, method, key); } /* }}} */ diff --git a/ext/fileinfo/libmagic/funcs.c b/ext/fileinfo/libmagic/funcs.c index 6ade713efa..9ea5386ebf 100644 --- a/ext/fileinfo/libmagic/funcs.c +++ b/ext/fileinfo/libmagic/funcs.c @@ -403,7 +403,7 @@ file_check_mem(struct magic_set *ms, unsigned int level) size_t len; if (level >= ms->c.len) { - len = (ms->c.len += 20 + level) * sizeof(*ms->c.li); + len = (ms->c.len = 20 + level) * sizeof(*ms->c.li); ms->c.li = CAST(struct level_info *, (ms->c.li == NULL) ? emalloc(len) : erealloc(ms->c.li, len)); diff --git a/ext/fileinfo/tests/bug68996.phpt b/ext/fileinfo/tests/bug68996.phpt index da208d35bc..214e52fa6f 100644 --- a/ext/fileinfo/tests/bug68996.phpt +++ b/ext/fileinfo/tests/bug68996.phpt @@ -1,11 +1,14 @@ --TEST-- Bug #68996 (Invalid free of CG(interned_empty_string)) --SKIPIF-- +<?php +if (getenv("USE_ZEND_ALLOC") !== "0") { + print "skip Need Zend MM disabled"; +} +?> <?php require_once(dirname(__FILE__) . '/skipif.inc'); ?> --INI-- html_errors=1 ---ENV-- -USE_ZEND_ALLOC=0 --FILE-- <?php finfo_open(FILEINFO_MIME_TYPE, "\xfc\x63"); diff --git a/ext/shmop/shmop.c b/ext/shmop/shmop.c index 4fe65ae37d..d647790aa0 100644 --- a/ext/shmop/shmop.c +++ b/ext/shmop/shmop.c @@ -203,6 +203,7 @@ PHP_FUNCTION(shmop_open) } if (shmctl(shmop->shmid, IPC_STAT, &shm)) { + /* please do not add coverage here: the segment would be leaked and impossible to delete via php */ php_error_docref(NULL, E_WARNING, "unable to get shared memory segment information '%s'", strerror(errno)); goto err; } diff --git a/ext/shmop/tests/003.phpt b/ext/shmop/tests/003.phpt deleted file mode 100644 index 1c154f08ca..0000000000 --- a/ext/shmop/tests/003.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -shmop extension error messages (non-root) ---SKIPIF-- -<?php - if( substr(PHP_OS, 0, 3) == "WIN") { - die('skip not for Windows'); - } - if (!extension_loaded("shmop")) { - die("skip shmop extension not available"); - } - if (!extension_loaded("posix")) { - die("skip posix extension not available"); - } - if (!posix_geteuid()) { - die("skip cannot run test as root"); - } -?> ---FILE-- -<?php - $hex_shm_id = function(){ - return mt_rand(1338, 9999); - }; - -echo '## shmop_open function tests ##', PHP_EOL; - // warning outputs: unable to get shared memory segment information - var_dump(shmop_open($hex_shm_id(), 'n', 0, 1024)); - -?> ---EXPECTF-- -## shmop_open function tests ## - -Warning: shmop_open(): unable to get shared memory segment information 'Permission denied' in %s on line %d -bool(false) diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index d5cb32606e..60cbac5726 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -82,18 +82,18 @@ static inline spl_array_object *spl_array_from_obj(zend_object *obj) /* {{{ */ { #define Z_SPLARRAY_P(zv) spl_array_from_obj(Z_OBJ_P((zv))) -static inline HashTable *spl_array_get_hash_table(spl_array_object* intern) { /* {{{ */ +static inline HashTable **spl_array_get_hash_table_ptr(spl_array_object* intern) { /* {{{ */ //??? TODO: Delay duplication for arrays; only duplicate for write operations if (intern->ar_flags & SPL_ARRAY_IS_SELF) { if (!intern->std.properties) { rebuild_object_properties(&intern->std); } - return intern->std.properties; + return &intern->std.properties; } else if (intern->ar_flags & SPL_ARRAY_USE_OTHER) { spl_array_object *other = Z_SPLARRAY_P(&intern->array); - return spl_array_get_hash_table(other); + return spl_array_get_hash_table_ptr(other); } else if (Z_TYPE(intern->array) == IS_ARRAY) { - return Z_ARRVAL(intern->array); + return &Z_ARRVAL(intern->array); } else { zend_object *obj = Z_OBJ(intern->array); if (!obj->properties) { @@ -104,9 +104,22 @@ static inline HashTable *spl_array_get_hash_table(spl_array_object* intern) { /* } obj->properties = zend_array_dup(obj->properties); } - return obj->properties; + return &obj->properties; } -} /* }}} */ +} +/* }}} */ + +static inline HashTable *spl_array_get_hash_table(spl_array_object* intern) { /* {{{ */ + return *spl_array_get_hash_table_ptr(intern); +} +/* }}} */ + +static inline void spl_array_replace_hash_table(spl_array_object* intern, HashTable *ht) { /* {{{ */ + HashTable **ht_ptr = spl_array_get_hash_table_ptr(intern); + zend_array_destroy(*ht_ptr); + *ht_ptr = ht; +} +/* }}} */ static inline zend_bool spl_array_is_object(spl_array_object *intern) /* {{{ */ { @@ -1432,16 +1445,12 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam spl_array_object *intern = Z_SPLARRAY_P(getThis()); HashTable *aht = spl_array_get_hash_table(intern); zval function_name, params[2], *arg = NULL; - uint32_t old_refcount; ZVAL_STRINGL(&function_name, fname, fname_len); - /* A tricky way to pass "aht" by reference, reset refcount */ - //??? It may be not safe, if user comparison handler accesses "aht" - old_refcount = GC_REFCOUNT(aht); - GC_REFCOUNT(aht) = 1; ZVAL_NEW_EMPTY_REF(¶ms[0]); ZVAL_ARR(Z_REFVAL(params[0]), aht); + GC_REFCOUNT(aht)++; if (!use_arg) { intern->nApplyCount++; @@ -1470,10 +1479,16 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam } exit: - /* A tricky way to pass "aht" by reference, copy back and cleanup */ - GC_REFCOUNT(aht) = old_refcount; - efree(Z_REF(params[0])); - zend_string_free(Z_STR(function_name)); + { + HashTable *new_ht = Z_ARRVAL_P(Z_REFVAL(params[0])); + if (aht != new_ht) { + spl_array_replace_hash_table(intern, new_ht); + } else { + GC_REFCOUNT(aht)--; + } + efree(Z_REF(params[0])); + zend_string_free(Z_STR(function_name)); + } } /* }}} */ #define SPL_ARRAY_METHOD(cname, fname, use_arg) \ diff --git a/ext/standard/array.c b/ext/standard/array.c index 4ff373a0b0..289870ac1f 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1035,37 +1035,30 @@ static int php_array_user_compare(const void *a, const void *b) /* {{{ */ static void php_usort(INTERNAL_FUNCTION_PARAMETERS, compare_func_t compare_func, zend_bool renumber) /* {{{ */ { zval *array; - zend_refcounted *arr; + zend_array *arr; zend_bool retval; PHP_ARRAY_CMP_FUNC_VARS; PHP_ARRAY_CMP_FUNC_BACKUP(); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/f", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "af", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) { PHP_ARRAY_CMP_FUNC_RESTORE(); return; } - /* Increase reference counter, so the attempts to modify the array in user - * comparison function will create a copy of array and won't affect the - * original array. The fact of modification is detected by comparing the - * zend_array pointer. The result of sorting in such case is undefined and - * the function returns FALSE. - */ - Z_ADDREF_P(array); - arr = Z_COUNTED_P(array); + arr = Z_ARR_P(array); + if (zend_hash_num_elements(arr) == 0) { + PHP_ARRAY_CMP_FUNC_RESTORE(); + RETURN_TRUE; + } - retval = zend_hash_sort(Z_ARRVAL_P(array), compare_func, renumber) != FAILURE; + /* Copy array, so the in-place modifications will not be visible to the callback function */ + arr = zend_array_dup(arr); - if (arr != Z_COUNTED_P(array)) { - php_error_docref(NULL, E_WARNING, "Array was modified by the user comparison function"); - if (--GC_REFCOUNT(arr) <= 0) { - _zval_dtor_func(arr ZEND_FILE_LINE_CC); - } - retval = 0; - } else { - Z_DELREF_P(array); - } + retval = zend_hash_sort(arr, compare_func, renumber) != FAILURE; + + zval_ptr_dtor(array); + ZVAL_ARR(array, arr); PHP_ARRAY_CMP_FUNC_RESTORE(); RETURN_BOOL(retval); diff --git a/ext/standard/tests/array/bug71334.phpt b/ext/standard/tests/array/bug71334.phpt new file mode 100644 index 0000000000..7a37d0953a --- /dev/null +++ b/ext/standard/tests/array/bug71334.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug #71334: Cannot access array keys while uksort() +--FILE-- +<?php + +class myClass +{ + private $a = [ + 'foo-test' => [1], + '-' => [2], + 'bar-test' => [3] + ]; + + private function _mySort($x, $y) + { + if (!isset($this->a[$x])) { + throw new Exception('Missing X: "' . $x . '"'); + } + + if (!isset($this->a[$y])) { + throw new Exception('Missing Y: "' . $y . '"'); + } + + return $x < $y; + } + + public function __construct() + { + uksort($this->a, [$this, '_mySort']); + } +} + +new myClass(); +echo "Done"; + +?> +--EXPECT-- +Done diff --git a/ext/standard/tests/array/unexpected_array_mod_bug.phpt b/ext/standard/tests/array/unexpected_array_mod_bug.phpt index 58f2249205..2762ebd830 100644 --- a/ext/standard/tests/array/unexpected_array_mod_bug.phpt +++ b/ext/standard/tests/array/unexpected_array_mod_bug.phpt @@ -4,7 +4,7 @@ Crash when function parameter modified via reference <?php function usercompare($a,$b) { unset($GLOBALS['my_var'][2]); - return 0; + return $a <=> $b; } $my_var = array(1 => "entry_1", 2 => "entry_2", @@ -12,10 +12,19 @@ $my_var = array(1 => "entry_1", 4 => "entry_4", 5 => "entry_5"); usort($my_var, "usercompare"); +var_dump($my_var); -echo "Done.\n"; ?> ---EXPECTF-- - -Warning: usort(): Array was modified by the user comparison function in %s on line %d -Done. +--EXPECT-- +array(5) { + [0]=> + string(7) "entry_1" + [1]=> + string(7) "entry_2" + [2]=> + string(7) "entry_3" + [3]=> + string(7) "entry_4" + [4]=> + string(7) "entry_5" +} diff --git a/ext/standard/tests/array/unexpected_array_mod_bug_variation1.phpt b/ext/standard/tests/array/unexpected_array_mod_bug_variation1.phpt new file mode 100644 index 0000000000..b5a1ee24d5 --- /dev/null +++ b/ext/standard/tests/array/unexpected_array_mod_bug_variation1.phpt @@ -0,0 +1,33 @@ +--TEST-- +Crash when function parameter modified via reference while keeping orig refcount +--FILE-- +<?php + +$array = array( + 1 => "entry_1", + 2 => "entry_2", + 3 => "entry_3", + 4 => "entry_4", + 5 => "entry_5" +); +usort($array, function($a, $b) use (&$array, &$ref) { + unset($array[2]); + $ref = $array; + return $a <=> $b; +}); +var_dump($array); + +?> +--EXPECT-- +array(5) { + [0]=> + string(7) "entry_1" + [1]=> + string(7) "entry_2" + [2]=> + string(7) "entry_3" + [3]=> + string(7) "entry_4" + [4]=> + string(7) "entry_5" +} |