[php-src] Issue #8041: php 8.2.0-dev crashes with assertion for cloning/get_object_vars on non-empty SplFixedArray (8.1 unaffected)
| From: | TysonAndre | Date: | Sat, 05 Feb 2022 15:19:01 +0000 |
| Subject: | [php-src] Issue #8041: php 8.2.0-dev crashes with assertion for cloning/get_object_vars on non-empty SplFixedArray (8.1 unaffected) | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-239499@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/8041
Author: TysonAndre
### Description
The following code:
```php
<?php
php > $x = new SplFixedArray(/*count*/ 1);
php > var_export((array)$x);
array (
0 => NULL,
)
php > $y = clone $x;
```
Resulted in this output (in a debug build - php 8.1 is unaffected), crashes in nts build for larger
arrays:
```
php: /path/to/php-src/Zend/zend_objects.c:241: zend_objects_clone_members: Assertion
`!(((__ht)->u.flags & (1<<2)) != 0)' failed.
[1] 126358 abort (core dumped) php -a
```
But I expected this output instead:
```
Not crashing with a ZEND_ASSERT failure or invalid memory access
```
----
Similar bugs affect Zend/zend_builtin_functions.c get_object_vars()
```
php > $x = new SplFixedArray(1);
php > $x[0] = $x;
php > var_export(get_object_vars($x));
php: /path/to/php-src/Zend/zend_hash.c:1012: _zend_hash_index_add_or_update_i: Assertion
`(zend_gc_refcount(&(ht)->gc) == 1) || ((ht)->u.flags & (1<<6))' failed.
[1] 127583 abort (core dumped) php -a
```
-----
Cause:
ZEND_HASH_MAP_FOREACH_KEY_VAL(old_object->properties, num_key, key, prop) {
expects the properties HashTable* to always be associative, but it sometimes be packed,
e.g. for SplFixedArray.
Possible solutions:
1. Use the slower ZEND_HASH_FOREACH_KEY_VAL macro that works with both packed and
associative HashTables. This seems to me like the best solution.
2. Split up the code into two separate cases for LIST/MAP internal representations where performance
sensitive, in combination with 1.
3. Somehow force properties tables to always be associative when creating objects, including for
PECL code (would waste memory)
@nikic @dstogov thoughts?
The following parts of the code are likely to be affected, I've only confirmed for
zend_objects.c and zend_builtin_functions.c
```c
» ag 'ZEND_HASH.*properties\b' ../php-src
../php-src/Zend/zend_objects.c
241: ZEND_HASH_MAP_FOREACH_KEY_VAL(old_object->properties, num_key, key, prop) {
../php-src/Zend/zend_API.c
1291: ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, value) {
1549: ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, prop) {
1581: ZEND_HASH_FOREACH_KEY_VAL(properties, h, key, prop) {
../php-src/Zend/zend_builtin_functions.c
764: ZEND_HASH_MAP_FOREACH_KEY_VAL(properties, num_key, key, value) {
../php-src/ext/snmp/snmp.c
1824: ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&php_snmp_properties, key, hnd) {
../php-src/ext/reflection/php_reflection.c
480: ZEND_HASH_MAP_FOREACH_STR_KEY(properties, prop_name) {
4590: ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, prop) {
```
### PHP Version
PHP 8.2.0-dev (2022-Feb-05)
### Operating System
_No response_