Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zif_get_object_vars: Assertion `!(((__ht)->u.flags & (1<<2)) != 0)' failed. #10200

Closed
Deltik opened this issue Jan 1, 2023 · 2 comments
Closed

Comments

@Deltik
Copy link

Deltik commented Jan 1, 2023

Description

The following code:

<?php

$xmlData = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<document>https://github.com/php/php-src/issues/10200 not encountered</document>
EOF;

$xml = simplexml_load_string($xmlData);
$output = get_object_vars($xml);
var_dump($output);

Resulted in this output:

php: /tmp/php-build/source/8.2.0/Zend/zend_builtin_functions.c:763: zif_get_object_vars: Assertion `!(((__ht)->u.flags & (1<<2)) != 0)' failed.
Aborted

But I expected this output instead:

array(1) {
  [0] =>
  string(59) "https://github.com/php/php-src/issues/10200 not encountered"
}

This bug affects PHP 8.2.0 but not PHP 8.1.13.

PHP 8.2.0 was compiled with the following configure options:

--enable-sockets
--enable-exif
--with-zlib
--with-zlib-dir=/usr
--with-bz2
--enable-intl
--with-openssl
--enable-soap
--enable-xmlreader
--with-xsl
--enable-ftp
--enable-cgi
--with-curl=/usr
--with-tidy
--enable-sysvsem
--enable-sysvshm
--enable-shmop
--with-mysqli=mysqlnd
--with-pdo-mysql=mysqlnd
--with-pdo-sqlite
--enable-pcntl
--with-readline
--enable-mbstring
--enable-debug
--enable-fpm
--enable-bcmath
--enable-phpdbg
--with-webp
--enable-gd
--with-jpeg
--with-zip
--with-mhash

PHP Version

PHP 8.2.0

Operating System

Ubuntu 22.04

Additional Information

Here's the line in the PHP source code where the assertion error happens:
https://github.com/php/php-src/blob/PHP-8.2.0/Zend/zend_builtin_functions.c#L763

@nielsdos
Copy link
Member

nielsdos commented Jan 1, 2023

I analyzed this issue for a bit. I can confirm this happens on 8.2 and higher.

The issue occurs because the summary element does not have attributes in your example, so the array of properties is just

array(1) {
  [0]=>
  string(31) "Segmentation fault happens here"
}

i.e. there is only an integer index here, so it's a packed hash table. But the code at that line 763 assumes it gets a non-packed hash table. Replacing ZEND_HASH_MAP_FOREACH_KEY_VAL by ZEND_HASH_FOREACH_KEY_VAL fixes the issue in this case I think. The error and the ZEND_HASH_MAP_FOREACH_KEY_VAL macro were introduced by 90b7bde, so I guess the assumption that there's a non-packed hash table does not hold at all the places where this replacement happened.

Applying the following diff fixes this particular case, but there are probably more places where the following change needs to happen.

diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 8813fa9788..5cebbbc560 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -760,7 +760,7 @@ ZEND_FUNCTION(get_object_vars)
        } else {
                array_init_size(return_value, zend_hash_num_elements(properties));
 
-               ZEND_HASH_MAP_FOREACH_KEY_VAL(properties, num_key, key, value) {
+               ZEND_HASH_FOREACH_KEY_VAL(properties, num_key, key, value) {
                        bool is_dynamic = 1;
                        if (Z_TYPE_P(value) == IS_INDIRECT) {
                                value = Z_INDIRECT_P(value);

@Deltik
Copy link
Author

Deltik commented Jan 2, 2023

I updated my repro snippet with a much simpler one.

Deltik added a commit to Deltik/e107 that referenced this issue Jan 2, 2023
… error

Casting a `SimpleXMLElement` to an array should be equivalent to
`get_object_vars(…)` as far as I can tell.  At least all existing
tests pass and I don't see any visual regressions upon making this
change.

By replacing `get_object_vars(…)` with a cast to array, we sidestep
this PHP 8.2.0 bug: php/php-src#10200

Fixes: e107inc#4938
nielsdos added a commit to nielsdos/php-src that referenced this issue Jan 2, 2023
… (1<<2)) != 0)' failed.

This occurs because the array of properties is a single element with an
integer key, not an associative array. Therefore it is a packed array
and thus the assumption the iteration macro makes is invalid.

This restores the behaviour of PHP<8.2.
nielsdos added a commit to nielsdos/php-src that referenced this issue Jan 2, 2023
Co-authored-by: Deltik <deltik@gmx.com>
Girgias pushed a commit that referenced this issue Jan 2, 2023
…<<2)) != 0)' failed.

This occurs because the array of properties is a single element with an
integer key, not an associative array. Therefore it is a packed array
and thus the assumption the iteration macro makes is invalid.

This restores the behaviour of PHP<8.2.

Closes GH-10209

Co-authored-by: Deltik <deltik@gmx.com>

Signed-off-by: George Peter Banyard <girgias@php.net>
@Girgias Girgias closed this as completed in a3d2c33 Jan 2, 2023
Jimmi08 pushed a commit to hpkizi/e107 that referenced this issue Jan 3, 2023
Casting a `SimpleXMLElement` to an array should be equivalent to
`get_object_vars(…)` as far as I can tell.  At least all existing
tests pass and I don't see any visual regressions upon making this
change.

By replacing `get_object_vars(…)` with a cast to array, we sidestep
this PHP 8.2.0 bug: php/php-src#10200

Fixes: e107inc/e107#4938
nielsdos added a commit to nielsdos/php-src that referenced this issue Jan 6, 2023
Girgias pushed a commit that referenced this issue Jan 7, 2023
Closes GH-10252

Signed-off-by: George Peter Banyard <girgias@php.net>
Girgias added a commit that referenced this issue Jan 7, 2023
* PHP-8.2:
  Move test for GH-10200 to the simplexml extension test directory
nielsdos added a commit to nielsdos/php-src that referenced this issue Mar 30, 2023
…perties

This is a variant of phpGH-10200, but in a different place.
Basically, simplexml may create a properties table that's packed instead
of associative. But the macro that was used to loop over the properties
table assumed that it was always associative. Replace it by the macro
that figures it out automatically which one of the two it is.
nielsdos added a commit that referenced this issue Apr 1, 2023
…ties

This is a variant of GH-10200, but in a different place.
Basically, simplexml may create a properties table that's packed instead
of associative. But the macro that was used to loop over the properties
table assumed that it was always associative. Replace it by the macro
that figures it out automatically which one of the two it is.

For test: Co-authored-by: jnvsor

Closes GH-10984.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants