This makes a number of related changes to the generator tree
management, that should hopefully make it easier to understand,
more robust and faster for the common linear-chain case. Fixes
https://bugs.php.net/bug.php?id=80240, which was the original
motivation here.
* Generators now only add a ref to their direct parent.
* Nodes only store their children, not their leafs, which avoids
any need for leaf updating. This means it's no longer possible
to fetch the child for a certain leaf, which is something we
only needed in one place (update_current). If multi-children
nodes are involved, this will require doing a walk in the other
direction (from leaf to root). It does not affect the common
case of single-child nodes.
* The root/leaf pointers are now seen as a pair. One leaf generator
can point to the current root. If a different leaf generator is
used, we'll move the root pointer over to that one. Again, this
is a cache to make the common linear chain case fast, trees may
need to scan up the parent link.
Closes GH-6344.
Use the general zend_generator_throw_exception() helper for this.
Otherwise we don't handle the off-by-one opline correctly (should
we maybe just stop doing that?)
This is a followup to ad750c3bb6,
which fixed a different yield from exception handling problem that
happened to show up in the same test case from oss-fuzz #25321.
Now both issues should be fixed.
Voidification of Zend API which always succeeded
Use bool argument types instead of int for boolean arguments
Use bool return type for functions which return true/false (1/0)
Use zend_result return type for functions which return SUCCESS/FAILURE as they don't follow normal boolean semantics
Closes GH-6002
From an engine perspective, named parameters mainly add three
concepts:
* The SEND_* opcodes now accept a CONST op2, which is the
argument name. For now, it is looked up by linear scan and
runtime cached.
* This may leave UNDEF arguments on the stack. To avoid having
to deal with them in other places, a CHECK_UNDEF_ARGS opcode
is used to either replace them with defaults, or error.
* For variadic functions, EX(extra_named_params) are collected
and need to be freed based on ZEND_CALL_HAS_EXTRA_NAMED_PARAMS.
RFC: https://wiki.php.net/rfc/named_params
Closes GH-5357.
Fixes a use-after-free encountered in Symfony's SecurityBundle.
I don't have a reproducer for this, and believe the issue can only
occur if we leak an iterator (the leak is a separate issue).
We should not free the generator iterator here, because we do not
own it. The code that fetched the iterator is responsible for
releasing it. In the rare case where we do hit this code-path,
we cause a use-after-free.
get_gc() implementations that need to explore heterogeneous data
currently work by computing how many GC entries they need,
allocating a buffer for that and storing it on the object. This
is inefficient and wastes memory, because the buffer is retained
after the GC run.
This commit adds an API for a single global GC buffer, which can
be reused by get_gc implementations (as only one get_gc call is
ever active at the same time). The GC buffer will automatically
grow during the GC run and be discarded at the end.
The DO_INIT flag, which will skip the first resume on a primed
generator, should always be set when starting to yield from a
new generator, not only when the yield from happens during priming.
Finally blocks in generators may be invoked during shutdown, in
which case we don't have a stack frame. Similar to what
zend_call_function does, we still need to rethrow these exceptions,
otherwise they will be hidden (and leak).
NULL out the execute_data before destroying it, otherwise GC may
trigger while the execute_data is partially destroyed, resulting
in double-frees.
The handling of call stack unfreezing is a bit awkward because it's
a ZEND_API function, so we can't change the signature.
We also change `Generator::throw()` to expect a `Throwable` in the
first place, and we now throw a TypeError instead of returning `false`
from `Exception::getTraceAsString()`.