There doesn't seem to be a thread post-startup hook that runs after
zend_startup_cb() that could be used for this
this fix is similar to accel_startup_ok() as seen here: fc1db70f10/ext/opcache/ZendAccelerator.c (L2631-L2634)
Closes GH-16853.
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.
When the current data is invalid, NULL must be returned. At least that's
how the check in SPL works and how other extensions do this as well.
If we don't do this, an UNDEF value gets propagated to a return value
(misprinted as null); leading to issues.
Closes GH-16825.
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.
When returning an UNDEF value, it actually becomes NULL.
The following code took this into account:
28344e0445/ext/opcache/jit/zend_jit_trace.c (L2196-L2199)
But the stack does not update the type to NULL, causing a mismatch.
Closes GH-16784.
Co-authored-by: Dmitry Stogov <dmitry@zend.com>
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.
There are two issues:
1) There's an off-by-one in the check for the minimum file size for a
tar (i.e. `>` instead of `>=`).
2) The loop in the tar parsing parses a header, and then unconditionally
reads the next one. However, that doesn't necessarily exist.
Instead, we remove the loop condition and check for the end of the
file before reading the next header. Note that we can't use
php_stream_eof as the flag may not be set yet when we're already at
the end.
Closes GH-16700.
Adding two exit early safeguards in the *nix configuration build script:
1) Given the initial cd into the build tree fails (the project root),
the `buildconf` script exits with non-zero status (failure).
2) Given the grep command does not exist or `configure.ac` AC_INIT [1]
expectations are unmet, the buildconf script exits non-zero.
Additionally quoting the pathname to cd into and the empty CD_PATH
parameter for portability, also for systems that are using a
non-portable pathname [2] for the build tree.
The initial CD safeguard has been applied to the `buildconf` and
four more scripts:
- build/genif.sh
- scripts/dev/credits
- scripts/dev/genfiles
- scripts/dev/makedist
Rationale:
Cd-ing into the project root should always prematurely exit w/ FAILURE
as a required precondition for its invocation has not been met. This
should never go unnoticed as it always requires user intervention.
Similar and more specifically to the PHP build on *nix systems, the
grep command is required early to obtain the `php_extra_version` from
configure.ac. Previously, if the grep command is missing (or failing
due to not matching the line with the AC_INIT macro [1]), the internal
dev parameter would always be zero (0) which can easily result in the
situation that the configure script is not being rebuilt. This is
cumbersome as the rebuild of a configure script is more likely required
with checked-out dev versions under change rather than an already
properly set-up build environment on a dedicated build or release
system. Missing the fact that either the grep utility is missing or
the expectation of having the AC_INIT macro in configure.ac is unmet
should never go unnoticed as it always requires user intervention.
[1]: https://www.gnu.org/software/autoconf/manual/autoconf-2.67/html_node/Initializing-configure.html
[2]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_271
Closes GH-16717.
When passing an array, the key entry can get converted to a string if it
is an object, but this actually modifies the original array entry.
The test originally outputted:
```
array(2) {
[0]=>
string(...) => ...
[1]=>
string(0) ""
}
```
This is unexpected. Use zval_try_get_string() to prevent this behaviour.
Closes GH-16693.
It is assumed that the serialization always had initialised its buffer
zend_string, but in the case of a type not serialising, it is null.
close GH-16599
zlog_buf_prefix() can return a larger length than what actually was
written due to its use of snprintf(). The code in
zlog_stream_prefix_ex() does not take this into account, other callers
do. What ends up happening then is that stream->length is set to the
length as if snprintf() was able to write all bytes, causing
stream->length to become larger than stream->buf.size, causing a
segfault.
In case the buffer was too small we try with a larger buffer up to a
limit of zlog_limit. This makes sure that the stream length will remain
bounded by the buffer size.
This also adds assertions to make the programmer intent clear and catch
this more easily in debug builds.
Closes GH-16680.
Additionally fixes wrong behaviour in ReflectionParameter when you first
have a construction that uses an object and the subsequent doesn't.
Closes GH-16672.
`timelib_astro_rise_set_altitude()` is not prepared to deal with non-
finite values (`nan`, `inf` and `-inf`) for `lon` and `lat`; instead
these trigger undefined behavior. Thus we catch non-finite values
before even calling that timelib function; for `date_sun_info()` we
trigger `ValueError`s; for `date_sunrise()` and `date_sunset()` we
silently return `false`, since these functions will be sunsetted
anyway.
Closes GH-16497.
A previous bug fix[1] relied on ODBC drivers to properly count down the
`StrLen_or_IndPtr` argument for consecutive calls to `SQLGetData()`.
Apparently, not all drivers handle this correctly, so we cannot assert
they do. Instead we fall back to the old behavior for drivers which
would violate the assertion.
A test against SQLServer (which we currently use in CI) would not make
sense, since the respective drivers do not exhibit that behavior.
Instead we target the regression test especially to a MS Access
database.
Since there is apparently no way to easily create an MS Access database
programmatically, we commit a minimal empty DB which is used for the
regression test, and could also be used by other test cases.
[1] <bccca0b53aa60a62e2988c750fc73c02d109e642>
Closes GH-16587.
We need to perform all sanity checks before doing any modification.
I don't have a reliable and easy test for this on 8.2, but I have one
for 8.4.
Closes GH-16598.
This is already forbidden by libxml, but this condition isn't properly
checked; so the return value and lack of error makes it seem like it
worked while it actually didn't. Furthermore, this can break assumptions
and assertions later on.
Closes GH-16596.
even without sanitizers, it is reproducible but with the following
```
<?php
$g = gmp_init(256);
var_dump(gmp_pow($g, PHP_INT_MAX));
```
we get this
```
AddressSanitizer:DEADLYSIGNAL
=================================================================
==286922==ERROR: AddressSanitizer: FPE on unknown address 0x03e8000460ca (pc 0x7faf6c69de5c bp 0x400000000000004 sp 0x7ffe9843c740 T0)
#0 0x7faf6c69de5c in __pthread_kill_implementation nptl/pthread_kill.c:44
#1 0x7faf6c649c81 in __GI_raise ../sysdeps/posix/raise.c:26
#2 0x7faf6db9386c in __gmp_exception (/lib/x86_64-linux-gnu/libgmp.so.10+0xd86c) (BuildId: 1af68a49fe041a5bb48a2915c3d47541f713bb38)
#3 0x7faf6db938d3 in __gmp_overflow_in_mpz (/lib/x86_64-linux-gnu/libgmp.so.10+0xd8d3) (BuildId: 1af68a49fe041a5bb48a2915c3d47541f713bb38)
#4 0x7faf6dbac95c in __gmpz_realloc (/lib/x86_64-linux-gnu/libgmp.so.10+0x2695c) (BuildId: 1af68a49fe041a5bb48a2915c3d47541f713bb38)
#5 0x7faf6dba9038 in __gmpz_n_pow_ui (/lib/x86_64-linux-gnu/libgmp.so.10+0x23038) (BuildId: 1af68a49fe041a5bb48a2915c3d47541f713bb38)
#6 0x5565ae1ccd9f in zif_gmp_pow /home/dcarlier/Contribs/php-src/ext/gmp/gmp.c:1286
#7 0x5565aee96ea9 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /home/dcarlier/Contribs/php-src/Zend/zend_vm_execute.h:1312
#8 0x5565af144320 in execute_ex /home/dcarlier/Contribs/php-src/Zend/zend_vm_execute.h:56075
#9 0x5565af160f07 in zend_execute /home/dcarlier/Contribs/php-src/Zend/zend_vm_execute.h:60439
#10 0x5565aed6fafe in zend_execute_scripts /home/dcarlier/Contribs/php-src/Zend/zend.c:1842
#11 0x5565aeae70a8 in php_execute_script /home/dcarlier/Contribs/php-src/main/main.c:2578
#12 0x5565af532f4e in do_cli /home/dcarlier/Contribs/php-src/sapi/cli/php_cli.c:964
#13 0x5565af535877 in main /home/dcarlier/Contribs/php-src/sapi/cli/php_cli.c:1334
#14 0x7faf6c633d67 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#15 0x7faf6c633e24 in __libc_start_main_impl ../csu/libc-start.c:360
#16 0x5565adc04040 in _start (/home/dcarlier/Contribs/php-src/sapi/cli/php+0x2604040) (BuildId: 949049955bdf8b7197390b1978a1dfc3ef6fdf38)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: FPE nptl/pthread_kill.c:44 in __pthread_kill_implementation
==286922==ABORTING
```
close GH-16384
`dba_open()` accepts arbitrary stream wrapper paths, but unless no
locking (`-`) is specified, we try to determine the underlying file
path. If that fails, we need to error out.
Closes GH-16498.
After normalization, `N` is supposed to be in range [0, 24], but for
very large and very small `$utcOffset` this is not necessarily the
case, since the normalization might yied `-inf` or `inf`. If that
happens, we let the function fail silently, since it is highly unlikely
that such `$utcOffset`s are passed in practice.
Closes GH-16483.