The behaviour is weird in the sense that the reference must get
unwrapped. What ended up happening is that when destroying the old
reference the sources list was not cleaned properly. We add handling for
that. Normally we would use use ZEND_TRY_ASSIGN_STRINGL but that doesn't
work here as it would keep the reference and change values through
references (see bug #26639).
Closes GH-16272.
In the test, I have an internal `__call` function for `_ZendTestMagicCallForward` that calls the global function with name `$name` via `call_user_function`.
Note that observer writes the pointer to the previously observed frame in the last temporary of the new call frame (`*prev_observed_frame`).
The following happens:
First, we call `$test->callee`, this will be handled via a trampoline with T=2 for the two arguments. The call frame is allocated at this point. This call frame is not observed because it has `ZEND_ACC_CALL_VIA_TRAMPOLINE` set. Next we use `ZEND_CALL_TRAMPOLINE` to call the trampoline, this reuses the stack frame allocated earlier with T=2, but this time it is observed. The pointer to the previous frame is written outside of the call frame because `T` is too small (should be 3). We are now in the internal function `_ZendTestMagicCallForward::__call` where we call the global function `callee`. This will push a new call frame which will overlap `*prev_observed_frame`. This value gets overwritten by `zend_init_func_execute_data` when `EX(opline)` is set because `*prev_observed_frame` overlaps with `EX(opline)`. From now on, `*prev_observed_frame` is corrupted. When `zend_observer_fcall_end` is called this will result in reading wrong value `*prev_observed_frame` into `current_observed_frame`. This causes issues in `zend_observer_fcall_end_all` leading to the segfault we observe.
Despite function with `ZEND_ACC_CALL_VIA_TRAMPOLINE` not being observed, the reuse of call frames makes problems when `T` is not large enough.
To fix this, we make sure to add 1 to `T` if `ZEND_OBSERVER_ENABLED` is true.
Closes GH-16252.
Bisect points to 94ee4f9, however this only reveals the problem.
Cloning an object on a lower branch and trying to call its methods
crashes as well. Cloning the object shouldn't be possible in the first
place because there's an engine constraint that when we have a new
object handler we should also have a clone handler. This constraint is
not fulfilled here.
Closes GH-16245.
libpcre2 can return the special value -1 for a non-match.
In this case we get pointer overflow, although it doesn't matter in
practice because the pointer will be in bounds and the copy length will
be 0. Still, we should fix the UBSAN warning.
Closes GH-16205.
The reference counts of the internal document pointer are mismanaged.
In the case of fragments the refcount may be increased too much, while
for other cases the document reference may not be applied to all
children.
This bug existed for a long time and this doesn't reproduce (easily)
on 8.2 due to other bugs. Furthermore 8.2 will enter security mode soon,
and this change may be too risky.
Fixes GH-16150.
Fixed GH-16152.
Closes GH-16178.
Adding a stack check here as I consider serialization to be a more
sensitive place where erroring out with an exception seems appropriate.
Closes GH-16159.
Unfortunately, old DOM allows attributes to be used as parent nodes.
Only text nodes and entities are allowed as children for these types of
nodes, because that's the constraint DOM and libxml give us.
Closes GH-16156.