mirror of
https://github.com/php/php-src.git
synced 2026-04-03 22:22:18 +02:00
Merge branch 'PHP-7.0' of https://github.com/php/php-src into PHP-7.0
This commit is contained in:
10
NEWS
10
NEWS
@@ -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:
|
||||
|
||||
16
Zend/tests/closure_invoke_case_insensitive.phpt
Normal file
16
Zend/tests/closure_invoke_case_insensitive.phpt
Normal file
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -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) \
|
||||
|
||||
@@ -1035,38 +1035,31 @@ 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);
|
||||
|
||||
retval = zend_hash_sort(Z_ARRVAL_P(array), compare_func, renumber) != FAILURE;
|
||||
|
||||
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);
|
||||
arr = Z_ARR_P(array);
|
||||
if (zend_hash_num_elements(arr) == 0) {
|
||||
PHP_ARRAY_CMP_FUNC_RESTORE();
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
||||
/* Copy array, so the in-place modifications will not be visible to the callback function */
|
||||
arr = zend_array_dup(arr);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
38
ext/standard/tests/array/bug71334.phpt
Normal file
38
ext/standard/tests/array/bug71334.phpt
Normal file
@@ -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
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
Reference in New Issue
Block a user