`try` is a keyword in C++, and as such C++ code including <zend_enum.h>
fails to compile unless a workaround is in place. To resolve this, we
simply rename the parameter.
We choose `try_from` to make it clear that this parameter is true when
the function is called from `BackedEnum::tryFrom()`. For consistency,
we also rename the `try` parameter of `zend_enum_from_base()`, although
that function is not exported.
This issue had been reported by @oplanre, who also provided an initial
PR.
Closes GH-15259.
The destructor of generators is a no-op when the generator is running in a fiber,
because the fiber may resume the generator. Normally the destructor
is not called in this case, but this can happen during shutdown.
We detect that a generator is running in a fiber with the
ZEND_GENERATOR_IN_FIBER flag.
This change fixes two cases not handled by this mechanism:
- The ZEND_GENERATOR_IN_FIBER flag was not added when resuming a "yield from $nonGenerator"
- When a generator that is running in a fiber has multiple children (aka multiple generators yielding from it), all of them could be considered to also run in a fiber (only one actually is), and could leak if not destroyed before shutdown.
This prevents compilation error when compiling PHP by GCC with "-O2 -g -Wall -Werror"
zend_API.c:2754:34: error: array subscript ‘zend_function
{aka const union _zend_function}[0]’ is partly outside array bounds of
‘unsigned char[160]’ [-Werror=array-bounds=]
2754 | if (ZSTR_VAL(fptr->common.function_name)[0] != '_'
Instead of fixing up temporaries count in between observer steps, just apply the additional temporary in the two affected observer steps.
Closes GH-14018.
This was only partially fixed in PHP-8.3. Backports and fixes the case for both
initialized and uninitialized property writes.
Fixes GH-14969
Closes GH-14971
The create_obj handler of InternalIterator is overwritten, but not the
clone_obj handler. This is not allowed.
In PHP 8.2 this didn't cause a segfault because the standard object
handler was used for the clone instead of the internal handler.
So then it allocates and frees the object using the standard object handlers.
In 8.3 however, the object is created using the standard object handler and
freed using the custom handler, resulting in the buffer overflow.
Even though bisect points to 1e1ea4f this only reveals the bug.
Closes GH-14882.
You cannot return or yield a reference to a nullsafe chain. This was
checked already in zend_compile_return but not yet in
zend_compile_yield.
Closes GH-14716.
Values retrieved from zend_getenv should be freed.
Note: The only possible value for `zend_getenv` is `sapi_getenv` which uses
zend alloc to duplicate the string that it reads from the SAPI module.
Closes GH-14708.
is_zend_ptr() expected zend_mm_heap.huge_list to be circular, but it's in fact NULL-terminated. It could crash when at least one huge block exists and the ptr did not belong to any block.
* Fix prototype for trait methods
Fixes GH-14009
* Clenup do_inheritance_check_on_method()
Remove wierd checks and define the behavior by explicit set of flags
* Fix naming and indentation
---------
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
Fixes GH-13970
Closes GH-14105
We cannot validate at compile-time for multiple reasons:
* Evaluating the argument naively with zend_get_attribute_value can lead to code
execution at compile time through the new expression, leading to possible
reentrance of the compiler.
* Even if the evaluation was possible, it would need to be restricted to the
current file, because constant values coming from other files can change
without affecting the current compilation unit. For this reason, validation
would need to be repeated at runtime anyway.
* Enums cannot be instantiated at compile-time (the actual bug report). This
could be allowed here, because the value is immediately destroyed. But given
the other issues, this won't be needed.
Instead, we just move it to runtime entirely. It's only needed for
ReflectionAttribute::newInstance(), which is not particularly a hot path. The
checks are also simple.
In the test cases, the compiler bails out due to a fatal error.
The data structures used by the compiler will contain stale values.
In particular, for the test case CG(loop_var_stack) will contain data.
The next compilation will incorrectly use elements from the previous
stack.
To solve this, we reset part of the compiler data structures.
We don't do a full re-initialization via init_compiler() because that will
also reset streams and resources.
Closes GH-13938.
This fixes an edge case causing the GC to be triggered repeatedly.
Destructors might add potential garbage to the buffer, so it may happen that num_root it higher than gc_threshold after collection, thus triggering a GC run almost immediately. This can happen by touching enough objects in a destructor, e.g. by iterating over an array. If this happens again in the new run, and the threshold is not updated, the GC may be triggered again.
The edge case requires specific conditions to be triggered and it must happen rarely in practice:
* At least GC_THRESHOLD_TRIGGER (100) objects must be collected during each run for the threshold to not be updated
* At least GC_G(gc_threshold) (initially 10k) objects must be touched (decref'ed to n>0) by any destructor during each run to fill the buffer
The fix is to increase the threshold if GC_G(num_roots) >= GC_G(gc_threshold) after GC. The threshold eventually reaches a point at which the second condition is not met anymore.
The included tests trigger more than 200 GC runs before the fix, and 2 after the fix (dtors always trigger a second run).
A related issue is that zend_gc_check_root_tmpvars() may add potential garbage before the threshold is adjusted, which may trigger GC and exhaust the stack. This is fixed by setting GC_G(active)=1 around zend_gc_check_root_tmpvars().
Inherited methods regardless of source must share the original runtime cache. Traits were missed.
This adds ZEND_ACC_TRAIT_CLONE to internal functions as well to allow easy distinction of these.
autoconf/libtool generating code to test features missed `void` for
C calls prototypes w/o arguments.
Note that specific changes related to libtool have to be upstreamed.
Co-authored-by: Peter Kokot <petk@php.net>
close GH-13732
Inside `zend_object_std_dtor` the weakrefs are notified after the destruction
of properties already took place. In this test case, the destructor of an anon
class will be invoked due to the property destruction. That class has a
weak reference to its parent. This means that the destructor can access
parent properties that already have been destroyed, resulting in a UAF.
Fix this by notifying the weakrefs at the start of the object's
destruction.
Closes GH-13613.
For master (8.4-dev) I merged GH-13381. But that PR changes public API
of TSRM, so cannot be used on lower branches.
This patch is a safe workaround for the issue, in combination with a
pre-existing fix using `ifdef ZTS + if (module_started)` inside pgsql
and odbc. The idea is to delay unloading modules until the persistent
resources are destroyed. This will keep the destructor code accessible
in memory.
This is not a proper fix on its own, because we still need the
workaround of not accessing globals after module destruction.
The proper fix is in master.
Closes GH-13388.
* Fix GH-13193: Significant performance degradation in 'foreach' starting from PHP 8.2.13 (caused by garbage collection)
* Don't run zend_gc_remove_root_tmpvars() if GC is not active or GC buffer is empty