zend_std_write_property() can return the variable pointer, but the code
was using a local variable, and so a pointer to a local variable could
be returned. Fix this by using the value pointer instead of the backup
value was written.
This can be more efficient on master by using the safe_assign helper.
Closes GH-17947.
`new Reflectionproperty($scope, $propName)` keeps a reference to the
zend_property_info of $propName declared in $scope. In getRawValue() and
related methods, we use this reference to check whether the property is hooked.
Calling `new ReflectionProperty($scope, $propName)->getRawValue($object)` is
equivalent to the expression $object->$propName from scope $scope (except that
it bypasses hooks), and thus may access an overridden property (unless the
original is private). This property may have hooks and different flags.
Here I fetch the effective property info before checking for hooks and
property flags.
Fixes GH-17713
Closes GH-17714
Normally, accesses to properties marked as lazy trigger the object's
initialization, or forward to a real instance if the object is an initialized
proxy.
The purpose of ReflectionProperty::setRawValueWithoutLazyInitialization() and
ReflectionProperty::skipLazyInitialization() is to bypass auto-initialization,
so that some properties can be initialized without triggering initialization.
However, when the object is an initialized proxy, these methods would
unexpectedly update the proxy.
Here I make sure that these methods have an effect on the real instance, when
the object is an initialized proxy.
Fixes GH-16344
If a lazy object is created for a class whose constants can not be updated, then
we have created an instance of a non-instantiable class. This breaks the
expectations of clone.
Here I ensure that a class has its constants updated before creating a lazy
instance of it.
Fixes OSS-Fuzz #71407
Closes GH-15856
Supporting object reset while its properties are being iterated would increase
complexity for little benefit. Furthermore it may not be possible to ensure a
consistent behavior between ghosts and proxies (wrt to iteration position).
Iteration is detected by checking if the object's properties ht has iterators.
This requires refactoring the hooked get_iterator() implementation to ensure
that it creates a properties ht iterator immediately.
Closes GH-15960
zend_lazy_object_get_properties() is used by zend_std_get_properties_ex() to fetch the properties of lazy objects. It initializes the object and returns its properties.
When initialization fails we return an empty ht because most callers do not check for NULL. We rely on the exception thrown during initialization. We also assign that empty ht to zend_object.properties for the same reasons.
We asserted that zend_object.properties was either NULL or &zend_empty_array, but there are other cases in which a uninitialized lazy object may have a properties ht.
Here I remove the assertion, and return the existing properties ht if there is one. Otherwise I return zend_new_array(0) instead of &zend_emtpy_array as not all callers expect an immutable array (e.g. FE_FETCH does not).
Instead of always saying that a name is reserved or deprecated and
cannot/should not be used as a class name, take the usage into account and say
the name cannot be used as an enum name, trait name, etc. In the process, for
class names add a missing "a".
The return value of zho_build_properties_ex() is passed to ZVAL_ARR(), which sets the IS_TYPE_REFCOUNTED flag. Returning &zend_emtpy_array will crash later when trying to dtor the zval.
I'm fixing this by returning zend_new_array(0) instead of &zend_empty_array.
An alternative was to make ZVAL_ARR() aware of immutable arrays, like ZVAL_STR() is with interned strings, but I found no other problematic cases.
zend_get_property_info_for_slot(obj, slot) assumes that 'slot' belongs to 'obj', but that may not be the case for lazy proxies.
Fortunately, the property info is often already available in path when it is needed.
For other cases, I make zend_get_property_info_for_slot() aware of lazy objects, and add zend_get_property_info_for_slot_self() for cases where the 'slot' is known to belong to the object itself.
Fixes oss-fuzz #71446