* Fix FD getting code on big endian (PHP 8.3)
stream casting as FD returns a php_socket_t, which is an int, but
zend_long is 64-bit (on those platforms). This works on LE by
accidental (unless it forgets to clear the high word), but is fatal
on big endian.
* change cast to match sig
Fortunately, these only allocate too much memory and not too little.
Also just change it to `sizeof(*var)` everywhere to avoid this mistake
in the future.
A bunch of different issues:
1) The referenced value is copied without incrementing the refcount.
The reason the refcount isn't incremented is because otherwise
the array modifications would violate the RC1 constraints.
Solve this by copying the reference itself instead and always
read the referenced value.
2) No type checks on the array data, so malicious scripts could
cause type confusion bugs.
3) Potential overflow when the arrays resize and we access ctag.
Closes GH-17205.
EX(opline) / opline can be stale if the IP is not stored, like in this
case on a trace enter. We always need to make sure that the opline is up
to date to make sure we don't use stale data.
Closes GH-17260.
This was a bug in both libxml and PHP.
We follow up with the same change as done in GNOME/libxml@b3871dd138.
Changing away from `xmlOutputBufferCreateFilenameDefault` is not
possible yet because this is a stable branch and would break BC.
Closes GH-17254.
The FFI call return values follow widening rules.
We must widen to `ffi_arg` in the case we're handling a return value for types shorter than the machine width.
From http://www.chiark.greenend.org.uk/doc/libffi-dev/html/The-Closure-API.html:
> In most cases, ret points to an object of exactly the size of the type specified when cif was constructed.
> However, integral types narrower than the system register size are widened.
> In these cases your program may assume that ret points to an ffi_arg object.
If we don't do this, we get wrong values when reading the return values.
Closes GH-17255.
Co-authored-by: Dmitry Stogov <dmitry@zend.com>
The issue that BMP RLE occasionally swallowed some pixels[1] had been
fixed long ago in libgd, but apparently it has been overlooked to port
it to our bundled libgd.
We also introduce the test helper `test_image_equals_image()` which
compares in-memory images for equality.
[1] <https://github.com/libgd/libgd/issues/276>
Closes GH-17250.
This bug happens because of a nested `SHM_UNPROTECT()` sequence.
In particular:
```
unprotect memory at ext/opcache/ZendAccelerator.c:2127
protect memory at ext/opcache/ZendAccelerator.c:2160
unprotect memory at ext/opcache/ZendAccelerator.c:2164
unprotect memory at ext/opcache/jit/zend_jit_trace.c:7464
^^^ Nested
protect memory at ext/opcache/jit/zend_jit_trace.c:7591
^^^ Problem is here: it should not protect again due to the nested unprotect
protect memory at ext/opcache/ZendAccelerator.c:2191
^^^ This one should actually protect, not the previous one
```
The reason this nesting happen is because:
1. We try to include the script, this eventually calls `cache_script_in_shared_memory`
2. `zend_optimize_script` will eventually run SCCP as part of the DFA pass.
3. SCCP will try to replace constants, but can also run destructors when a partial array is destructed here:
4e9cde758e/Zend/Optimizer/sccp.c (L2387-L2389)
In this case, this destruction invokes the GC which invokes the tracing JIT,
leading to the nested unprotects.
This patch disables the GC to prevent invoking user code, as user code
is not supposed to run during the optimizer pipeline.
Closes GH-17249.
Co-authored-by: Dmitry Stogov <dmitry@zend.com>
NULL checks for the glob stream are inconsistently applied. To solve
this generally, factor it out to a helper function so it's less likely
to be forgotten in the future.
Closes GH-17231.
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
* PHP-8.3:
NEWS for GH-17168
ext/gettext/config.m4: symlink en_US.UTF-8 test bits to en_US for musl
ext/gettext/tests: fix libintl return values under musl
ext/gettext/gettext.c: handle NULLs from bindtextdomain()
The gettext() family of functions under musl does not support codeset
suffixes like ".UTF-8", because the only codeset it understands is
UTF-8. (Yes, it is annoying that it doesn't support the suffix for the
codeset that it does understand; no, I am not in charge.) Thanks to
this, we have six failing tests on musl,
* FAIL Gettext basic test with en_US locale that should be on nearly
every system
[ext/gettext/tests/gettext_basic-enus.phpt]
* FAIL Test if bindtextdomain() returns string id if no directory path
is set( if directory path is 'null')
[ext/gettext/tests/gettext_bindtextdomain-cwd.phpt]
* FAIL Test dcgettext() functionality
[ext/gettext/tests/gettext_dcgettext.phpt]
* FAIL Test dgettext() functionality
[ext/gettext/tests/gettext_dgettext.phpt]
* FAIL Test if dngettext() returns the correct translations
(optionally plural).
[ext/gettext/tests/gettext_dngettext-plural.phpt]
* FAIL Test ngettext() functionality
[ext/gettext/tests/gettext_ngettext.phpt]
These are all fixed by symlinking the en_US.UTF-8 message data to en_US,
where musl is able to find it.
This does not make the situation any better for developers (who don't
know what libc their users will be running), but that problem is
inhereted from C and is not the fault of the gettext extension.
This partially addresses GH #13696
Musl has two quirks that are leading to failed internationalization
tests. First is that the return value of bindtextdomain(..., NULL)
will always be false, rather than an "implementation-defined default
directory," because musl does not have an implementation-defined
default directory. One test needs a special case for this.
Second is that the musl implementation of bind_textdomain_codeset()
always returns NULL. The POSIX-correctness of this is debatable, but
it is roughly equivalent to correct, because musl only support UTF-8,
so the NULL value indicating that the codeset is unchanged from the
locale's codeset (UTF-8) is accurate.
PHP's bind_textdomain_codeset() function however treats NULL as
failure, unconditionally:
* https://github.com/php/doc-en/issues/4311
* https://github.com/php/php-src/issues/17163
This unfortunately causes false to be returned consistently on musl --
even when nothing unexpected has happened -- and naturally this is
affecting several tests. For now we change two tests to accept "false"
in addition to "UTF-8" so that they may pass on musl. If PHP's
bind_textdomain_codeset() is updated to differentiate between NULL and
NULL-with-errno-set, these tests can also be updated once again to
reject the NULL-with-errno result.
This partially addresses GH #13696
According to POSIX, bindtextdomain() returns "the implementation-
defined default directory pathname used by the gettext family of
functions" when its second parameter is NULL (i.e. when you are
querying the directory corresponding to some text domain and that
directory has not yet been set). Its PHP counterpart is feeding
that result direclty to RETURN_STRING, but this can go wrong in
two ways:
1. If an error occurs, even POSIX-compliant implementations
may return NULL.
2. At least one non-compliant implementation (musl) lacks
a default directory and returns NULL whenever the domain
has not yet been bound.
In either of those cases, PHP segfaults on the NULL string. In this
commit we check for the NULL, and RETURN_FALSE when it happens rather
than crashing.
This partially addresses GH #13696
`glob(3)` doesn't know the virtual CWD of PHP, so we need to pass an
absolute path for ZTS builds. In lack of a reusable routine, we copy
the code from `glob()` and adapt as needed.
Closes GH-17074.