exif_read_data() only reads the thumbnail if $read_thumbnail is true,
and exif_thumbnail() only scans the thumbnail for its dimensions if they
are requested, so the exif fuzzer never reached this code.
Since the default of opcache.jit changed from "tracing" to "disable"
(c16ad918ba, RFC jit_config_defaults), JIT_G(enabled) is false after
startup and zend_jit_config() rejects every runtime change of
opcache.jit. The function-jit and tracing-jit fuzzers turn the JIT on
at runtime without checking the result, so since PHP 8.4 they have only
been running the VM. The OSS-Fuzz coverage report of 2026-10-24 shows
0.04% line coverage (40/103166) for ext/opcache/jit/.
Start with opcache.jit=off, which keeps the JIT available, and abort if
switching the JIT mode fails, so that this cannot regress silently.
- Replace bailout on OOM with UnwindExit
- Properly reset various globals that may be accessed during startup
Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
Co-authored-by: Jakub Zelenka <bukka@php.net>
Co-authored-by: Nora Dossche <7771979+ndossche@users.noreply.github.com>
Co-authored-by: Nicolas Grekas <nicolas.grekas@gmail.com>
ZEND_VM_ENTER_BIT tags the opline returned by CALL VM handlers. It is
1ULL so that ~ZEND_VM_ENTER_BIT keeps the upper half of 64-bit pointers,
but on 32-bit platforms it widens the tagged pointer expressions to
64 bits, and casting those back to a pointer warns. This breaks
--enable-werror builds where no global VM registers are used, e.g. arm32,
or i386 with --disable-gcc-global-regs.
Use (uintptr_t)1 instead, which is exactly pointer-sized everywhere, also
in the copies of the definition in the JIT and the fuzzer SAPI.
This is unused; this is a vestige of 6c158374ba
and 45e327a672, which set up some timeout code
which was removed in 650c1c0a7d. Remove this
useless function from SAPIs.
Previously, the fuzzer only used the default options (`0`) and the
`PHP_JSON_OBJECT_AS_ARRAY` option (`1`). After running the fuzzer on its
existing corpus with `-reduce_inputs=0`, `-runs=100000`, and `-seed=1`, it
failed to reach the code paths for handling big integers and strings, or for
dealing with invalid UTF8, within the allotted 100,000 runs. Those 100,000 runs
resulted in coverage of roughly 2,020 code blocks or edges, and roughly 5,400
"features".
Expand the fuzzer to also run with options that include the
`PHP_JSON_BIGINT_AS_STRING`, `PHP_JSON_INVALID_UTF8_IGNORE`, and
`PHP_JSON_INVALID_UTF8_SUBSTITUTE` flags. The two flags for handling UTF-8 are
not applied used together, since invalid UTF-8 can only be handled one way, but
other than that all combinations of these flags and `PHP_JSON_OBJECT_AS_ARRAY`
are now tested. Repeating the same fuzzing as earlier with the expanded options
results in roughly 2,150 code blocks or edges, and roughly 5,700 "features",
being covered.
FUZZER_BUILD links $(PHP_BINARY_OBJS), including
main/internal_functions_cli.lo, but the php-fuzz-* rules list
$(PHP_SAPI_OBJS), including main/internal_functions.lo, as prerequisites.
Building a fuzzer target in isolation from a clean tree therefore fails
because internal_functions_cli.lo has not been built.
Use $(PHP_BINARY_OBJS) for these prerequisites to match the objects linked by
FUZZER_BUILD. This aligns the fuzzer build rules with the CLI, CGI, phpdbg,
and litespeed fragments.
Assisted-By: Claude Opus 5
Closes#23394
The libtool 1.5.26 is bundled with PHP since the very early days of the
Autotools build system to ease the building process and avoid additional
dependency on the system Libtool. This updates the bundled libtool to
2.5.4 version.
Fixes and implementations:
- Fixed race conditions when building PHP in parallel ("cannot create
.libs" warnings).
- Implements request https://bugs.php.net/70374 (Update libtool.m4)
- Fixes libtool eating -flto flags.
- Fixes GH-17310 (configure producing errors on macOS)
- Fixes GH-15946 (./configure error when building with NixOS)
Changes:
- Add a script to update autotools files.
- libtool is spread across multiple files; phpize is updated to handle
this.
- Remove outdated hacks, i.e. for `ar`.
- Remove documentation references to external libtool, as we vendor it.
- `--with-pic` is now `--enable-pic`. Error out on the old flag.
- On macOS linker now uses -undefined dynamic_lookup flag for shared
extensions and shared embed SAPI (libphp) instead of older
'-undefined suppress -flat_namespace' combination.
Co-authored-by: Peter Kokot <peterkokot@gmail.com>
The zend_exception_save() and zend_exception_restore() functions were removed in
GH-20256. However, the fuzzer expects to be able to call opcache_invalidate()
even if there was an exception thrown. I'm not sure why exactly, but let's
restore the previous behavior.
Closes OSS-Fuzz #476466130
These are leftovers from the pre-PHP-7.0 era. This also implicitly solves
GH-20564 by not clearing exceptions before entering the autoloader.
Closes GH-20256
Fixes GH-20564
RFC: https://wiki.php.net/rfc/deprecations_php_8_5#remove_disable_classes_ini_setting
This took longer to merge than expected but the initial motivation from 2 years ago still applied:
As described in the email to the PHP internals list [1] this feature is fundamentally broken and pointless.
Only internal classes can be disable which brings the following observation. On a minimal build of PHP, with only the mandatory extensions enabled, there are 148 classes/interfaces/traits defined. [2]
Other than the SPL ones (and even then), disabling any of these classes will cause issues within the engine.
Moreover, the SPL ones are not a security concern.
Therefore, any other class that can be disabled must come from an extension that can be disabled altogether. And "disabling" a class from an extension without disabling said extension will render it useless anyway.
If a hosting provided is concerned about an extension, then it should not enable it in the first place. Not break it ad hoc.
Considering the above, I cannot see how this functionality was ever useful.
This is in stark contrast to the disable_functions INI setting, which can be used to selectively remove functionality of an extension without breaking it overall.
What makes this setting particularly broken is that it does not unregister the class, it only overwrites the create CE handler to emit a warning and purge the properties and function hashtables. This leads to various use after free, segfaults, and broken expectations for the engine and extensions which define said classes. On top of that, it is possible to actually instantiate such a class (and even classes which actually disallow this like ext/imap) in userland, and pass it to function that are typed against said class without raising a TypeError. However, when trying to do anything with said object stuff is going to explode in countless ways.
[1] https://news-web.php.net/php.internals/120896
[2] https://gist.github.com/Girgias/63d55ba1e50b580412b004046daed02b
The stack limit is checked when entering execute_ex(), but the fuzzer has
its own execute function and does not call execute_ex().
Add a stack limit check in the fuzzer's execute function.
Closes GH-19391
This removes the --enable-opcache/--disable-opcache configure switch. OPcache
is now always builtin. The default value of opcache.enable and
opcache.enable_cli is unchanged.
RFC: https://wiki.php.net/rfc/make_opcache_required
Closes GH-18961.
Co-authored-by: Tim Düsterhus <tim@tideways-gmbh.com>
- AS_VAR_IF macro used
- redundant quotes removed
- PHP_FUZZER_TARGET macro body synced with the rest of the macros in
php-src
- PHP_FUZZER_TARGET arguments quoted
This macro once had also the 5th argument (the build target), which was
removed via 2a6da0f24c. This quotes all
PHP_SELECT_SAPI arguments and removes the redundant ones. The basic
macro usage help text is moved to the macros section from the obsolete
docs file.
- Arguments quoted
- Redundant comments removed (some basic help info is in the
build/php.m4)
- APXS variable as such isn't used in the generated Makefile, the path
to the apxs tool is inserted during the configure step directly
* Include from build dir first
This fixes out of tree builds by ensuring that configure artifacts are included
from the build dir.
Before, out of tree builds would preferably include files from the src dir, as
the include path was defined as follows (ignoring includes from ext/ and sapi/) :
-I$(top_builddir)/main
-I$(top_srcdir)
-I$(top_builddir)/TSRM
-I$(top_builddir)/Zend
-I$(top_srcdir)/main
-I$(top_srcdir)/Zend
-I$(top_srcdir)/TSRM
-I$(top_builddir)/
As a result, an out of tree build would include configure artifacts such as
`main/php_config.h` from the src dir.
After this change, the include path is defined as follows:
-I$(top_builddir)/main
-I$(top_builddir)
-I$(top_srcdir)/main
-I$(top_srcdir)
-I$(top_builddir)/TSRM
-I$(top_builddir)/Zend
-I$(top_srcdir)/Zend
-I$(top_srcdir)/TSRM
* Fix extension include path for out of tree builds
* Include config.h with the brackets form
`#include "config.h"` searches in the directory containing the including-file
before any other include path. This can include the wrong config.h when building
out of tree and a config.h exists in the source tree.
Using `#include <config.h>` uses exclusively the include path, and gives
priority to the build dir.
These are either undefined or defined to value 1 in Autotools and
Windows:
- HAVE_COMMONCRYPTO_COMMONRANDOM_H
- HAVE_EXIF
- HAVE_FOPENCOOKIE
- HAVE_IF_NAMETOINDEX
- HAVE_LIBICONV
- HAVE_SOCKETS
- HAVE_STRUCT_STAT_ST_RDEV
- HAVE_STRUCT_TM_TM_GMTOFF
- HAVE_STRUCT_TM_TM_ZONE
Follow up of GH-5526 (-Wundef)
* Mark many functions as static
Multiple functions are missing the static qualifier.
* remove unused struct sigactions
struct sigaction act, old_term, old_quit, old_int;
all unused.
* optimizer: minXOR and maxXOR are unused