Rarely fails with "Maximum execution time of 1 seconds exceeded" due to being
too fast. Increase the compared arrays and mark as FLAKY, given this is
inherently dependent on processing speed.
zend_std_get_property_ptr_ptr() was the only property handler that did
not propagate the IN_GET guard to the underlying object when forwarding
from a lazy proxy after initialization. This caused __get to be called
on the underlying object when it shouldn't be, leading to assertion
failures.
The same guard-copying pattern already existed in read_property,
write_property, unset_property, and has_property since commit
26f5009e91 (GH-18039).
Also fixes GH-20873 and GH-20854.
Closes GH-20875
The primary motivation for this is that this is required for my abstract generic types proof of concept, as the resolving of bound types needs to happen early to properly track the types.
However, there doesn't seem to be a good reason for delaying the inheritance of interfaces.
This approach might even allow us to drop the `iface` parameter of the `interface_gets_implemented()` handler as the interface name is always known.
Previously, static trait properties would always redeclare locally declared
static properties to make sure any inherited property would stop sharing a
common slot with the parent. This would leave holes in property_info, creating
issues for this code:
zend_hash_extend(&ce->properties_info,
zend_hash_num_elements(&ce->properties_info) +
zend_hash_num_elements(&parent_ce->properties_info), 0);
where zend_hash_num_elements(&ce->properties_info) +
zend_hash_num_elements(&parent_ce->properties_info) is supposed to extend the
hash table enough to hold all additional properties coming from parent. However,
if ce->properties_info contains holes this might not be enough, given all parent
properties are appended at nNumUsed.
This could be fixed by further extending the hash table, but we can also avoid
the holes in properties_info completely by not redeclaring trait properties that
are already declared in the target class. This is now possible because traits
are bound before performing parent class inheritance, so if the property is
already present we know it will separate the property slot.
Fixes GH-20672
Closes GH-21358
Disable resource-heavy tests by default (>1GB of memory usage), unless the
RUN_RESOURCE_HEAVY_TESTS env variable is set.
Fixes GH-20762
Closes GH-20935
We don't expect the lazy proxy to be modified during initialization, but
this is allowed. The modification may set a property, still marked LAZY,
without removing the LAZY flag. This causes an assertion failure in GH-20174.
Both the RFC and the documentation specify that after an initialization
failure, the state of the object is reset to its pre-initialization state:
If the initializer throws an exception, the object state is reverted to
its pre-initialization state and the object is marked as lazy again. In
other words, all effects on the object itself are reverted. Other side
effects, such as effects on other objects, are not reverted. This prevents
exposing a partially initialized instance in case of failure.
This behavior would have prevented this issue, but it was not implemented
for lazy proxies (only for ghosts).
Fix by implementing the missing behavior.
Fixes GH-20174
Closes GH-20181
In GH-18039 we guard the underlying property before forwarding access
to the real instance of a lazy proxy. When the real instance lacks magic
methods, the assertion zobj->ce->ce_flags & ZEND_ACC_USE_GUARDS fails in
zend_get_property_guard().
Fix by checking that the real instance uses guards.
Fixes GH-20504
Closes GH-21093
A lazy object is marked non-lazy when all its properties are
initialized. Before doing so we delete the object info, resulting in a
temporarily invalid state. In GH-20657 the GC is triggered at this moment.
Fix by deleting the object info _after_ marking it non lazy.
Fixes GH-20657
Closes GH-21094
The aim of this PR is twofold:
- Reduce the number of highly similar TMP|VAR handlers
- Avoid ZVAL_DEREF in most of these cases
This is achieved by guaranteeing that all zend_compile_expr() calls, as well as
all other compile calls with BP_VAR_{R,IS}, will result in a TMP variable. This
implies that the result will not contain an IS_INDIRECT or IS_REFERENCE value,
which was mostly already the case, with two exceptions:
- Calls to return-by-reference functions. Because return-by-reference functions
are quite rare, this is solved by delegating the DEREF to the RETURN_BY_REF
handler, which will examine the stack to check whether the caller expects a
VAR or TMP to understand whether the DEREF is needed. Internal functions will
also need to adjust by calling the zend_return_unwrap_ref() function.
- By-reference assignments, including both $a = &$b, as well as $a = [&$b]. When
the result of these expressions is used in a BP_VAR_R context, the reference
is unwrapped via a ZEND_QM_ASSIGN opcode beforehand. This is exceptionally
rare.
Closes GH-20628
The computed number of properties using zend_hash_num_elements(zobj->properties)
is incorrect when the object contains virtual properties. We don't have a
trivial way to find the number of properties virtual properties that need to be
added to this number, so just append with zend_hash_add_new() instead.
Fixes GH-20479
Closes GH-20988
When __clone of the underlying object fails with a bailout, ZEND_ASSERT(res ==
SUCCESS) in zend_lazy_object_del_info() will fail because the info has not been
registered yet.
Only copy OBJ_EXTRA_FLAGS once the info has been successfully registered.
Fixes GH-20905
Closes GH-20975
These are leftovers from the pre-PHP-7.0 era. This also implicitly solves
GH-20564 by not clearing exceptions before entering the autoloader.
Closes GH-20256
Fixes GH-20564
UNSET_OBJ et al. do not expect to find IS_UNDEF results for IS_INDIRECT vars. To
solve this, return IS_NULL from FETCH_OBJ_UNSET when properties are
uninitialized. Do the same for FETCH_STATIC_PROP_IS, as we're otherwise copying
IS_UNDEF into the VAR result, which is not a valid value for VAR.
Fixes OSS-Fuzz #429429090
Closes GH-19160