From 2565bf85958f6f12f1b5dd2f19260d60013aebfd Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 24 Jun 2026 11:11:46 -0400 Subject: [PATCH 1/4] Fix GH-22422: define ZEND_TRACK_ARENA_ALLOC in php_config.h (#22439) ZEND_TRACK_ARENA_ALLOC selects an alternative zend_arena struct layout for AddressSanitizer, but it was only appended to the core CFLAGS, never recorded in php_config.h. Extensions built separately with phpize inherit php_config.h rather than the core CFLAGS, so they compiled the untracked layout while core used the tracked one. Destroying a core-created arena from such an extension leaked every tracked allocation. Define it with AC_DEFINE so core and extensions agree on the layout. Fixes GH-22422 --- NEWS | 2 ++ configure.ac | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 0961ddaa9fbf..71f67c39665f 100644 --- a/NEWS +++ b/NEWS @@ -30,6 +30,8 @@ PHP NEWS string interpolation). (timwolla) . Fixed bug GH-22373 (AST pretty-printing drops meaningful parentheses surrounding property access). (timwolla) + . Fixed GH-22422 (zend_arena layout mismatch leaked memory in separately + built extensions under AddressSanitizer). (iliaal) - BCMath: . Added NUL-byte validation to BCMath functions. (jorgsowa) diff --git a/configure.ac b/configure.ac index b61b909b67b7..9014869fb94e 100644 --- a/configure.ac +++ b/configure.ac @@ -1539,8 +1539,10 @@ AS_VAR_IF([PHP_ADDRESS_SANITIZER], [yes], ]))]) AX_CHECK_COMPILE_FLAG([-fsanitize=address], [ - CFLAGS="$CFLAGS -fsanitize=address -DZEND_TRACK_ARENA_ALLOC" - CXXFLAGS="$CXXFLAGS -fsanitize=address -DZEND_TRACK_ARENA_ALLOC" + CFLAGS="$CFLAGS -fsanitize=address" + CXXFLAGS="$CXXFLAGS -fsanitize=address" + AC_DEFINE([ZEND_TRACK_ARENA_ALLOC], [1], + [Whether to track arena allocations individually for AddressSanitizer.]) ], [AC_MSG_ERROR([AddressSanitizer is not available])]) ]) From 06037f8b7b9981bf1c49a165a4cbb4e23c20a18e Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sun, 21 Jun 2026 08:12:42 -0400 Subject: [PATCH 2/4] Fix invalid Firebird isolation level proceeding with the connection pdo_firebird_handle_factory() raised a ValueError for an out-of-range TRANSACTION_ISOLATION_LEVEL but only set ret = 0; zend_value_error() queues the exception without aborting, so control fell through into the isc_attach_database() block, opened the connection and overwrote ret with 1. The constructor then returned success with a pending ValueError and a live handle whose isolation level was never selected. Break out of the attach block when an exception is pending and skip the trailing fb_interpret() error so the ValueError is the sole result; the existing !ret cleanup closes the unused handle. Closes GH-22430 --- ext/pdo_firebird/firebird_driver.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index c104e8f5517d..e45a9108f726 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -1410,6 +1410,10 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* char const *dpb_values[] = { dbh->username, dbh->password, vars[1].optval, vars[2].optval }; char dpb_buffer[256] = { isc_dpb_version1 }, *dpb; + if (EG(exception)) { + break; + } + dpb = dpb_buffer + 1; /* loop through all the provided arguments and set dpb fields accordingly */ @@ -1446,7 +1450,7 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* } } - if (!dbh->methods) { + if (!dbh->methods && !EG(exception)) { char errmsg[512]; const ISC_STATUS *s = H->isc_status; fb_interpret(errmsg, sizeof(errmsg),&s); From c94681937f473fe8f8157b4f72ef2ffaacc11619 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sun, 21 Jun 2026 08:07:22 -0400 Subject: [PATCH 3/4] Fix signed dbconvert() return stored into size_t in dblib lastInsertId dblib_handle_last_id() stored the DBINT return of dbconvert() into a size_t len. dbconvert() returns -1 on conversion failure, which sign-extends to SIZE_MAX and is passed as the length to zend_string_init(), reading far past the 40-byte buffer and requesting a SIZE_MAX allocation. Hold the result in a DBINT and bail on a negative return, matching the failure-returns-NULL handling already used for dbresults()/dbnextrow()/dbdatlen() earlier in the function. Closes GH-22428 --- ext/pdo_dblib/dblib_driver.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c index d1d849168bab..f81e9e7397f3 100644 --- a/ext/pdo_dblib/dblib_driver.c +++ b/ext/pdo_dblib/dblib_driver.c @@ -234,7 +234,7 @@ zend_string *dblib_handle_last_id(pdo_dbh_t *dbh, const zend_string *name) RETCODE ret; char *id = NULL; - size_t len; + DBINT len; zend_string *ret_id; /* @@ -271,6 +271,11 @@ zend_string *dblib_handle_last_id(pdo_dbh_t *dbh, const zend_string *name) len = dbconvert(NULL, (dbcoltype(H->link, 1)) , (dbdata(H->link, 1)) , (dbdatlen(H->link, 1)), SQLCHAR, (BYTE *)id, (DBINT)40); dbcancel(H->link); + if (len < 0) { + efree(id); + return NULL; + } + ret_id = zend_string_init(id, len, 0); efree(id); return ret_id; From be55be0a4db5cc681b5ec0544fc602706a3b697e Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 24 Jun 2026 07:34:59 -0400 Subject: [PATCH 4/4] Fix posix_getgrnam()/posix_getgrgid() crash on NULL group name php_posix_group_to_array() passed gr_name straight to add_assoc_string() with no NULL guard, so a NULL group name segfaults via zend_string_init(), while the sibling gr_passwd field right below is already guarded. glibc's files NSS backend normalizes empty fields to "", but third-party NSS modules (nss-systemd, nss-ldap, sssd and other directory backends) populate struct group directly and may leave gr_name NULL. Guard it and emit null instead, matching the existing gr_passwd handling. Closes GH-22433 --- ext/posix/posix.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ext/posix/posix.c b/ext/posix/posix.c index 38f7eaa41860..b659207f67b6 100644 --- a/ext/posix/posix.c +++ b/ext/posix/posix.c @@ -669,7 +669,11 @@ int php_posix_group_to_array(struct group *g, zval *array_group) /* {{{ */ array_init(&array_members); - add_assoc_string(array_group, "name", g->gr_name); + if (g->gr_name) { + add_assoc_string(array_group, "name", g->gr_name); + } else { + add_assoc_null(array_group, "name"); + } if (g->gr_passwd) { add_assoc_string(array_group, "passwd", g->gr_passwd); } else {