In SCCP, arrays containing partial objects must be marked as partial so that
their values are not accidentally propagated.
Fixes GH-21227
Closes GH-21232
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
Inline assembly in zend_safe_address() clobbers flags register. Add missing
register in clobber list for aarch64 and powerpc64. Other archs were already
correct.
Fixes GH-21029
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
Within hooks, the backing value can directly be accessed as if no hooks were
present. This was previously handled only in read_property().
zend_fetch_property_address(), which is used for by-ref assignment, will first
call get_property_ptr_ptr() and then try read_property(). However, when called
on uninitialized backing values, read_property() will return
&EG(uninitialized_zval) with an uninitialized property warning. This is
problematic for zend_fetch_property_address() because it write to the result of
read_property() unless there's an exception.
For untyped properties, this can result in writes to &EG(uninitialized_zval)
(see oss-fuzz-471486164-001.phpt). For types properties, it will result in an
unexpected "Typed property C::$prop must not be accessed before initialization"
exception.
Fixes OSS-Fuzz #471486164
Closes GH-20943
* Fix use-after-free in FE_FREE with GC interaction
When FE_FREE with ZEND_FREE_ON_RETURN frees the loop variable during
an early return from a foreach loop, the live range for the loop
variable was incorrectly extending past the FE_FREE to the normal
loop end. This caused GC to access the already-freed loop variable
when it ran after the RETURN opcode, resulting in use-after-free.
Fix by splitting the ZEND_LIVE_LOOP range when an FE_FREE with
ZEND_FREE_ON_RETURN is encountered:
- One range covers the early return path up to the FE_FREE
- A separate range covers the normal loop end FE_FREE
- Multiple early returns create multiple separate ranges
* Split the live-ranges of loop variables again
b0af9ac733 removed the live-range splitting of foreach variables, however it only added handling to ZEND_HANDLE_EXCEPTION.
This was sort-of elegant, until it was realized in 8258b7731b that it would leak the return variable, requiring some more special handling.
At some point we added live tmpvar rooting in 52cf7ab8a2, but this did not take into account already freed loop variables, which also might happen during ZEND_RETURN, which cannot be trivially accounted for, without even more complicated handling in zend_gc_*_tmpvars() functions.
This commit also proposes a simpler way of tracking the loop end in loopvar freeing ops: handle it directly during live range computation rather than during compilation, eliminating the need for opcache to handle it specifically.
Further, opcache was using live_ranges in its basic block computation in the past, which it no longer does. Thus this complication is no longer necessary and this approach should be actually simpler now.
Closes#20766.
Signed-off-by: Bob Weinand <bobwei9@hotmail.com>
---------
Signed-off-by: Bob Weinand <bobwei9@hotmail.com>
Co-authored-by: Gustavo Lopes <mail@geleia.net>
Attributes may themselves contain elements which can have a doc comment on
their own (namely Closures). A doc comment before the attribute list is
generally understood as belonging to the symbol having the attributes.
Fixesphp/php-src#20895.
Internal enums can be cloned and compared, unlike user enums, because we didn't set default_object_handlers when registering internal enums.
Fix by setting default_object_handlers when registering internal enums.
Fixes GH-20914
Closes GH-20915
In the following optimization:
JMPZ(X,L1) JMP(L2) L1: -> JMPNZ(X,L2) NOP
L1 must not be followed by another block, so that it may safely be followed by
the block containing the JMPNZ. get_next_block() is used to verify L1 is the
direct follower. This function also skips empty blocks, including live, empty
target blocks, which will then implicitly follow the new follow block. This will
result in L1 being followed by two separate blocks, which is not possible.
Resolve this by get_next_block() stopping at target blocks.
Fixes OSS-Fuzz #472563272
Closes GH-20850
zend_object_release(&fiber->std) may restart the fiber due to finally. Any
thrown exception must be remembered and unset so that the next fiber may
successfully start.
Fixes OSS-Fuzz #471533782
Closes GH-20884