From 614b22ab465718a57b15736fc9c7b28ffee3c807 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Sun, 15 Mar 2026 00:30:00 +0100 Subject: [PATCH 1/5] Add array size maximum to array_diff() This silences some reports about the equivalence to array_merge()'s issue. However, this is different as no packed fill is used in this code, so it doesn't have the same bug that array_merge() had. Closes GH-21449. --- NEWS | 1 + ext/standard/array.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index ca6b431d70cd..509e5398563e 100644 --- a/NEWS +++ b/NEWS @@ -134,6 +134,7 @@ PHP NEWS null destination). (David Carlier) . Fixed bug GH-13204 (glob() fails if square bracket is in current directory). (ndossche) + . Add array size maximum to array_diff(). (ndossche) - Streams: . Added so_keepalive, tcp_keepidle, tcp_keepintvl and tcp_keepcnt stream diff --git a/ext/standard/array.c b/ext/standard/array.c index 640d832dd1d2..3ee5afa70f8f 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -5741,7 +5741,7 @@ PHP_FUNCTION(array_diff) { zval *args; uint32_t argc, i; - uint32_t num; + uint64_t num; HashTable exclude; zval *value; zend_string *str, *tmp_str, *key; @@ -5831,6 +5831,11 @@ PHP_FUNCTION(array_diff) return; } + if (UNEXPECTED(num >= HT_MAX_SIZE)) { + zend_throw_error(NULL, "The total number of elements must be lower than %u", HT_MAX_SIZE); + RETURN_THROWS(); + } + ZVAL_NULL(&dummy); /* create exclude map */ zend_hash_init(&exclude, num, NULL, NULL, 0); From f92d54b6b527ea730583af5a2cf9e506eca7ed0d Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Fri, 6 Mar 2026 17:59:36 +0100 Subject: [PATCH 2/5] openssl: Fix missing error propagation for BIO_printf() calls Since these go through a file, this can fail. For some of these, the error is already checked but not propagated to userland, causing a "true" return value but an incomplete file. For others, the error is not checked and can also lead to an incomplete file. Solve this by always propagating failure, especially as the other write calls are already checked for failure. Closes GH-21360. --- NEWS | 1 + ext/openssl/openssl.c | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index a5605382424a..c94a84b19118 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,7 @@ PHP NEWS - OpenSSL: . Fixed bug GH-21083 (Skip private_key_bits validation for EC/curve-based keys). (iliaal) + . Fix missing error propagation for BIO_printf() calls. (ndossche) - PCRE: . Fixed re-entrancy issue on php_pcre_match_impl, php_pcre_replace_impl, diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 7e2b95683256..1c1073345a16 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -5900,16 +5900,21 @@ PHP_FUNCTION(openssl_pkcs7_encrypt) /* tack on extra headers */ if (zheaders) { ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zheaders), strindex, zcertval) { + int ret; zend_string *str = zval_try_get_string(zcertval); if (UNEXPECTED(!str)) { goto clean_exit; } if (strindex) { - BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str)); + ret = BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str)); } else { - BIO_printf(outfile, "%s\n", ZSTR_VAL(str)); + ret = BIO_printf(outfile, "%s\n", ZSTR_VAL(str)); } zend_string_release(str); + if (ret < 0) { + php_openssl_store_errors(); + goto clean_exit; + } } ZEND_HASH_FOREACH_END(); } @@ -6128,6 +6133,7 @@ PHP_FUNCTION(openssl_pkcs7_sign) zend_string_release(str); if (ret < 0) { php_openssl_store_errors(); + goto clean_exit; } } ZEND_HASH_FOREACH_END(); } @@ -6518,16 +6524,21 @@ PHP_FUNCTION(openssl_cms_encrypt) /* tack on extra headers */ if (zheaders && encoding == ENCODING_SMIME) { ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zheaders), strindex, zcertval) { + int ret; zend_string *str = zval_try_get_string(zcertval); if (UNEXPECTED(!str)) { goto clean_exit; } if (strindex) { - BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str)); + ret = BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str)); } else { - BIO_printf(outfile, "%s\n", ZSTR_VAL(str)); + ret = BIO_printf(outfile, "%s\n", ZSTR_VAL(str)); } zend_string_release(str); + if (ret < 0) { + php_openssl_store_errors(); + goto clean_exit; + } } ZEND_HASH_FOREACH_END(); } @@ -6807,6 +6818,7 @@ PHP_FUNCTION(openssl_cms_sign) zend_string_release(str); if (ret < 0) { php_openssl_store_errors(); + goto clean_exit; } } ZEND_HASH_FOREACH_END(); } From d3727f44e77cd7b20be83a99a3316b21ebff7a9c Mon Sep 17 00:00:00 2001 From: Arshid Date: Sat, 21 Mar 2026 15:09:44 +0530 Subject: [PATCH 3/5] ext/pgsql: Remove unreachable break (#21482) --- ext/pgsql/pgsql.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index f50bc680c4b9..2cef31c28710 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -1814,18 +1814,14 @@ static void php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_typ switch (entry_type) { case PHP_PG_FIELD_NAME: RETURN_STRING(PQfname(pgsql_result, (int)field)); - break; case PHP_PG_FIELD_SIZE: RETURN_LONG(PQfsize(pgsql_result, (int)field)); - break; case PHP_PG_FIELD_TYPE: RETURN_STR(get_field_name(pg_result->conn, PQftype(pgsql_result, (int)field))); - break; case PHP_PG_FIELD_TYPE_OID: oid = PQftype(pgsql_result, (int)field); PGSQL_RETURN_OID(oid); - break; EMPTY_SWITCH_DEFAULT_CASE() } } @@ -4545,8 +4541,8 @@ PHP_FUNCTION(pg_flush) } switch (ret) { - case 0: RETURN_TRUE; break; - case 1: RETURN_LONG(0); break; + case 0: RETURN_TRUE; + case 1: RETURN_LONG(0); default: RETURN_FALSE; } } From c524773a4f4f73d7c084ef827d3d3cea8c3dfa86 Mon Sep 17 00:00:00 2001 From: Arshid Date: Sat, 21 Mar 2026 16:54:04 +0530 Subject: [PATCH 4/5] ext/ftp: Remove unreachable break (#21481) --- ext/ftp/php_ftp.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c index 245d95bf1260..671281ee4729 100644 --- a/ext/ftp/php_ftp.c +++ b/ext/ftp/php_ftp.c @@ -1264,7 +1264,6 @@ PHP_FUNCTION(ftp_set_option) } ftp->timeout_sec = Z_LVAL_P(z_value); RETURN_TRUE; - break; case PHP_FTP_OPT_AUTOSEEK: if (Z_TYPE_P(z_value) != IS_TRUE && Z_TYPE_P(z_value) != IS_FALSE) { zend_argument_type_error(3, "must be of type bool for the FTP_AUTOSEEK option, %s given", zend_zval_value_name(z_value)); @@ -1272,7 +1271,6 @@ PHP_FUNCTION(ftp_set_option) } ftp->autoseek = Z_TYPE_P(z_value) == IS_TRUE ? 1 : 0; RETURN_TRUE; - break; case PHP_FTP_OPT_USEPASVADDRESS: if (Z_TYPE_P(z_value) != IS_TRUE && Z_TYPE_P(z_value) != IS_FALSE) { zend_argument_type_error(3, "must be of type bool for the FTP_USEPASVADDRESS option, %s given", zend_zval_value_name(z_value)); @@ -1280,11 +1278,9 @@ PHP_FUNCTION(ftp_set_option) } ftp->usepasvaddress = Z_TYPE_P(z_value) == IS_TRUE ? 1 : 0; RETURN_TRUE; - break; default: zend_argument_value_error(2, "must be one of FTP_TIMEOUT_SEC, FTP_AUTOSEEK, or FTP_USEPASVADDRESS"); RETURN_THROWS(); - break; } } /* }}} */ @@ -1304,13 +1300,10 @@ PHP_FUNCTION(ftp_get_option) switch (option) { case PHP_FTP_OPT_TIMEOUT_SEC: RETURN_LONG(ftp->timeout_sec); - break; case PHP_FTP_OPT_AUTOSEEK: RETURN_BOOL(ftp->autoseek); - break; case PHP_FTP_OPT_USEPASVADDRESS: RETURN_BOOL(ftp->usepasvaddress); - break; default: zend_argument_value_error(2, "must be one of FTP_TIMEOUT_SEC, FTP_AUTOSEEK, or FTP_USEPASVADDRESS"); RETURN_THROWS(); From d8560ad17764f657322f5db01505f81821cef14d Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Fri, 20 Mar 2026 16:39:26 +0100 Subject: [PATCH 5/5] use lexbor version from library --- ext/lexbor/config.m4 | 1 - ext/lexbor/config.w32 | 1 - ext/lexbor/php_lexbor.c | 3 ++- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/lexbor/config.m4 b/ext/lexbor/config.m4 index 3e67c10fdfc3..ee136881c5be 100644 --- a/ext/lexbor/config.m4 +++ b/ext/lexbor/config.m4 @@ -2,7 +2,6 @@ PHP_LEXBOR_CFLAGS="-I@ext_srcdir@/" LEXBOR_DIR="lexbor" AC_DEFINE([HAVE_LEXBOR], [1], [Define to 1 if the PHP extension 'lexbor' is available.]) -AC_DEFINE([LEXBOR_VERSION], ["2.5.0"], [Define the main Lexbor version]) PHP_NEW_EXTENSION([lexbor], m4_normalize([ php_lexbor.c diff --git a/ext/lexbor/config.w32 b/ext/lexbor/config.w32 index bd1f3b383a7e..900cc91e9dd4 100644 --- a/ext/lexbor/config.w32 +++ b/ext/lexbor/config.w32 @@ -24,6 +24,5 @@ ADD_SOURCES("ext/lexbor/lexbor/url", "url.c","lexbor"); ADD_FLAG("CFLAGS_LEXBOR", "/D LEXBOR_BUILDING /utf-8"); AC_DEFINE("HAVE_LEXBOR", 1, "Define to 1 if the PHP extension 'lexbor' is available."); -AC_DEFINE("LEXBOR_VERSION", "2.5.0", "Define the main Lexbor version") PHP_INSTALL_HEADERS("ext/lexbor", "php_lexbor.h lexbor/"); diff --git a/ext/lexbor/php_lexbor.c b/ext/lexbor/php_lexbor.c index 7f847bfb0afe..af61f90291df 100644 --- a/ext/lexbor/php_lexbor.c +++ b/ext/lexbor/php_lexbor.c @@ -22,6 +22,7 @@ #include "php.h" #include "zend_globals.h" #include "ext/standard/info.h" +#include "lexbor/core/base.h" #include "lexbor/core/types.h" #include "lexbor/core/lexbor.h" @@ -53,7 +54,7 @@ static PHP_MINFO_FUNCTION(lexbor) { php_info_print_table_start(); php_info_print_table_row(2, "Lexbor support", "active"); - php_info_print_table_row(2, "Lexbor version", LEXBOR_VERSION); + php_info_print_table_row(2, "Lexbor version", LEXBOR_VERSION_STRING); php_info_print_table_end(); }