Issue: https://github.com/php/php-src/issues/8044
Author: TysonAndre
### Description
The following code in a php build configured with --enable-debug (reproduced in 7.4,
8.0, 8.1, 8.2.0-dev):
```php
<?php
$x = new SplFixedArray(1);
$x[0] = $x;
var_export($x);
```
Resulted in this output in _zend_hash_index_add_or_update_i for
HT_ASSERT_RC1. This is due to ext/spl/spl_array.c needing to update the implementation
of its array in place for static HashTable* spl_fixedarray_object_get_properties(zend_object
*obj) so that the output of var_export, var_dump, json_encode, etc. all reflect the latest
array contents of the backing fixed array:
```
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] 312613 abort (core dumped) php -a
```
But I expected this output instead:
```
Not crashing, successfully setting $x[0]
```
(I haven't tested php 7.3, though that branch is closed regardless. 7.2 did not have this debug
failure)
--------
Also, I'm not familiar with the history of this, but it seems like there are (at least) **3
different mechanisms** in use for infinite recursion detection for json_encode/var_export/var_dump.
**Would it make sense to firstcheck Z_PROTECT_RECURSION in var_export in addition to/instead of
protecting the array, before calling get_properties_for?**
- json_encode needs distinct results of *get_properties (Z_OBJPROP) to detect infinite
recursion.
- var_export needs *get_properties_for to return the same array every time to detect
infinite recursion with GC_TRY_PROTECT_RECURSION. (E.g. this 1. makes it impractical to save memory
(and save time in garbage collection) by returning a distinct array rather than populating
get_properties., 2. Seems like it would delay garbage collection of objects unintuitively if you
call var_export then replace the entry of SplFixedArray (they wouldn't be garbage collected
until the next var_export/json_encode/var_dump call, or (array) cast?))
Adding similar calls to Z_PROTECT_RECURSION(zval *struct) (and UNPROTECT), either
instead of or in addition to existing may help avoid this failure mode.
By design, var_export does not use https://www.php.net/manual/en/language.oop5.magic.php#object.debuginfo
- I wonder if that's somehow related to the different design used by var_dump, but the code
isn't documented
- var_dump is doing yet another different thing, and calling Z_PROTECT_RECURSION(zval
*struct) to set the GC_FLAGS
on the object?
- serialize thankfully calls php_var_serialize_intern and checks with var_already
= php_add_var_hash with a var_hash specific to that serializer, which is correct
-------
I'd be worried about replacing the existing checks in <=8.1/8.0, in case extensions were
somehow relying on specifics of whatever calls to get_properties/get_properties_for were made.
### PHP Version
PHP 7.4-8.2
### Operating System
_No response_