If there's a try-finally where the try_op starts on a basic block with a
single JMP, and the JMP optimization causes that basic block to become
unreachable, then we update try_op.
In this case, there is no catch_op, so try_op is erroneously set to 0,
we should instead set it to `b->start`.
Closes GH-18110.
We destroy classes of dl()'ed modules in clean_module_classes(), during
shutdown. Child classes of a module use structures of the parent class (such as
inherited properties), which are destroyed earlier, so we have a use-after-free
when destroying a child class.
Here I destroy classes in reverse order, as it is done in zend_shutdown() for
persistent classes.
Fixes GH-17961
Fixes GH-15367
The cache slot for FETCH_OBJ_W in function `test` is primed with the
class for C. The next call uses a simplexml instance and reuses the same
cache slot. simplexml's get_property_ptr handler does not use the cache
slot, so the old values remain in the cache slot. When
`zend_handle_fetch_obj_flags` is called this is not guarded by a check
for the class entry. So we end up using the prop_info from the property
C::$a instead of the simplexml property.
This patch adds a reset to the cache slots in the property address fetch
code and also in the extensions with a non-standard reference handler.
This keeps the run time cache consistent and avoids the issue without
complicating the fast paths.
Closes GH-17739.
This was asked to be checked in https://github.com/php/php-src/pull/17472#issuecomment-2591325036
There are 2 issues:
1) The UB in the if can overflow, and can be fixed by using zend_ulong
for the sum/sub.
2) fast_long_sub_function() has a problem when result aliases.
This is fixed in the same way as fast_long_add_function() works.
Closes GH-17666.
The check for `!fbc || (fbc->common.fn_flags & ZEND_ACC_VARIADIC)` is
performed after `fbc` is set to NULL, so this always returns true.
This results in `ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS` always being
set for unpack sends. Fix it by moving the flag updates to the point
before setting `fbc` to NULL.
Closes GH-17534.
`zend_test_create_throwing_resource` sets the exception in the `test`
call frame and unwinds to `main`. It then throws for the `resource`
variable and verifies that the exception opline is set. However, it
wasn't set in `main`, it was set at the `test` call frame and rethrown later.
The assertion is too conservative, but the end result is right, so drop
the assertion.
Closes GH-17533.
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
The error handling is incomplete on argument cleanup.
1. The fci is not cleared which means that zend_free_trampoline() is
never called.
2. The cleaning for extra named arguments was missing, resulting in
memory leak.
Closes GH-17219.
When observer is enabled, we normally add an extra temporary to all
functions, to store the previously observed frame. However, this is done in
zend_observer_post_startup() so it doesn't happen to dl'ed() functions.
One possible fix would be to move that from zend_observer_post_startup()
to zend_register_functions(), but this would be too early: Observer may
not be enabled when zend_register_functions() is called, and may still be
enabled later.
However, when zend_register_functions() is called at run-time (during dl()),
we know definitively whether observer is enabled.
Here I update zend_register_functions() to add a temporary to dl'ed()
functions when observer is enabled.
Fixes: GH-17211
Closes: GH-17220
op1 of ZEND_MATCH_ERROR, which refers to the match expression, is not freed by
MATCH_ERROR itself. Instead, it is freed by ZEND_HANDLE_EXCEPTION. For normal
control flow, a FREE is placed at the end of the match expression.
Since FREE may appear after MATCH_ERROR in the opcode sequence, we need to
correctly handle op1 of MATCH_ERROR as alive.
Fixes GH-17106
Closes GH-17108
Only on Windows `IS_SLASH_P()` may read the previous byte, and so may
in unlikely cases read one byte out of bounds. Since `IS_SLASH_P()` is
in a public header (albeit not likely to be used by external extensions
or SAPIs), we introduce `IS_SLASH_P_EX()` which accepts a second
argument to prevent that OOB read.
It should be noted that the PHP userland function `dirname()` is not
affected by this issue, since it does not call `zend_dirname()` on
Windows.
Closes GH-16995.
We should compare the block memory, not the block metadata (See
zend_mm_add_huge_block).
This caused random test failure for ext/ffi/tests/gh14626.phpt when the
malloc() performed by the FFI code lies close to the block metadata, and
the size of the block is large enough.
This was reported by https://github.com/php/php-src/issues/16902#issuecomment-2498310452
Closes GH-16938.
zend_save_lexical_state() can be nested multiple times, for example for
the parser initialization and then in the heredoc lexing. The input
should not be freed if we restore to the same filtered string.
Closes GH-16716.
zend_is_callable_ex() can unfortunately emit a deprecation, and then
a user error handler can throw an exception. This causes an assert
failure at ZEND_VM_NEXT_OPCODE(). We fix this by checking if there's an
exception after zend_is_callable_ex().
Closes GH-16803.
Reproducer: https://github.com/php/php-src/issues/16727#issuecomment-2466256317
The root cause is a data race between two different threads:
1) We allocate a lower cased name for an anonymous class here:
f97353f228/Zend/zend_compile.c (L8109)
2) This gets looked up as an interned string here:
f97353f228/Zend/zend_compile.c (L8112)
Assuming that there are uppercase symbols in the string and therefore
`lcname != name` and that `lcname` is not yet in the interned string table,
the pointer value of `lcname` won't change.
3) Here we add the string into the interned string table:
f97353f228/Zend/zend_compile.c (L8223)
However, in the meantime another thread could've added the string into the interned string table.
This means that the following code will run, indirectly called via the `LITERAL_STR` macro,
freeing `lcname`: 62e53e6f49/ext/opcache/ZendAccelerator.c (L572-L575)
4) In the reproducer we then access the freed `lcname` string here:
f97353f228/Zend/zend_compile.c (L8229)
This is solved in my patch by retrieving the interned string pointer
and putting it in `lcname`.
Closes GH-16748.