Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 200 additions & 14 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,206 @@ PHP NEWS
?? ??? ????, PHP 8.6.0alpha1

- Core:
. Added first-class callable cache to share instances for the duration of the
request. (ilutov)
. It is now possible to use reference assign on WeakMap without the key
needing to be present beforehand. (ndossche)
. Added `clamp()`. (kylekatarnls, thinkverse)
. Fix OSS-Fuzz #429429090 (Failed assertion on unset() with uninitialized
container). (ilutov)
. Fixed GH-20564 (Don't call autoloaders with pending exception). (ilutov)
. Fix deprecation now showing when accessing null key of an array with JIT.
(alexandre-daubois)
. Fixed bug GH-20174 (Assertion failure in
ReflectionProperty::skipLazyInitialization after failed LazyProxy
initialization). (Arnaud)
. Enabled the TAILCALL VM on Windows when compiling with Clang >= 19 x86_64.
. Fixed bug GH-22290 (AST pretty printing does not correctly handle strings
containing NUL). (iliaal)
. Fixed bug GH-22206 (missing return in global register detection).
(P3p111n0)

- DBA:
. Fixed OOB read on malformed length field in dba flatfile handler. (alhudz)

- Exif:
. Fixed bug GH-11020 (exif_read_data() emits a spurious "Illegal IFD size"
warning when an IFD is not followed by a next-IFD offset). (Eyüp Can Akman)

- Hash:
. Fixed bug GH-18173 (ext/hash relies on implementation-defined malloc
alignment). (iliaal)

- Opcache:
. Fixed bug GH-22158 (Tracing JIT dispatches the observer begin handler
through the wrong run_time_cache slot on megamorphic calls). (ptondereau,
iliaal)
. Fixed bug GH-22443 (Tracing JIT SIGSEGV on megamorphic dynamic calls from
an undereferenced run_time_cache map_ptr offset). (iliaal)
. Fixed bug GH-21770 (Infinite recursion in property hook getter in opcache
preloaded trait). (iliaal)

- OpenSSL:
. Fixed timeout for supplemental read at end of a blocking stream in SSL
stream wrapper. (ilutov)

- Intl:
. Fixed Locale::lookup() and locale_lookup() to return NULL instead of the
fallback locale when a language tag cannot be canonicalized. (Weilin Du)
. Fixed memory leaks when calling Collator::__construct() or
Spoofchecker::__construct() twice. (Weilin Du)
. Fixed memory leak when calling IntlListFormatter::__construct() twice.
(Weilin Du)
. Fixed IntlChar methods leaving stale global error state after successful
calls. (Xuyang Zhang)

- PDO_ODBC:
. Fixed bug GH-20726 (Crash with ODBC connection pooling when the DSN
carries no credentials). (iliaal)

- Phar:
. Fixed inconsistent handling of the magic ".phar" directory. Paths such as
"/.phar" remain protected, while non-magic paths that merely start with
".phar" are handled consistently across file and directory creation,
copying, ArrayAccess, stream lookup, directory iteration and extraction.
(Weilin Du)

- PHPDBG:
. Fixed bug GH-17387 (Trivial crash in phpdbg lexer). (iliaal)

- Reflection:
. Fixed bug GH-22324 (Ignore leading namespace separator in
ReflectionParameter::__construct()). (jorgsowa)
. Fixed bug GH-22441 (ReflectionClass::hasProperty() and getProperty() ignore
dynamic properties shadowing a private parent property). (iliaal)

- Session:
. Fixed bug GH-21314 (Different session garbage collector behavior between
PHP 8.3 and PHP 8.5). (jorgsowa)

- SPL:
. Fix class_parents for classes with leading slash in non-autoload mode.
(jorgsowa)
. Ignore leading back-slash in class_parents(), class_implements(), and
class_uses(). (jorgsowa)
. Fixed bug GH-16217 (SplFileObject::fputcsv() on an uninitialized object
segfaults). (iliaal)

- Standard:
. Fixed bug GH-22395 (base_convert() outputs at most 64 characters).
(Weilin Du)

- URI:
. Fixed behavior of Uri\WhatWg\Url wither methods with regards to empty
opaque hosts. (kocsismate)

02 Jul 2026, PHP 8.5.8

- Core:
. Fixed bug GH-22280 (Incorrect compile error for goto to label preceding
try/finally block). (Pratik Bhujel)
. Fixed bug GH-22112 (Assertion when error handler throws during NaN to
bool/string coercion). (iliaal)

- BCMath:
. Fixed issues with oversized allocations and signed overflow in bcround()
and BcMath\Number::round(). (edorian)

- Date:
. Fix incorrect recurrence check of DatePeriod::createFromISO8601String().
(ndossche)

- Exif:
. Read correct value for single and double tags. (ndossche)

- GD:
. Fixed bug GH-22121 (Double free in gdImageSetStyle() after
overflow-triggered early return). (iliaal)

- Intl:
. Fix incorrect argument positions for invalid start/end arguments in
transliterator_transliterate().
(Weilin Du)
. Fixed IntlTimeZone::getDisplayName() to synchronize object error state
for invalid display types. (Weilin Du)

- Lexbor:
. Merge patch c3a6847. (ilutov, timwolla)

- Opcache:
. Fixed bug GH-22265 (Another tailcall vm_interrupt bug). (Levi Morrison)
. Fixed bug GH-20469 (Unsafe inheritance cache replay with reentrant
autoloading). (Levi Morrison)
. Fixed bug GH-21972 (Corrupted variable type when a typed by-value return
contains a reference wrapper). (Weilin Du)

- Phar:
. Fixed a bypass of the magic ".phar" directory protection in
Phar::addEmptyDir() for paths starting with "/.phar", while allowing
non-magic directory names that merely share the ".phar" prefix. (Weilin Du)
. Fixed an integer underflow when parsing ZIP extra fields. (Weilin Du)

- Reflection:
. Preserve class-name case in ReflectionClass::getProperty() error messages
and autoloading. (jorgsowa)

- SOAP:
. Fixed bug GH-22218 (SoapServer::handle() crash on $_SERVER not being
an array). (David Carlier / Rex-Reynolds)
. Fixed bug GH-22285 (Soap server requires the raw input to be passed
to $server->handle). (David Carlier / ndossche)

- Sqlite:
. Fix error checks for column retrieval. (ndossche)

- URI:
. Add LEXBOR_STATIC to CFLAGS_URI on Windows so ext/uri does not see
LXB_API as __declspec(dllimport) when linked statically into PHP.
(Luther Monson)
. Clean error logs before each Uri\WhatWg\Url wither call so that errors from
previous wither calls are not returned the next time a UrlValidationError
is thrown. (kocsismate)

- Zip:
. Fixed error-related memory leaks. (ndossche)

- Zlib:
. Fixed memory leak if deflate initialization fails and there is a dict.
(ndossche)
. Fixed memory leak in inflate_add(). (ndossche)

02 Jun 2026, PHP 8.5.7

- CLI:
. Fixed bug GH-21901 (Stale getopt() optional value). (onthebed)

- Core:
. Fixed bug GH-22071 (JIT assertion on abstract static method call).
(David Carlier)

- Date:
. Fixed bug GH-18422 (int overflow in php_date_llabs). (iliaal)

- DOM:
. Fixed bug GH-22077 (UAF in custom XPath function).
(afflerbach/David Carlier)

- Opcache:
. Fixed tracing JIT crash when a VM interrupt is handled during an observed
user function call. (Levi Morrison)
. Fixed bug GH-21746 (Segfault with tracing JIT). (Arnaud)
. Fixed bug GH-22004 (Assertion failure at ext/opcache/jit/zend_jit_trace.c).
(Arnaud)
. Fixed tailcall VM crash when a VM interrupt is handled from a VM helper.
(Levi Morrison, Arnaud)

- OpenSSL:
. Fix compatibility issues with OpenSSL 4.0. (jordikroon, Remi)

- Standard:
. Fixed bug GH-21689 (version_compare() incorrectly handles versions ending
with a dot). (timwolla)

- URI:
. Fixed CVE-2026-44927 (In uriparser before 1.0.2, there is pointer
difference truncation to int in various places). (CVE-2026-44927)
(Sebastian Pipping)
. Fixed CVE-2026-44928 (In uriparser before 1.0.2, the function family
EqualsUri can misclassify two unequal URIs as equal). (CVE-2026-44928)
(Sebastian Pipping)

07 May 2026, PHP 8.5.6

- Core:
. Fixed bug GH-19983 (GC assertion failure with fibers, generators and
destructors). (iliaal)
. Fixed ZEND_API mismatch on zend_ce_closure forward decl for Windows+Clang.
(henderkes)
. Deprecate specifying a nullable return type for __debugInfo(). (timwolla)
. Fixed bug GH-22142 (Assertion failure in zendi_try_get_long() on IS_UNDEF).
Expand Down
60 changes: 28 additions & 32 deletions ext/dba/libflatfile/flatfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@

#define FLATFILE_BLOCK_SIZE 1024

/* Parse the length prefix in `buf` into `num` and grow `buf` to hold it.
* atoi() narrows a malformed (e.g. negative) length to a huge size_t whose
* `+ FLATFILE_BLOCK_SIZE` would overflow erealloc(); the macro yields true in
* that case so the caller stops reading and the read stays within `buf_size`. */
#define FLATFILE_GROW_BUF(num, buf, buf_size) ( \
(num) = atoi(buf), \
(num) >= (buf_size) && ( \
(num) > SIZE_MAX - FLATFILE_BLOCK_SIZE \
|| ((buf) = erealloc((buf), (buf_size) = (num) + FLATFILE_BLOCK_SIZE), 0) \
) \
)

/*
* ret = -1 means that database was opened for read-only
* ret = 0 success
Expand Down Expand Up @@ -110,10 +122,8 @@ int flatfile_delete(flatfile *dba, datum key_datum) {
if (!php_stream_gets(dba->fp, buf, 15)) {
break;
}
num = atoi(buf);
if (num >= buf_size) {
buf_size = num + FLATFILE_BLOCK_SIZE;
buf = erealloc(buf, buf_size);
if (FLATFILE_GROW_BUF(num, buf, buf_size)) {
break;
}
pos = php_stream_tell(dba->fp);

Expand All @@ -133,10 +143,8 @@ int flatfile_delete(flatfile *dba, datum key_datum) {
if (!php_stream_gets(dba->fp, buf, 15)) {
break;
}
num = atoi(buf);
if (num >= buf_size) {
buf_size = num + FLATFILE_BLOCK_SIZE;
buf = erealloc(buf, buf_size);
if (FLATFILE_GROW_BUF(num, buf, buf_size)) {
break;
}
/* read in the value */
num = php_stream_read(dba->fp, buf, num);
Expand All @@ -160,10 +168,8 @@ int flatfile_findkey(flatfile *dba, datum key_datum) {
if (!php_stream_gets(dba->fp, buf, 15)) {
break;
}
num = atoi(buf);
if (num >= buf_size) {
buf_size = num + FLATFILE_BLOCK_SIZE;
buf = erealloc(buf, buf_size);
if (FLATFILE_GROW_BUF(num, buf, buf_size)) {
break;
}
num = php_stream_read(dba->fp, buf, num);

Expand All @@ -176,10 +182,8 @@ int flatfile_findkey(flatfile *dba, datum key_datum) {
if (!php_stream_gets(dba->fp, buf, 15)) {
break;
}
num = atoi(buf);
if (num >= buf_size) {
buf_size = num + FLATFILE_BLOCK_SIZE;
buf = erealloc(buf, buf_size);
if (FLATFILE_GROW_BUF(num, buf, buf_size)) {
break;
}
num = php_stream_read(dba->fp, buf, num);
}
Expand All @@ -200,10 +204,8 @@ datum flatfile_firstkey(flatfile *dba) {
if (!php_stream_gets(dba->fp, buf, 15)) {
break;
}
num = atoi(buf);
if (num >= buf_size) {
buf_size = num + FLATFILE_BLOCK_SIZE;
buf = erealloc(buf, buf_size);
if (FLATFILE_GROW_BUF(num, buf, buf_size)) {
break;
}
num = php_stream_read(dba->fp, buf, num);

Expand All @@ -216,10 +218,8 @@ datum flatfile_firstkey(flatfile *dba) {
if (!php_stream_gets(dba->fp, buf, 15)) {
break;
}
num = atoi(buf);
if (num >= buf_size) {
buf_size = num + FLATFILE_BLOCK_SIZE;
buf = erealloc(buf, buf_size);
if (FLATFILE_GROW_BUF(num, buf, buf_size)) {
break;
}
num = php_stream_read(dba->fp, buf, num);
}
Expand All @@ -242,20 +242,16 @@ datum flatfile_nextkey(flatfile *dba) {
if (!php_stream_gets(dba->fp, buf, 15)) {
break;
}
num = atoi(buf);
if (num >= buf_size) {
buf_size = num + FLATFILE_BLOCK_SIZE;
buf = erealloc(buf, buf_size);
if (FLATFILE_GROW_BUF(num, buf, buf_size)) {
break;
}
num = php_stream_read(dba->fp, buf, num);

if (!php_stream_gets(dba->fp, buf, 15)) {
break;
}
num = atoi(buf);
if (num >= buf_size) {
buf_size = num + FLATFILE_BLOCK_SIZE;
buf = erealloc(buf, buf_size);
if (FLATFILE_GROW_BUF(num, buf, buf_size)) {
break;
}
num = php_stream_read(dba->fp, buf, num);

Expand Down
31 changes: 31 additions & 0 deletions ext/dba/tests/dba_flatfile_oob.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
--TEST--
DBA FlatFile handler bounds with a malformed (negative) length field
--EXTENSIONS--
dba
--SKIPIF--
<?php
require_once __DIR__ . '/setup/setup_dba_tests.inc';
check_skip('flatfile');
?>
--FILE--
<?php
$db_file = __DIR__ . '/dba_flatfile_oob.db';
// A negative length narrows to a huge size_t and previously overran the read buffer.
file_put_contents($db_file, "-1\n" . str_repeat('A', 200000));

$db = dba_open($db_file, 'r', 'flatfile');
var_dump(dba_firstkey($db));
var_dump(dba_exists("AAAA", $db));
var_dump(dba_fetch("AAAA", $db));
dba_close($db);
echo "done\n";
?>
--CLEAN--
<?php
@unlink(__DIR__ . '/dba_flatfile_oob.db');
?>
--EXPECT--
bool(false)
bool(false)
bool(false)
done
10 changes: 8 additions & 2 deletions ext/exif/exif.c
Original file line number Diff line number Diff line change
Expand Up @@ -3650,8 +3650,14 @@ static bool exif_process_IFD_in_JPEG(image_info_type *ImageInfo, char *dir_start
* There are 2 IDFs, the second one holds the keys (0x0201 and 0x0202) to the thumbnail
*/
if (!exif_offset_info_contains(info, dir_start+2+NumDirEntries*12, 4)) {
exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Illegal IFD size");
return false;
/*
* A TIFF/EXIF IFD ends with a 4-byte offset to the next IFD (IFD1 here,
* which links the thumbnail), or zero when there is none. Some files end
* the EXIF segment right after the entries and omit those 4 bytes. A
* missing offset is valid and just means there is no next IFD, so stop
* here instead of reporting the size as illegal.
*/
return true;
}

if (tag != TAG_EXIF_IFD_POINTER && tag != TAG_GPS_IFD_POINTER) {
Expand Down
Loading
Loading