mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix GH-19303: Unpacking empty packed array into uninitialized array causes assertion failure
Having an empty result array is not a problem, because zend_hash_extend() will initialize it. Except it does not when the number of elements to add equals 0, which leaves the array uninitialized and therefore does not set the packed flag, causing the assertion failure. Technically, removing the assert would also work and save a check. On the other hand, this check could also prevent some real work to be done and should be relatively cheap as we already have to compute the sum anyway. Closes GH-19318.
This commit is contained in:
2
NEWS
2
NEWS
@@ -11,6 +11,8 @@ PHP NEWS
|
||||
binary const expr). (ilutov)
|
||||
. Fixed bug GH-19305 (Operands may be being released during comparison).
|
||||
(Arnaud)
|
||||
. Fixed bug GH-19303 (Unpacking empty packed array into uninitialized array
|
||||
causes assertion failure). (nielsdos)
|
||||
|
||||
- FTP:
|
||||
. Fix theoretical issues with hrtime() not being available. (nielsdos)
|
||||
|
||||
11
Zend/tests/array_unpack/gh19303.phpt
Normal file
11
Zend/tests/array_unpack/gh19303.phpt
Normal file
@@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
GH-19303 (Unpacking empty packed array into uninitialized array causes assertion failure)
|
||||
--FILE--
|
||||
<?php
|
||||
$a = [0];
|
||||
unset($a[0]);
|
||||
var_dump([...$a]);
|
||||
?>
|
||||
--EXPECT--
|
||||
array(0) {
|
||||
}
|
||||
@@ -6162,17 +6162,22 @@ ZEND_VM_C_LABEL(add_unpack_again):
|
||||
zval *val;
|
||||
|
||||
if (HT_IS_PACKED(ht) && (zend_hash_num_elements(result_ht) == 0 || HT_IS_PACKED(result_ht))) {
|
||||
zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1);
|
||||
ZEND_HASH_FILL_PACKED(result_ht) {
|
||||
ZEND_HASH_PACKED_FOREACH_VAL(ht, val) {
|
||||
if (UNEXPECTED(Z_ISREF_P(val)) &&
|
||||
UNEXPECTED(Z_REFCOUNT_P(val) == 1)) {
|
||||
val = Z_REFVAL_P(val);
|
||||
}
|
||||
Z_TRY_ADDREF_P(val);
|
||||
ZEND_HASH_FILL_ADD(val);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} ZEND_HASH_FILL_END();
|
||||
/* zend_hash_extend() skips initialization when the number of elements is 0,
|
||||
* but the code below expects that result_ht is initialized as packed.
|
||||
* We can just skip the work in that case. */
|
||||
if (result_ht->nNumUsed + zend_hash_num_elements(ht) > 0) {
|
||||
zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1);
|
||||
ZEND_HASH_FILL_PACKED(result_ht) {
|
||||
ZEND_HASH_PACKED_FOREACH_VAL(ht, val) {
|
||||
if (UNEXPECTED(Z_ISREF_P(val)) &&
|
||||
UNEXPECTED(Z_REFCOUNT_P(val) == 1)) {
|
||||
val = Z_REFVAL_P(val);
|
||||
}
|
||||
Z_TRY_ADDREF_P(val);
|
||||
ZEND_HASH_FILL_ADD(val);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} ZEND_HASH_FILL_END();
|
||||
}
|
||||
} else {
|
||||
zend_string *key;
|
||||
|
||||
|
||||
27
Zend/zend_vm_execute.h
generated
27
Zend/zend_vm_execute.h
generated
@@ -2657,17 +2657,22 @@ add_unpack_again:
|
||||
zval *val;
|
||||
|
||||
if (HT_IS_PACKED(ht) && (zend_hash_num_elements(result_ht) == 0 || HT_IS_PACKED(result_ht))) {
|
||||
zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1);
|
||||
ZEND_HASH_FILL_PACKED(result_ht) {
|
||||
ZEND_HASH_PACKED_FOREACH_VAL(ht, val) {
|
||||
if (UNEXPECTED(Z_ISREF_P(val)) &&
|
||||
UNEXPECTED(Z_REFCOUNT_P(val) == 1)) {
|
||||
val = Z_REFVAL_P(val);
|
||||
}
|
||||
Z_TRY_ADDREF_P(val);
|
||||
ZEND_HASH_FILL_ADD(val);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} ZEND_HASH_FILL_END();
|
||||
/* zend_hash_extend() skips initialization when the number of elements is 0,
|
||||
* but the code below expects that result_ht is initialized as packed.
|
||||
* We can just skip the work in that case. */
|
||||
if (result_ht->nNumUsed + zend_hash_num_elements(ht) > 0) {
|
||||
zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1);
|
||||
ZEND_HASH_FILL_PACKED(result_ht) {
|
||||
ZEND_HASH_PACKED_FOREACH_VAL(ht, val) {
|
||||
if (UNEXPECTED(Z_ISREF_P(val)) &&
|
||||
UNEXPECTED(Z_REFCOUNT_P(val) == 1)) {
|
||||
val = Z_REFVAL_P(val);
|
||||
}
|
||||
Z_TRY_ADDREF_P(val);
|
||||
ZEND_HASH_FILL_ADD(val);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} ZEND_HASH_FILL_END();
|
||||
}
|
||||
} else {
|
||||
zend_string *key;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user