From 387b1c62bfbe5e14647620f132a00880ccfcf0c6 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Wed, 19 Jun 2024 00:05:24 +0100 Subject: [PATCH 01/57] PHP-8.3 is now for PHP-8.3.10-dev --- NEWS | 6 +++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 8395fff08256b..c0bd086f9500e 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.3.9 +?? ??? ????, PHP 8.3.10 + + + +20 Jun 2024, PHP 8.3.9 - Core: . Fixed bug GH-14315 (Incompatible pointer type warnings). (Peter Kokot) diff --git a/Zend/zend.h b/Zend/zend.h index 1727b91b19318..7b375c58067fd 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.3.9-dev" +#define ZEND_VERSION "4.3.10-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 6a23c1424ebca..0f9526cc0a52f 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.3.9-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.3.10-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 1ba99e780ae96..afe90c887c4e2 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 3 -#define PHP_RELEASE_VERSION 9 +#define PHP_RELEASE_VERSION 10 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.3.9-dev" -#define PHP_VERSION_ID 80309 +#define PHP_VERSION "8.3.10-dev" +#define PHP_VERSION_ID 80310 From 6704c605894e6bd62cc4605417aef066fd5a83c8 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 19 Jun 2024 20:45:05 +0100 Subject: [PATCH 02/57] Fix GH-14596: phpdbg with asan and ZC_RC_DEBUG set crashes. close GH-14607 --- NEWS | 4 ++++ sapi/phpdbg/phpdbg.c | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index e2744458f9411..061a9e9483ac0 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.22 +- PHPDBG: + . Fixed bug GH-14596 (crashes with ASAN and ZEND_RC_DEBUG=1). + (David Carlier) + 04 Jul 2024, PHP 8.2.21 diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index d4ffcdf473df8..3aa0b7b60d7e9 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -229,13 +229,13 @@ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ if (zend_vm_kind() != ZEND_VM_KIND_HYBRID) { /* phpdbg cannot work JIT-ed code */ - zend_string *key = zend_string_init(ZEND_STRL("opcache.jit"), 1); - zend_string *value = zend_string_init(ZEND_STRL("off"), 1); + zend_string *key = zend_string_init(ZEND_STRL("opcache.jit"), false); + zend_string *value = zend_string_init(ZEND_STRL("off"), false); - zend_alter_ini_entry(key, value, ZEND_INI_SYSTEM, ZEND_INI_STAGE_STARTUP); + zend_alter_ini_entry_ex(key, value, ZEND_INI_SYSTEM, ZEND_INI_STAGE_STARTUP, false); - zend_string_release(key); - zend_string_release(value); + zend_string_release_ex(key, false); + zend_string_release_ex(value, false); } return SUCCESS; From 686afc10bfe2fad59c8b552f60d34441e7e67d18 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 20 Jun 2024 05:57:05 +0100 Subject: [PATCH 03/57] Fix GH-14603: invalid null zip file entry. close GH-14610 --- NEWS | 4 ++++ ext/phar/tests/gh14603.phpt | Bin 0 -> 1198 bytes ext/phar/zip.c | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 ext/phar/tests/gh14603.phpt diff --git a/NEWS b/NEWS index 061a9e9483ac0..e91dee30c4f9f 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.22 +- Phar: + . Fixed bug GH-14603 (null string from zip entry). + (David Carlier) + - PHPDBG: . Fixed bug GH-14596 (crashes with ASAN and ZEND_RC_DEBUG=1). (David Carlier) diff --git a/ext/phar/tests/gh14603.phpt b/ext/phar/tests/gh14603.phpt new file mode 100644 index 0000000000000000000000000000000000000000..95b9fa30fd559aec191c29817d3f99b65f03406c GIT binary patch literal 1198 zcma)6OHUL*5FSK`OaccmUi45*mSiR{i?0}E1wvqemB)^-2^uv^?`-c*>!xSy?&0Bv zgO7v1!Gpg*FCH}UCwL<90r7?mn1w+Fa7iMVDp;elci2We-BV>V1ck%}l5K&A}iK!hOMwlx|u3&tm)O6rn2 zxzvqS!DdoYWoOE_GUSfqfS@W793%C5&+A}|fm`wzU}&MK`FhM!;gc zLbvphalw;%ePsU#4%(!Jzutj>s2~LUwnp)`0ve|`$WR9wW)BU*2r|^2s8O{2wpl8nkHhci8N|^#(BzlZIKiCLY?*Nl{Gt4N>+l_HQ!$g|2QL)`j1F3|dRm zpS~NuH(i{?r(j6xt_3PYB*uX93Pe>1C|82ip~3_WRD>Z^NLm3M KJ0wkA*yc~?K^XV| literal 0 HcmV?d00001 diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 1472906c8b9da..b610104acadeb 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -771,7 +771,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia } } - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), actual_alias, mydata->alias_len, mydata); + zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, mydata); mydata->alias = pestrndup(alias, alias_len, mydata->is_persistent); mydata->alias_len = alias_len; } else { From 3fbca7fb6a09c871d3b25b006fb31a116bb2af3b Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 24 Jun 2024 19:52:55 +0200 Subject: [PATCH 04/57] Support sysconf(_SC_GETPW_R_SIZE_MAX) == -1 (#13922) --- ext/standard/filestat.c | 36 ++++++++++++++++++++++++++++++------ main/fopen_wrappers.c | 34 +++++++++++++++++++++++----------- main/main.c | 17 +++++++++++++++-- 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c index aaf7e730d0a54..28643c73d5f92 100644 --- a/ext/standard/filestat.c +++ b/ext/standard/filestat.c @@ -313,13 +313,25 @@ PHPAPI int php_get_gid_by_name(const char *name, gid_t *gid) struct group *retgrptr; long grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX); char *grbuf; + int err; if (grbuflen < 1) { - return FAILURE; + grbuflen = 1024; } - +# if ZEND_DEBUG + /* Test retry logic */ + grbuflen = 1; +# endif grbuf = emalloc(grbuflen); - if (getgrnam_r(name, &gr, grbuf, grbuflen, &retgrptr) != 0 || retgrptr == NULL) { + +try_again: + err = getgrnam_r(name, &gr, grbuf, grbuflen, &retgrptr); + if (err != 0 || retgrptr == NULL) { + if (err == ERANGE) { + grbuflen *= 2; + grbuf = erealloc(grbuf, grbuflen); + goto try_again; + } efree(grbuf); return FAILURE; } @@ -439,13 +451,25 @@ PHPAPI uid_t php_get_uid_by_name(const char *name, uid_t *uid) struct passwd *retpwptr = NULL; long pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); char *pwbuf; + int err; if (pwbuflen < 1) { - return FAILURE; + pwbuflen = 1024; } - +# if ZEND_DEBUG + /* Test retry logic */ + pwbuflen = 1; +# endif pwbuf = emalloc(pwbuflen); - if (getpwnam_r(name, &pw, pwbuf, pwbuflen, &retpwptr) != 0 || retpwptr == NULL) { + +try_again: + err = getpwnam_r(name, &pw, pwbuf, pwbuflen, &retpwptr); + if (err != 0 || retpwptr == NULL) { + if (err == EAGAIN) { + pwbuflen *= 2; + pwbuf = erealloc(pwbuf, pwbuflen); + goto try_again; + } efree(pwbuf); return FAILURE; } diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c index efb110171b148..ad59b2b85bf11 100644 --- a/main/fopen_wrappers.c +++ b/main/fopen_wrappers.c @@ -362,26 +362,38 @@ PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle) if (s) { /* if there is no path name after the file, do not bother */ char user[32]; /* to try open the directory */ + + length = s - (path_info + 2); + if (length > sizeof(user) - 1) { + length = sizeof(user) - 1; + } + memcpy(user, path_info + 2, length); + user[length] = '\0'; + struct passwd *pw; #if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX) struct passwd pwstruc; long pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); char *pwbuf; + int err; if (pwbuflen < 1) { - return FAILURE; + pwbuflen = 1024; } - +# if ZEND_DEBUG + /* Test retry logic */ + pwbuflen = 1; +# endif pwbuf = emalloc(pwbuflen); -#endif - length = s - (path_info + 2); - if (length > sizeof(user) - 1) { - length = sizeof(user) - 1; - } - memcpy(user, path_info + 2, length); - user[length] = '\0'; -#if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX) - if (getpwnam_r(user, &pwstruc, pwbuf, pwbuflen, &pw)) { + +try_again: + err = getpwnam_r(user, &pwstruc, pwbuf, pwbuflen, &pw); + if (err) { + if (err == ERANGE) { + pwbuflen *= 2; + pwbuf = erealloc(pwbuf, pwbuflen); + goto try_again; + } efree(pwbuf); return FAILURE; } diff --git a/main/main.c b/main/main.c index 634b00936bc3e..0adecd10ffcca 100644 --- a/main/main.c +++ b/main/main.c @@ -1460,12 +1460,25 @@ PHPAPI char *php_get_current_user(void) struct passwd *retpwptr = NULL; int pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); char *pwbuf; + int err; if (pwbuflen < 1) { - return ""; + pwbuflen = 1024; } +# if ZEND_DEBUG + /* Test retry logic */ + pwbuflen = 1; +# endif pwbuf = emalloc(pwbuflen); - if (getpwuid_r(pstat->st_uid, &_pw, pwbuf, pwbuflen, &retpwptr) != 0) { + +try_again: + err = getpwuid_r(pstat->st_uid, &_pw, pwbuf, pwbuflen, &retpwptr); + if (err != 0) { + if (err == ERANGE) { + pwbuflen *= 2; + pwbuf = erealloc(pwbuf, pwbuflen); + goto try_again; + } efree(pwbuf); return ""; } From d7ef2c209abebcb3f516f9efe8ae0d0597971a5b Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 24 Jun 2024 19:55:47 +0200 Subject: [PATCH 05/57] [ci skip] NEWS for GH-13922 --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index e91dee30c4f9f..0f07ff0411e76 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,8 @@ PHP NEWS calls destructor). (Girgias) . Fixed bug GH-14549 (Incompatible function pointer type for fclose). (Ryan Carsten Schmidt) + . Fixed bug GH-13922 (Fixed support for systems with + sysconf(_SC_GETPW_R_SIZE_MAX) == -1). (Arnaud) - BCMatch: . Fixed bug (bcpowmod() with mod = -1 returns 1 when it must be 0). (Girgias) From e230610c761e9253a03d62501317b9d008f70e73 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 24 Jun 2024 19:57:00 +0200 Subject: [PATCH 06/57] [ci skip] NEWS for GH-13922 --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 75172950bbe4f..280c55118badf 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,8 @@ PHP NEWS (Florian Engelhardt) . Fixed bug GH-14549 (Incompatible function pointer type for fclose). (Ryan Carsten Schmidt) + . Fixed bug GH-13922 (Fixed support for systems with + sysconf(_SC_GETPW_R_SIZE_MAX) == -1). (Arnaud) - BCMatch: . Fixed bug (bcpowmod() with mod = -1 returns 1 when it must be 0). (Girgias) From 1ff277dee288bcd52cd5900286ac171cea0a94cf Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 25 Jun 2024 15:14:00 +0200 Subject: [PATCH 07/57] Fix is_zend_ptr() for huge blocks (#14626) is_zend_ptr() expected zend_mm_heap.huge_list to be circular, but it's in fact NULL-terminated. It could crash when at least one huge block exists and the ptr did not belong to any block. --- Zend/tests/gh14626.phpt | 18 ++++++++++++++++++ Zend/zend_alloc.c | 18 ++++++++---------- ext/ffi/tests/gh14626.phpt | 32 ++++++++++++++++++++++++++++++++ ext/zend_test/test.c | 11 +++++++++++ ext/zend_test/test.stub.php | 2 ++ ext/zend_test/test_arginfo.h | 8 +++++++- 6 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 Zend/tests/gh14626.phpt create mode 100644 ext/ffi/tests/gh14626.phpt diff --git a/Zend/tests/gh14626.phpt b/Zend/tests/gh14626.phpt new file mode 100644 index 0000000000000..c0c029fcd8474 --- /dev/null +++ b/Zend/tests/gh14626.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-14626: is_zend_ptr() may crash for non-zend ptrs when huge blocks exist +--EXTENSIONS-- +zend_test +--FILE-- + +==DONE== +--EXPECT-- +==DONE== diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 0952a88a41194..e86f2961cfac9 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2455,17 +2455,15 @@ ZEND_API bool is_zend_ptr(const void *ptr) } while (chunk != AG(mm_heap)->main_chunk); } - if (AG(mm_heap)->huge_list) { - zend_mm_huge_list *block = AG(mm_heap)->huge_list; - - do { - if (ptr >= (void*)block - && ptr < (void*)((char*)block + block->size)) { - return 1; - } - block = block->next; - } while (block != AG(mm_heap)->huge_list); + zend_mm_huge_list *block = AG(mm_heap)->huge_list; + while (block) { + if (ptr >= (void*)block + && ptr < (void*)((char*)block + block->size)) { + return 1; + } + block = block->next; } + return 0; } diff --git a/ext/ffi/tests/gh14626.phpt b/ext/ffi/tests/gh14626.phpt new file mode 100644 index 0000000000000..f69122e288917 --- /dev/null +++ b/ext/ffi/tests/gh14626.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-14626: FFI::free() may crash in is_zend_ptr() when at least one huge block exists and the ptr is non-zend +--EXTENSIONS-- +ffi +--SKIPIF-- + +--INI-- +ffi.enable=1 +--FILE-- +malloc(10); +$addr = $ffi->cast("uintptr_t", $ffi->cast("char*", $ptr))->cdata; + +$ptr = FFI::cdef()->cast("char*", $addr); + +// Should not crash in is_zend_ptr() +FFI::free($ptr); + +?> +==DONE== +--EXPECT-- +==DONE== diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 8ab8a06107eb1..2df6c2027498a 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -628,6 +628,17 @@ static ZEND_FUNCTION(zend_test_cast_fread) } } +static ZEND_FUNCTION(zend_test_is_zend_ptr) +{ + zend_long addr; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(addr); + ZEND_PARSE_PARAMETERS_END(); + + RETURN_BOOL(is_zend_ptr((void*)addr)); +} + static zend_object *zend_test_class_new(zend_class_entry *class_type) { zend_object *obj = zend_objects_new(class_type); diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index e4439fe38c05f..7dc348934400f 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -189,6 +189,8 @@ function zend_test_set_fmode(bool $binary): void {} /** @param resource $stream */ function zend_test_cast_fread($stream): void {} + + function zend_test_is_zend_ptr(int $addr): bool {} } namespace ZendTestNS { diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index c07e3dca01bed..19ea9e7a2adf5 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 98cade449e4dcf038166adeee07b17308dd48725 */ + * Stub hash: 07ce28cd75080118509ac0d30d8ce5ef54110747 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -122,6 +122,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_cast_fread, 0, 1, IS_V ZEND_ARG_INFO(0, stream) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_is_zend_ptr, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, addr, IS_LONG, 0) +ZEND_END_ARG_INFO() + #define arginfo_ZendTestNS2_namespaced_func arginfo_zend_test_is_pcre_bundled #define arginfo_ZendTestNS2_namespaced_deprecated_func arginfo_zend_test_void_return @@ -230,6 +234,7 @@ static ZEND_FUNCTION(zend_test_is_pcre_bundled); static ZEND_FUNCTION(zend_test_set_fmode); #endif static ZEND_FUNCTION(zend_test_cast_fread); +static ZEND_FUNCTION(zend_test_is_zend_ptr); static ZEND_FUNCTION(ZendTestNS2_namespaced_func); static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func); static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func); @@ -293,6 +298,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(zend_test_set_fmode, arginfo_zend_test_set_fmode) #endif ZEND_FE(zend_test_cast_fread, arginfo_zend_test_cast_fread) + ZEND_FE(zend_test_is_zend_ptr, arginfo_zend_test_is_zend_ptr) ZEND_NS_FALIAS("ZendTestNS2", namespaced_func, ZendTestNS2_namespaced_func, arginfo_ZendTestNS2_namespaced_func) ZEND_NS_DEP_FALIAS("ZendTestNS2", namespaced_deprecated_func, ZendTestNS2_namespaced_deprecated_func, arginfo_ZendTestNS2_namespaced_deprecated_func) ZEND_NS_FALIAS("ZendTestNS2", namespaced_aliased_func, zend_test_void_return, arginfo_ZendTestNS2_namespaced_aliased_func) From a9acc29a37033d9b055a2890db381217f82b38a5 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 25 Jun 2024 15:15:17 +0200 Subject: [PATCH 08/57] [ci skip] NEWS for GH-14626 --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 0f07ff0411e76..34c8d2e873a11 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,7 @@ PHP NEWS (Ryan Carsten Schmidt) . Fixed bug GH-13922 (Fixed support for systems with sysconf(_SC_GETPW_R_SIZE_MAX) == -1). (Arnaud) + . Fixed bug GH-14626 (Fix is_zend_ptr() for huge blocks). (Arnaud) - BCMatch: . Fixed bug (bcpowmod() with mod = -1 returns 1 when it must be 0). (Girgias) From a5a75ae39d0024ef08a32e2054915c0f842e5c43 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 25 Jun 2024 15:17:24 +0200 Subject: [PATCH 09/57] [ci skip] NEWS for GH-14626 --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 280c55118badf..fdb45bc204e59 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,7 @@ PHP NEWS (Ryan Carsten Schmidt) . Fixed bug GH-13922 (Fixed support for systems with sysconf(_SC_GETPW_R_SIZE_MAX) == -1). (Arnaud) + . Fixed bug GH-14626 (Fix is_zend_ptr() for huge blocks). (Arnaud) - BCMatch: . Fixed bug (bcpowmod() with mod = -1 returns 1 when it must be 0). (Girgias) From 5a32b510eff57080b78e04a2b65a4748ec86c74c Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:31:21 -0700 Subject: [PATCH 10/57] Add SKIPIFs for upstream regression in libxslt (#14674) See https://gitlab.gnome.org/GNOME/libxslt/-/issues/113 --- ext/xsl/tests/skip_upstream_issue113.inc | 5 +++++ ext/xsl/tests/xslt010_gt10129.phpt | 1 + 2 files changed, 6 insertions(+) create mode 100644 ext/xsl/tests/skip_upstream_issue113.inc diff --git a/ext/xsl/tests/skip_upstream_issue113.inc b/ext/xsl/tests/skip_upstream_issue113.inc new file mode 100644 index 0000000000000..a08bc4f037c2f --- /dev/null +++ b/ext/xsl/tests/skip_upstream_issue113.inc @@ -0,0 +1,5 @@ +hasExsltSupport()) die('skip EXSLT support not available'); if (LIBXSLT_VERSION < 10130) die('skip too old libxsl'); +require __DIR__.'/skip_upstream_issue113.inc'; ?> --FILE-- Date: Fri, 28 Jun 2024 18:26:47 +0200 Subject: [PATCH 11/57] Fix GH-14537: shmop Windows 11 crashes the process The error handling code isn't entirely right in two places. One of the code blocks is dead because of an always-false condition, and another code block is missing the assignment of a NULL pointer. Getting the exact same behaviour is not entirely possible because you can't extend the size of a shared memory region after it was made with the Windows APIs we use, unless we destroy the region and recreate it, but that has other consequences. However, it certainly shouldn't crash. Closes GH-14707. --- NEWS | 2 ++ TSRM/tsrm_win32.c | 5 +++-- ext/shmop/tests/gh14537.phpt | 27 +++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 ext/shmop/tests/gh14537.phpt diff --git a/NEWS b/NEWS index 34c8d2e873a11..ac4460a55e062 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS . Fixed bug GH-14596 (crashes with ASAN and ZEND_RC_DEBUG=1). (David Carlier) +- Shmop: + . Fixed bug GH-14537 (shmop Windows 11 crashes the process). (nielsdos) 04 Jul 2024, PHP 8.2.21 diff --git a/TSRM/tsrm_win32.c b/TSRM/tsrm_win32.c index dc8f9fefa3ab1..0af03b6ed8985 100644 --- a/TSRM/tsrm_win32.c +++ b/TSRM/tsrm_win32.c @@ -709,6 +709,7 @@ TSRM_API int shmget(key_t key, size_t size, int flags) CloseHandle(shm->segment); } UnmapViewOfFile(shm->descriptor); + shm->descriptor = NULL; return -1; } @@ -744,8 +745,8 @@ TSRM_API int shmdt(const void *shmaddr) shm->descriptor->shm_lpid = getpid(); shm->descriptor->shm_nattch--; - ret = 1; - if (!ret && shm->descriptor->shm_nattch <= 0) { + ret = 0; + if (shm->descriptor->shm_nattch <= 0) { ret = UnmapViewOfFile(shm->descriptor) ? 0 : -1; shm->descriptor = NULL; } diff --git a/ext/shmop/tests/gh14537.phpt b/ext/shmop/tests/gh14537.phpt new file mode 100644 index 0000000000000..05af26a70ffa9 --- /dev/null +++ b/ext/shmop/tests/gh14537.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-14537: shmop Windows 11 crashes the process +--EXTENSIONS-- +shmop +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +object(Shmop)#1 (0) { +} + +Warning: shmop_open(): Unable to attach or create shared memory segment "No error" in %s on line %d +bool(false) From 643762cd78991a191c13f68640aafe38fa20ad62 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 28 Jun 2024 20:16:19 +0200 Subject: [PATCH 12/57] [ci skip] Move incorrectly placed NEWS items to the right place --- NEWS | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index ac4460a55e062..5fbbf9073398f 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,11 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.22 +- Core: + . Fixed bug GH-13922 (Fixed support for systems with + sysconf(_SC_GETPW_R_SIZE_MAX) == -1). (Arnaud) + . Fixed bug GH-14626 (Fix is_zend_ptr() for huge blocks). (Arnaud) + - Phar: . Fixed bug GH-14603 (null string from zip entry). (David Carlier) @@ -25,9 +30,6 @@ PHP NEWS calls destructor). (Girgias) . Fixed bug GH-14549 (Incompatible function pointer type for fclose). (Ryan Carsten Schmidt) - . Fixed bug GH-13922 (Fixed support for systems with - sysconf(_SC_GETPW_R_SIZE_MAX) == -1). (Arnaud) - . Fixed bug GH-14626 (Fix is_zend_ptr() for huge blocks). (Arnaud) - BCMatch: . Fixed bug (bcpowmod() with mod = -1 returns 1 when it must be 0). (Girgias) From 056bec72f434008960c3375ac13223b622d73305 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 28 Jun 2024 21:09:17 +0200 Subject: [PATCH 13/57] Fix GH-14590: Memory leak in FPM test gh13563-conf-bool-env.phpt Values retrieved from zend_getenv should be freed. Note: The only possible value for `zend_getenv` is `sapi_getenv` which uses zend alloc to duplicate the string that it reads from the SAPI module. Closes GH-14708. --- NEWS | 2 ++ Zend/zend_ini_parser.y | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 5fbbf9073398f..37f76cef3db4e 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ PHP NEWS . Fixed bug GH-13922 (Fixed support for systems with sysconf(_SC_GETPW_R_SIZE_MAX) == -1). (Arnaud) . Fixed bug GH-14626 (Fix is_zend_ptr() for huge blocks). (Arnaud) + . Fixed bug GH-14590 (Memory leak in FPM test gh13563-conf-bool-env.phpt. + (nielsdos) - Phar: . Fixed bug GH-14603 (null string from zip entry). diff --git a/Zend/zend_ini_parser.y b/Zend/zend_ini_parser.y index 2d4e949d5c475..7ade9792ccec5 100644 --- a/Zend/zend_ini_parser.y +++ b/Zend/zend_ini_parser.y @@ -173,8 +173,10 @@ static void zend_ini_get_var(zval *result, zval *name) if ((curval = zend_get_configuration_directive(Z_STR_P(name))) != NULL) { ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(curval), Z_STRLEN_P(curval), ZEND_SYSTEM_INI)); /* ..or if not found, try ENV */ - } else if ((envvar = zend_getenv(Z_STRVAL_P(name), Z_STRLEN_P(name))) != NULL || - (envvar = getenv(Z_STRVAL_P(name))) != NULL) { + } else if ((envvar = zend_getenv(Z_STRVAL_P(name), Z_STRLEN_P(name))) != NULL) { + ZVAL_NEW_STR(result, zend_string_init(envvar, strlen(envvar), ZEND_SYSTEM_INI)); + efree(envvar); + } else if ((envvar = getenv(Z_STRVAL_P(name))) != NULL) { ZVAL_NEW_STR(result, zend_string_init(envvar, strlen(envvar), ZEND_SYSTEM_INI)); } else { zend_ini_init_string(result); From 42908f9f68e824c9e7bc1b1ce8662adc94a0661a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 28 Jun 2024 17:51:31 +0200 Subject: [PATCH 14/57] Fix GH-14702: DOMDocument::xinclude() crash The xinclude code from libxml removes the fallback node, but the fallback node is still reference via $fallback. The solution is to detach the nodes that are going to be removed in advance. Closes GH-14704. --- NEWS | 3 ++ ext/dom/document.c | 54 +++++++++++++++++++++++++++++++ ext/dom/tests/gh14702.phpt | 66 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 ext/dom/tests/gh14702.phpt diff --git a/NEWS b/NEWS index 37f76cef3db4e..5623652830db7 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,9 @@ PHP NEWS . Fixed bug GH-14590 (Memory leak in FPM test gh13563-conf-bool-env.phpt. (nielsdos) +- Dom: + . Fixed bug GH-14702 (DOMDocument::xinclude() crash). (nielsdos) + - Phar: . Fixed bug GH-14603 (null string from zip entry). (David Carlier) diff --git a/ext/dom/document.c b/ext/dom/document.c index a2772479cfe8e..38af4ca27c820 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -1566,6 +1566,58 @@ static void php_dom_remove_xinclude_nodes(xmlNodePtr cur) /* {{{ */ } /* }}} */ +/* Backported from master branch xml_common.h */ +static zend_always_inline xmlNodePtr php_dom_next_in_tree_order(const xmlNode *nodep, const xmlNode *basep) +{ + if (nodep->type == XML_ELEMENT_NODE && nodep->children) { + return nodep->children; + } + + if (nodep->next) { + return nodep->next; + } else { + /* Go upwards, until we find a parent node with a next sibling, or until we hit the base. */ + do { + nodep = nodep->parent; + if (nodep == basep) { + return NULL; + } + } while (nodep->next == NULL); + return nodep->next; + } +} + +static void dom_xinclude_strip_references(xmlNodePtr basep) +{ + php_libxml_node_free_resource(basep); + + xmlNodePtr current = basep->children; + + while (current) { + php_libxml_node_free_resource(current); + current = php_dom_next_in_tree_order(current, basep); + } +} + +/* See GH-14702. + * We have to remove userland references to xinclude fallback nodes because libxml2 will make clones of these + * and remove the original nodes. If the originals are removed while there are still userland references + * this will cause memory corruption. */ +static void dom_xinclude_strip_fallback_references(const xmlNode *basep) +{ + xmlNodePtr current = basep->children; + + while (current) { + if (current->type == XML_ELEMENT_NODE && current->ns != NULL && current->_private != NULL + && xmlStrEqual(current->name, XINCLUDE_FALLBACK) + && (xmlStrEqual(current->ns->href, XINCLUDE_NS) || xmlStrEqual(current->ns->href, XINCLUDE_OLD_NS))) { + dom_xinclude_strip_references(current); + } + + current = php_dom_next_in_tree_order(current, basep); + } +} + /* {{{ Substitutues xincludes in a DomDocument */ PHP_METHOD(DOMDocument, xinclude) { @@ -1588,6 +1640,8 @@ PHP_METHOD(DOMDocument, xinclude) DOM_GET_OBJ(docp, id, xmlDocPtr, intern); + dom_xinclude_strip_fallback_references((const xmlNode *) docp); + PHP_LIBXML_SANITIZE_GLOBALS(xinclude); err = xmlXIncludeProcessFlags(docp, (int)flags); PHP_LIBXML_RESTORE_GLOBALS(xinclude); diff --git a/ext/dom/tests/gh14702.phpt b/ext/dom/tests/gh14702.phpt new file mode 100644 index 0000000000000..9811bb7883acb --- /dev/null +++ b/ext/dom/tests/gh14702.phpt @@ -0,0 +1,66 @@ +--TEST-- +GH-14702 (DOMDocument::xinclude() crash) +--EXTENSIONS-- +dom +--FILE-- +loadXML(<< + + + + + + + +XML); +$xi = $doc->createElementNS('http://www.w3.org/2001/XInclude', 'xi:include'); +$xi->setAttribute('href', 'nonexistent'); + +$fallback = $doc->createElementNS('http://www.w3.org/2001/XInclude', 'xi:fallback'); +$xi->appendChild($fallback); +$child1 = $fallback->appendChild($doc->createElement('fallback-child1')); +$child2 = $fallback->appendChild($doc->createElement('fallback-child2')); + +$xpath = new DOMXPath($doc); +$toReplace = $xpath->query('//child')->item(0); +$toReplace->parentNode->replaceChild($xi, $toReplace); + +$keep = $doc->documentElement->lastElementChild; + +var_dump(@$doc->xinclude()); +echo $doc->saveXML(); + +var_dump($child1, $child2, $fallback, $keep->nodeName); + +$keep->textContent = 'still works'; +echo $doc->saveXML(); +?> +--EXPECT-- +int(2) + + + + + + +object(DOMElement)#4 (1) { + ["schemaTypeInfo"]=> + NULL +} +object(DOMElement)#5 (1) { + ["schemaTypeInfo"]=> + NULL +} +object(DOMElement)#3 (1) { + ["schemaTypeInfo"]=> + NULL +} +string(4) "keep" + + + + + still works + From b08def5156474bbd5a96cc5d2cb72e98f09f03a0 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 29 Jun 2024 15:39:11 +0200 Subject: [PATCH 15/57] Fix GH-14563: Build failure with libxml2 v2.13.0 Remove xmlErrMemory from the export section for Windows, this fixes the build. Even though the original function was renamed [1] it is hidden, so removing this should be sufficient and not be a BC break. [1] https://github.com/GNOME/libxml2/commit/130436917c362d14f0eb3705a0edddc523a9640e Closes GH-14719. --- NEWS | 3 +++ ext/libxml/php_libxml2.def | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 5623652830db7..74b925bf11325 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,9 @@ PHP NEWS - Dom: . Fixed bug GH-14702 (DOMDocument::xinclude() crash). (nielsdos) +- LibXML: + . Fixed bug GH-14563 (Build failure with libxml2 v2.13.0). (nielsdos) + - Phar: . Fixed bug GH-14603 (null string from zip entry). (David Carlier) diff --git a/ext/libxml/php_libxml2.def b/ext/libxml/php_libxml2.def index 5980df8bf8891..06c05f188e8fb 100644 --- a/ext/libxml/php_libxml2.def +++ b/ext/libxml/php_libxml2.def @@ -345,7 +345,6 @@ xmlElemDump xmlEncodeEntities xmlEncodeEntitiesReentrant xmlEncodeSpecialChars -xmlErrMemory xmlFileClose xmlFileMatch xmlFileOpen From c03196a5be14cd4f1a9cf42d77791d892317a60d Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 29 Jun 2024 11:53:34 +0100 Subject: [PATCH 16/57] Fix GH-14712: segfault on invalid object. If the extension does not allow to get a property pointer (like PDORow object), we fallback to the read property cb anyway. --- NEWS | 4 ++++ Zend/zend_execute.c | 3 +++ ext/pdo/pdo_stmt.c | 12 +++++++++++- ext/pdo_sqlite/tests/gh14712.phpt | 18 ++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 ext/pdo_sqlite/tests/gh14712.phpt diff --git a/NEWS b/NEWS index 74b925bf11325..1ae1996bb4a19 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,10 @@ PHP NEWS - LibXML: . Fixed bug GH-14563 (Build failure with libxml2 v2.13.0). (nielsdos) +- PDO: + . Fixed bug GH-14712 (Crash with PDORow access to null property). + (David Carlier) + - Phar: . Fixed bug GH-14603 (null string from zip entry). (David Carlier) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 5a060540db015..3de48fb1358c5 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3127,6 +3127,9 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c } } + /* Pointer on property callback is required */ + ZEND_ASSERT(zobj->handlers->get_property_ptr_ptr != NULL); + if (prop_op_type == IS_CONST) { name = Z_STR_P(prop_ptr); } else { diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index e11d0f4288cfb..239b8d6a99bef 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2453,6 +2453,16 @@ static zend_function *row_get_ctor(zend_object *object) return NULL; } +static zval *pdo_row_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot) +{ + ZEND_IGNORE_VALUE(object); + ZEND_IGNORE_VALUE(name); + ZEND_IGNORE_VALUE(type); + ZEND_IGNORE_VALUE(cache_slot); + + return NULL; +} + void pdo_row_free_storage(zend_object *std) { pdo_row_t *row = (pdo_row_t *)std; @@ -2492,7 +2502,7 @@ void pdo_stmt_init(void) memcpy(&pdo_row_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); pdo_row_object_handlers.free_obj = pdo_row_free_storage; pdo_row_object_handlers.clone_obj = NULL; - pdo_row_object_handlers.get_property_ptr_ptr = NULL; + pdo_row_object_handlers.get_property_ptr_ptr = pdo_row_get_property_ptr_ptr; pdo_row_object_handlers.read_property = row_prop_read; pdo_row_object_handlers.write_property = row_prop_write; pdo_row_object_handlers.has_property = row_prop_exists; diff --git a/ext/pdo_sqlite/tests/gh14712.phpt b/ext/pdo_sqlite/tests/gh14712.phpt new file mode 100644 index 0000000000000..d565abacdcd11 --- /dev/null +++ b/ext/pdo_sqlite/tests/gh14712.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-14712: segfault on PDORow +--EXTENSIONS-- +pdo_sqlite +--CREDITS-- +YuanchengJiang +--FILE-- +query("select 1 as queryStringxx")->fetch(PDO::FETCH_LAZY)->documentElement->firstChild->nextElementSibling->textContent = "é"; +} catch (Error $e) { + echo $e->getMessage(); +} +?> +--EXPECT-- +Attempt to modify property "firstChild" on null From d568337680657c37a3db4f92fe4c883da3e06273 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 29 Jun 2024 14:16:54 +0200 Subject: [PATCH 17/57] Fix OSS-Fuzz #69765: Yield reference to nullsafe chain You cannot return or yield a reference to a nullsafe chain. This was checked already in zend_compile_return but not yet in zend_compile_yield. Closes GH-14716. --- NEWS | 1 + Zend/tests/oss-fuzz-69765.phpt | 10 ++++++++++ Zend/zend_compile.c | 4 ++++ 3 files changed, 15 insertions(+) create mode 100644 Zend/tests/oss-fuzz-69765.phpt diff --git a/NEWS b/NEWS index 1ae1996bb4a19..4182d5d7745c8 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,7 @@ PHP NEWS . Fixed bug GH-14626 (Fix is_zend_ptr() for huge blocks). (Arnaud) . Fixed bug GH-14590 (Memory leak in FPM test gh13563-conf-bool-env.phpt. (nielsdos) + . Fixed OSS-Fuzz #69765. (nielsdos) - Dom: . Fixed bug GH-14702 (DOMDocument::xinclude() crash). (nielsdos) diff --git a/Zend/tests/oss-fuzz-69765.phpt b/Zend/tests/oss-fuzz-69765.phpt new file mode 100644 index 0000000000000..011b1ea525269 --- /dev/null +++ b/Zend/tests/oss-fuzz-69765.phpt @@ -0,0 +1,10 @@ +--TEST-- +OSS-Fuzz #69765: yield reference to nullsafe chain +--FILE-- +y?->y; +} +?> +--EXPECTF-- +Fatal error: Cannot take reference of a nullsafe chain in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index e7f9ed8f000a2..502a29863a5d7 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -9329,6 +9329,10 @@ static void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */ if (value_ast) { if (returns_by_ref && zend_is_variable(value_ast)) { + if (zend_ast_is_short_circuited(value_ast)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain"); + } + zend_compile_var(&value_node, value_ast, BP_VAR_W, 1); } else { zend_compile_expr(&value_node, value_ast); From 8fd095669a4f1f2c4316ee95ccc7c0b5c53b37c3 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 29 Jun 2024 14:20:31 +0200 Subject: [PATCH 18/57] Factor out common check for short-circuited ast --- Zend/zend_compile.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 502a29863a5d7..8662e188aaafb 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2312,6 +2312,13 @@ static bool zend_ast_is_short_circuited(const zend_ast *ast) } } +static void zend_assert_not_short_circuited(const zend_ast *ast) +{ + if (zend_ast_is_short_circuited(ast)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain"); + } +} + /* Mark nodes that are an inner part of a short-circuiting chain. * We should not perform a "commit" on them, as it will be performed by the outer-most node. * We do this to avoid passing down an argument in various compile functions. */ @@ -3304,9 +3311,8 @@ static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */ if (!zend_is_variable_or_call(expr_ast)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot assign reference to non referenceable value"); - } else if (zend_ast_is_short_circuited(expr_ast)) { - zend_error_noreturn(E_COMPILE_ERROR, - "Cannot take reference of a nullsafe chain"); + } else { + zend_assert_not_short_circuited(expr_ast); } zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1); @@ -3348,9 +3354,7 @@ static void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */ zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this"); } zend_ensure_writable_variable(target_ast); - if (zend_ast_is_short_circuited(source_ast)) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain"); - } + zend_assert_not_short_circuited(source_ast); if (is_globals_fetch(source_ast)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot acquire reference to $GLOBALS"); } @@ -5026,10 +5030,7 @@ static void zend_compile_return(zend_ast *ast) /* {{{ */ expr_node.op_type = IS_CONST; ZVAL_NULL(&expr_node.u.constant); } else if (by_ref && zend_is_variable(expr_ast)) { - if (zend_ast_is_short_circuited(expr_ast)) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain"); - } - + zend_assert_not_short_circuited(expr_ast); zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1); } else { zend_compile_expr(&expr_node, expr_ast); @@ -9329,10 +9330,7 @@ static void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */ if (value_ast) { if (returns_by_ref && zend_is_variable(value_ast)) { - if (zend_ast_is_short_circuited(value_ast)) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain"); - } - + zend_assert_not_short_circuited(value_ast); zend_compile_var(&value_node, value_ast, BP_VAR_W, 1); } else { zend_compile_expr(&value_node, value_ast); From 98cb0be17d521afea16b1a92eed55e278c05ff36 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Mon, 1 Jul 2024 22:06:10 +0200 Subject: [PATCH 19/57] Use pattern tags for NDBM ext/dba/tests (#14755) --- ext/dba/tests/dba_ndbm.phpt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/dba/tests/dba_ndbm.phpt b/ext/dba/tests/dba_ndbm.phpt index 5c50370947e89..dcf368ff1a36f 100644 --- a/ext/dba/tests/dba_ndbm.phpt +++ b/ext/dba/tests/dba_ndbm.phpt @@ -26,11 +26,11 @@ cleanup_standard_db($db_name); --EXPECT-- === RUNNING WITH FILE LOCK === -Notice: dba_open(): Handler ndbm does locking internally in /home/girgias/Dev/php-src/ext/dba/tests/setup/setup_dba_tests.inc on line 40 +Notice: dba_open(): Handler ndbm does locking internally in %s on line %d -Notice: dba_open(): Handler ndbm does locking internally in /home/girgias/Dev/php-src/ext/dba/tests/setup/setup_dba_tests.inc on line 40 +Notice: dba_open(): Handler ndbm does locking internally in %s on line %d -Notice: dba_open(): Handler ndbm does locking internally in /home/girgias/Dev/php-src/ext/dba/tests/setup/setup_dba_tests.inc on line 82 +Notice: dba_open(): Handler ndbm does locking internally in %s on line %d Remove key 1 and 3 bool(true) bool(true) @@ -61,7 +61,7 @@ bool(true) Fetch "key2": Content 2 replaced 2nd time Fetch "key number 6": The 6th value -Notice: dba_open(): Handler ndbm does locking internally in /home/girgias/Dev/php-src/ext/dba/tests/setup/setup_dba_tests.inc on line 149 +Notice: dba_open(): Handler ndbm does locking internally in %s on line %d array(6) { ["[key10]name10"]=> string(17) "Content String 10" @@ -122,5 +122,5 @@ array(6) { } === RUNNING WITH NO LOCK === -Warning: dba_open(): Locking cannot be disabled for handler ndbm in /home/girgias/Dev/php-src/ext/dba/tests/setup/setup_dba_tests.inc on line 40 +Warning: dba_open(): Locking cannot be disabled for handler ndbm in %s on line %d Failed to create DB From 2edf12e87f6955e6ed82f9c65db2916820276876 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 23 Jun 2024 15:06:35 +0100 Subject: [PATCH 20/57] Fix GH-14638: null dereference after XML parsing failure. object document is null if the parsing had failed prior to cast to string. --- NEWS | 4 +++ ext/simplexml/simplexml.c | 56 ++++++++++++++++++-------------- ext/simplexml/tests/gh14638.phpt | 25 ++++++++++++++ 3 files changed, 61 insertions(+), 24 deletions(-) create mode 100644 ext/simplexml/tests/gh14638.phpt diff --git a/NEWS b/NEWS index 4182d5d7745c8..80c66a126a83a 100644 --- a/NEWS +++ b/NEWS @@ -31,6 +31,10 @@ PHP NEWS - Shmop: . Fixed bug GH-14537 (shmop Windows 11 crashes the process). (nielsdos) +- SimpleXML: + . Fixed bug GH-14638 (null dereference after XML parsing failure). + (David Carlier) + 04 Jul 2024, PHP 8.2.21 - Core: diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index ce7c96a0d468b..6bcb9edcfface 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -1502,6 +1502,35 @@ static void sxe_add_namespaces(php_sxe_object *sxe, xmlNodePtr node, bool recurs } } /* }}} */ +static inline void sxe_object_free_iterxpath(php_sxe_object *sxe) +{ + if (!Z_ISUNDEF(sxe->iter.data)) { + zval_ptr_dtor(&sxe->iter.data); + ZVAL_UNDEF(&sxe->iter.data); + } + + if (sxe->iter.name) { + efree(sxe->iter.name); + sxe->iter.name = NULL; + } + if (sxe->iter.nsprefix) { + efree(sxe->iter.nsprefix); + sxe->iter.nsprefix = NULL; + } + if (!Z_ISUNDEF(sxe->tmp)) { + zval_ptr_dtor(&sxe->tmp); + ZVAL_UNDEF(&sxe->tmp); + } + + php_libxml_node_decrement_resource((php_libxml_node_object *)sxe); + + if (sxe->xpath) { + xmlXPathFreeContext(sxe->xpath); + sxe->xpath = NULL; + } +} + + /* {{{ Return all namespaces in use */ PHP_METHOD(SimpleXMLElement, getNamespaces) { @@ -2156,29 +2185,7 @@ static void sxe_object_free_storage(zend_object *object) zend_object_std_dtor(&sxe->zo); - if (!Z_ISUNDEF(sxe->iter.data)) { - zval_ptr_dtor(&sxe->iter.data); - ZVAL_UNDEF(&sxe->iter.data); - } - - if (sxe->iter.name) { - efree(sxe->iter.name); - sxe->iter.name = NULL; - } - if (sxe->iter.nsprefix) { - efree(sxe->iter.nsprefix); - sxe->iter.nsprefix = NULL; - } - if (!Z_ISUNDEF(sxe->tmp)) { - zval_ptr_dtor(&sxe->tmp); - ZVAL_UNDEF(&sxe->tmp); - } - - php_libxml_node_decrement_resource((php_libxml_node_object *)sxe); - - if (sxe->xpath) { - xmlXPathFreeContext(sxe->xpath); - } + sxe_object_free_iterxpath(sxe); if (sxe->properties) { zend_hash_destroy(sxe->properties); @@ -2378,11 +2385,12 @@ PHP_METHOD(SimpleXMLElement, __construct) PHP_LIBXML_RESTORE_GLOBALS(read_file_or_memory); if (!docp) { - ((php_libxml_node_object *)sxe)->document = NULL; zend_throw_exception(zend_ce_exception, "String could not be parsed as XML", 0); RETURN_THROWS(); } + sxe_object_free_iterxpath(sxe); + sxe->iter.nsprefix = ns_len ? (xmlChar*)estrdup(ns) : NULL; sxe->iter.isprefix = isprefix; php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp); diff --git a/ext/simplexml/tests/gh14638.phpt b/ext/simplexml/tests/gh14638.phpt new file mode 100644 index 0000000000000..abb4e1ac1407c --- /dev/null +++ b/ext/simplexml/tests/gh14638.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-14638: null pointer dereference on object cast __toString after failed XML parsing +--EXTENSIONS-- +simplexml +--CREDITS-- +YuanchengJiang +--FILE-- + + +'; +$root = simplexml_load_string($xml); +try { + $root->__construct("malformed"); +} catch (Exception $e) { + // Intentionally empty +} +echo $root; +?> +--EXPECTF-- +Warning: SimpleXMLElement::__construct(): Entity: line 1: parser error : Start tag expected, '<' not found in %s on line %d + +Warning: SimpleXMLElement::__construct(): malformed in %s on line %d + +Warning: SimpleXMLElement::__construct(): ^ in %s on line %d From cd67080236e8a054f0a7710b2745509ce2554fa2 Mon Sep 17 00:00:00 2001 From: Go Kudo Date: Wed, 3 Jul 2024 14:53:33 +0900 Subject: [PATCH 21/57] [ci skip] fix NEWS typo (#14777) --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 80c66a126a83a..f33c3842df40e 100644 --- a/NEWS +++ b/NEWS @@ -48,7 +48,7 @@ PHP NEWS . Fixed bug GH-14549 (Incompatible function pointer type for fclose). (Ryan Carsten Schmidt) -- BCMatch: +- BCMath: . Fixed bug (bcpowmod() with mod = -1 returns 1 when it must be 0). (Girgias) - Curl: From 070779c8744982faeb47fc1783c8cb52ef02fd9a Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Wed, 3 Jul 2024 16:12:57 +0200 Subject: [PATCH 22/57] Fix test race condition Closes GH-14790 --- ext/openssl/tests/gh13860.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/openssl/tests/gh13860.phpt b/ext/openssl/tests/gh13860.phpt index 0b52e0e0583ab..aff0df15cca95 100644 --- a/ext/openssl/tests/gh13860.phpt +++ b/ext/openssl/tests/gh13860.phpt @@ -18,8 +18,8 @@ $serverCode = <<<'CODE' $client = @stream_socket_accept($server); if ($client) { - fwrite($client, "xx"); phpt_wait(); + fwrite($client, "xx"); fclose($client); phpt_notify(); } From 15bea9ed74dd1024cd31cfec1bd8c92d7486c4de Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 3 Jul 2024 06:39:29 +0100 Subject: [PATCH 23/57] Fix GH-14775: range overflow on negative step. overflow occurs since we only deal with positive steps. close GH-14778 --- NEWS | 6 +++++- ext/standard/array.c | 4 ++++ ext/standard/tests/array/gh14775.phpt | 12 ++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/array/gh14775.phpt diff --git a/NEWS b/NEWS index ac6bf6c108cc0..cb382e9c83591 100644 --- a/NEWS +++ b/NEWS @@ -29,7 +29,11 @@ PHP NEWS (David Carlier) - Shmop: - . Fixed bug GH-14537 (shmop Windows 11 crashes the process). (nielsdos) + . Fixed bug GH-14537 (shmop Windows 11 crashes the process). (nielsdos) + +- Standard: + . Fixed bug GH-14775 (range function overflow with negative step argument). + (David Carlier) 20 Jun 2024, PHP 8.3.9 diff --git a/ext/standard/array.c b/ext/standard/array.c index 30868a47b5932..b6f78fad28611 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2887,6 +2887,10 @@ PHP_FUNCTION(range) step = Z_LVAL_P(user_step); /* We only want positive step values. */ if (step < 0) { + if (UNEXPECTED(step == ZEND_LONG_MIN)) { + zend_argument_value_error(3, "must be greater than " ZEND_LONG_FMT, step); + RETURN_THROWS(); + } is_step_negative = true; step *= -1; } diff --git a/ext/standard/tests/array/gh14775.phpt b/ext/standard/tests/array/gh14775.phpt new file mode 100644 index 0000000000000..df4db76031ecb --- /dev/null +++ b/ext/standard/tests/array/gh14775.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-14775: Range negative step overflow +--FILE-- +getMessage() . PHP_EOL; +} +--EXPECTF-- +range(): Argument #3 ($step) must be greater than %s From a8d195534864b57cb39dfea108d55b623e0cb429 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Wed, 3 Jul 2024 09:32:23 -0400 Subject: [PATCH 24/57] ext/standard/tests: use %d instead of bytes in an overflow message In strings/chunk_split_variation1_32bit.phpt, we have a test that is expected to fail on x32 with a possible integer overflow error. The message reports the exact number of bytes -- a number big enough to overflow an int on x32 -- stemming from a memory allocation in chunk_split(). This number appears unpredictable, and is not the point of the test. We replace it with %d to make the test independent of the allocation details. --- ext/standard/tests/strings/chunk_split_variation1_32bit.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/tests/strings/chunk_split_variation1_32bit.phpt b/ext/standard/tests/strings/chunk_split_variation1_32bit.phpt index b4bef8add4103..03a101eb2e43d 100644 --- a/ext/standard/tests/strings/chunk_split_variation1_32bit.phpt +++ b/ext/standard/tests/strings/chunk_split_variation1_32bit.phpt @@ -17,4 +17,4 @@ var_dump(chunk_split($a,$b,$c)); --EXPECTF-- *** Testing chunk_split() : unexpected large 'end' string argument variation 1 *** -Fatal error: %rAllowed memory size of %d bytes exhausted%s\(tried to allocate %d bytes\)|Possible integer overflow in memory allocation \(4294901777 \+ 2097152\)%r in %s on line %d +Fatal error: %rAllowed memory size of %d bytes exhausted%s\(tried to allocate %d bytes\)|Possible integer overflow in memory allocation \(4294901777 \+ %d\)%r in %s on line %d From 7b74cadf8c12abbba91be08e47dd4cca5d2db4a0 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 4 Jul 2024 04:34:33 -0700 Subject: [PATCH 25/57] Fix uninitialized (dummy) memory in php_strtr_array() (#14812) Fixes one issue in GH-14806. --- ext/standard/string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index e8c682a4cb77b..0cc8af0ef366d 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -3275,7 +3275,7 @@ PHP_FUNCTION(strtr) /* case_sensitive */ true, NULL)); } else { - zend_long dummy; + zend_long dummy = 0; RETVAL_STR(php_str_to_str_ex(str, ZSTR_VAL(str_key), ZSTR_LEN(str_key), ZSTR_VAL(replace), ZSTR_LEN(replace), &dummy)); From bc32a6bd4e544c1c102c6b8e786bd3b5cf24e392 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 2 Jul 2024 11:53:20 +0200 Subject: [PATCH 26/57] Fix syntax error in SWITCH VM Closes GH-14768 --- Zend/zend_vm_def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index f731653a24813..2c604d9724971 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8024,7 +8024,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) /* Exception was thrown before executing any op */ if (UNEXPECTED(!throw_op)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, -1, 0, 0); + ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, -1, op_num, 0); } uint32_t throw_op_num = throw_op - EX(func)->op_array.opcodes; From 4fe821311cafb18ca8bdf20b9d796c48a13ba552 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 4 Jul 2024 06:29:50 -0700 Subject: [PATCH 27/57] Backport libxml2 2.13.2 fixes (#14816) Backproted from https://github.com/php/php-src/pull/14789 --- ext/dom/document.c | 6 ++-- .../DOMDocument_loadHTMLfile_error1.phpt | 2 +- .../DOMDocument_loadXML_error2_gte2_12.phpt | 2 +- .../DOMDocument_load_error2_gte2_12.phpt | 2 +- .../DOMDocument_relaxNGValidate_error2.phpt | 2 +- .../tests/DOMDocument_saveHTMLFile_basic.phpt | 4 +++ ...DOMDocument_saveHTMLFile_formatOutput.phpt | 4 +++ ...nt_saveHTMLFile_formatOutput_gte_2_13.phpt | 32 +++++++++++++++++++ .../DOMDocument_saveHTML_basic_gte_2_13.phpt | 31 ++++++++++++++++++ .../DOMDocument_schemaValidate_error5.phpt | 2 +- ext/dom/tests/dom_create_element.phpt | 14 +++----- ext/libxml/libxml.c | 4 ++- ext/libxml/php_libxml.h | 2 ++ ext/simplexml/tests/bug79971_1.phpt | 2 +- ext/soap/php_encoding.c | 9 ++++-- ext/soap/php_xml.c | 8 ++++- ext/soap/tests/bugs/bug42151.phpt | 4 +-- ext/xml/compat.c | 3 +- ext/xmlwriter/php_xmlwriter.c | 3 +- 19 files changed, 109 insertions(+), 27 deletions(-) create mode 100644 ext/dom/tests/DOMDocument_saveHTMLFile_formatOutput_gte_2_13.phpt create mode 100644 ext/dom/tests/DOMDocument_saveHTML_basic_gte_2_13.phpt diff --git a/ext/dom/document.c b/ext/dom/document.c index 38af4ca27c820..516ffffae8d78 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -1292,11 +1292,13 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so if (keep_blanks == 0 && ! (options & XML_PARSE_NOBLANKS)) { options |= XML_PARSE_NOBLANKS; } + if (recover) { + options |= XML_PARSE_RECOVER; + } php_libxml_sanitize_parse_ctxt_options(ctxt); xmlCtxtUseOptions(ctxt, options); - ctxt->recovery = recover; if (recover) { old_error_reporting = EG(error_reporting); EG(error_reporting) = old_error_reporting | E_WARNING; @@ -1306,7 +1308,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so if (ctxt->wellFormed || recover) { ret = ctxt->myDoc; - if (ctxt->recovery) { + if (recover) { EG(error_reporting) = old_error_reporting; } /* If loading from memory, set the base reference uri for the document */ diff --git a/ext/dom/tests/DOMDocument_loadHTMLfile_error1.phpt b/ext/dom/tests/DOMDocument_loadHTMLfile_error1.phpt index 5b88546908df0..bacf64edb2a2b 100644 --- a/ext/dom/tests/DOMDocument_loadHTMLfile_error1.phpt +++ b/ext/dom/tests/DOMDocument_loadHTMLfile_error1.phpt @@ -15,4 +15,4 @@ $result = $doc->loadHTMLFile(__DIR__ . "/ffff/test.html"); assert($result === false); ?> --EXPECTF-- -%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile(): I/O warning : failed to load external entity %s +%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile(): I/O %s diff --git a/ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt index 6a3ff5841f565..d84d690c715fb 100644 --- a/ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt +++ b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt @@ -23,7 +23,7 @@ domdocumentloadxml_test_method.inc --EXPECTF-- Warning: DOMDocument::loadXML(): AttValue: " or ' expected in Entity, line: 4 in %s on line %d -Warning: DOMDocument::loadXML(): internal error: xmlParseStartTag: problem parsing attributes in Entity, line: 4 in %s on line %d +Warning: DOMDocument::loadXML():%sattributes%s Warning: DOMDocument::loadXML(): Couldn't find end of Start Tag book line 4 in Entity, line: 4 in %s on line %d diff --git a/ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt b/ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt index 4fadf41736124..aaab30ed64573 100644 --- a/ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt +++ b/ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt @@ -23,7 +23,7 @@ domdocumentload_test_method.inc --EXPECTF-- Warning: DOMDocument::load(): AttValue: " or ' expected in %s on line %d -Warning: DOMDocument::load(): internal error: xmlParseStartTag: problem parsing attributes in %s on line %d +Warning: DOMDocument::load():%sattributes%s Warning: DOMDocument::load(): Couldn't find end of Start Tag book line 4 in %s on line %d diff --git a/ext/dom/tests/DOMDocument_relaxNGValidate_error2.phpt b/ext/dom/tests/DOMDocument_relaxNGValidate_error2.phpt index 1ad46e014a0a7..cb506f70789d8 100644 --- a/ext/dom/tests/DOMDocument_relaxNGValidate_error2.phpt +++ b/ext/dom/tests/DOMDocument_relaxNGValidate_error2.phpt @@ -20,7 +20,7 @@ $result = $doc->relaxNGValidate($rng); var_dump($result); ?> --EXPECTF-- -Warning: DOMDocument::relaxNGValidate(): I/O warning : failed to load external entity "%s/foo.rng" in %s on line %d +Warning: DOMDocument::relaxNGValidate(): I/O %s : failed to load %s Warning: DOMDocument::relaxNGValidate(): xmlRelaxNGParse: could not load %s/foo.rng in %s on line %d diff --git a/ext/dom/tests/DOMDocument_saveHTMLFile_basic.phpt b/ext/dom/tests/DOMDocument_saveHTMLFile_basic.phpt index cf392c0262fd4..32f1a3c36e2f4 100644 --- a/ext/dom/tests/DOMDocument_saveHTMLFile_basic.phpt +++ b/ext/dom/tests/DOMDocument_saveHTMLFile_basic.phpt @@ -5,6 +5,10 @@ Knut Urdalen #PHPTestFest2009 Norway 2009-06-09 \o/ --EXTENSIONS-- dom +--SKIPIF-- += 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756"); +?> --FILE-- #PHPTestFest2009 Norway 2009-06-09 \o/ --EXTENSIONS-- dom +--SKIPIF-- += 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756"); +?> --FILE-- +#PHPTestFest2009 Norway 2009-06-09 \o/ +--EXTENSIONS-- +dom +--SKIPIF-- + +--FILE-- +formatOutput = true; +$root = $doc->createElement('html'); +$root = $doc->appendChild($root); +$head = $doc->createElement('head'); +$head = $root->appendChild($head); +$title = $doc->createElement('title'); +$title = $head->appendChild($title); +$text = $doc->createTextNode('This is the title'); +$text = $title->appendChild($text); +$bytes = $doc->saveHTMLFile($filename); +var_dump($bytes); +echo file_get_contents($filename); +unlink($filename); +?> +--EXPECT-- +int(59) +This is the title diff --git a/ext/dom/tests/DOMDocument_saveHTML_basic_gte_2_13.phpt b/ext/dom/tests/DOMDocument_saveHTML_basic_gte_2_13.phpt new file mode 100644 index 0000000000000..c0be105253dd7 --- /dev/null +++ b/ext/dom/tests/DOMDocument_saveHTML_basic_gte_2_13.phpt @@ -0,0 +1,31 @@ +--TEST-- +DOMDocument::saveHTMLFile() should dump the internal document into a file using HTML formatting +--CREDITS-- +Knut Urdalen +#PHPTestFest2009 Norway 2009-06-09 \o/ +--EXTENSIONS-- +dom +--SKIPIF-- + +--FILE-- +createElement('html'); +$root = $doc->appendChild($root); +$head = $doc->createElement('head'); +$head = $root->appendChild($head); +$title = $doc->createElement('title'); +$title = $head->appendChild($title); +$text = $doc->createTextNode('This is the title'); +$text = $title->appendChild($text); +$bytes = $doc->saveHTMLFile($filename); +var_dump($bytes); +echo file_get_contents($filename); +unlink($filename); +?> +--EXPECT-- +int(59) +This is the title diff --git a/ext/dom/tests/DOMDocument_schemaValidate_error5.phpt b/ext/dom/tests/DOMDocument_schemaValidate_error5.phpt index 2feda5d1e1f8d..bc94abacf22ad 100644 --- a/ext/dom/tests/DOMDocument_schemaValidate_error5.phpt +++ b/ext/dom/tests/DOMDocument_schemaValidate_error5.phpt @@ -17,7 +17,7 @@ var_dump($result); ?> --EXPECTF-- -Warning: DOMDocument::schemaValidate(): I/O warning : failed to load external entity "%snon-existent-file" in %s.php on line %d +Warning: DOMDocument::schemaValidate(): I/O %s : failed to load %s Warning: DOMDocument::schemaValidate(): Failed to locate the main schema resource at '%s/non-existent-file'. in %s.php on line %d diff --git a/ext/dom/tests/dom_create_element.phpt b/ext/dom/tests/dom_create_element.phpt index 82d73826da433..19acb5614d575 100644 --- a/ext/dom/tests/dom_create_element.phpt +++ b/ext/dom/tests/dom_create_element.phpt @@ -251,14 +251,10 @@ try { print $e->getMessage() . "\n"; } -/* This isn't because the xml namespace isn't there and we can't create it */ -print "29 DOMElement::__construct('xml:valid', '', 'http://www.w3.org/XML/1998/namespace')\n"; -try { - $element = new DomElement('xml:valid', '', 'http://www.w3.org/XML/1998/namespace'); - print "valid\n"; -} catch (Exception $e) { - print $e->getMessage() . "\n"; -} +/* There used to be a 29 here that tested DOMElement::__construct('xml:valid', '', 'http://www.w3.org/XML/1998/namespace'). + * In libxml2 version 2.12 or prior this didn't work because the xml namespace isn't there and you can't create it without + * a document. Starting from libxml2 version 2.13 it does actually work because the XML namespace is statically defined. + * The behaviour from version 2.13 is actually the desired behaviour anyway. */ /* the qualifiedName or its prefix is "xmlns" and the namespaceURI is @@ -378,8 +374,6 @@ Namespace Error Namespace Error 28 DOMDocument::createElementNS('http://www.w3.org/XML/1998/namespace', 'xml:valid') valid -29 DOMElement::__construct('xml:valid', '', 'http://www.w3.org/XML/1998/namespace') -Namespace Error 30 DOMDocument::createElementNS('http://wrong.namespaceuri.com/', 'xmlns:valid') Namespace Error 31 DOMElement::__construct('xmlns:valid', '', 'http://wrong.namespaceuri.com/') diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index 1de693892b7aa..5f9749ffed239 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -419,8 +419,10 @@ php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc) static xmlOutputBufferPtr php_libxml_output_buffer_create_filename(const char *URI, xmlCharEncodingHandlerPtr encoder, - int compression ATTRIBUTE_UNUSED) + int compression) { + ZEND_IGNORE_VALUE(compression); + xmlOutputBufferPtr ret; xmlURIPtr puri; void *context = NULL; diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h index a7f7971c5a5f5..8b800ae27d9ed 100644 --- a/ext/libxml/php_libxml.h +++ b/ext/libxml/php_libxml.h @@ -167,6 +167,7 @@ ZEND_TSRMLS_CACHE_EXTERN() * Generally faster because no locking is involved, and this has the advantage that it sets the options to a known good value. */ static zend_always_inline void php_libxml_sanitize_parse_ctxt_options(xmlParserCtxtPtr ctxt) { + PHP_LIBXML_IGNORE_DEPRECATIONS_START ctxt->loadsubset = 0; ctxt->validate = 0; ctxt->pedantic = 0; @@ -174,6 +175,7 @@ static zend_always_inline void php_libxml_sanitize_parse_ctxt_options(xmlParserC ctxt->linenumbers = 0; ctxt->keepBlanks = 1; ctxt->options = 0; + PHP_LIBXML_IGNORE_DEPRECATIONS_END } #else /* HAVE_LIBXML */ diff --git a/ext/simplexml/tests/bug79971_1.phpt b/ext/simplexml/tests/bug79971_1.phpt index 1097d74bb29d2..2ee24e89f1231 100644 --- a/ext/simplexml/tests/bug79971_1.phpt +++ b/ext/simplexml/tests/bug79971_1.phpt @@ -20,7 +20,7 @@ var_dump($sxe->asXML("$uri.out%00foo")); --EXPECTF-- Warning: simplexml_load_file(): URI must not contain percent-encoded NUL bytes in %s on line %d -Warning: simplexml_load_file(): I/O warning : failed to load external entity "%s/bug79971_1.xml%%r00%rfoo" in %s on line %d +Warning: simplexml_load_file(): I/O warning : failed to load %s bool(false) Warning: SimpleXMLElement::asXML(): URI must not contain percent-encoded NUL bytes in %s on line %d diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index c52677b6c65a7..82b21d1588146 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -3374,7 +3374,6 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns) } else { smart_str prefix = {0}; int num = ++SOAP_GLOBAL(cur_uniq_ns); - xmlChar *enc_ns; while (1) { smart_str_appendl(&prefix, "ns", 2); @@ -3388,9 +3387,15 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns) num = ++SOAP_GLOBAL(cur_uniq_ns); } - enc_ns = xmlEncodeSpecialChars(node->doc, BAD_CAST(ns)); + /* Starting with libxml 2.13, we don't have to do this workaround anymore, otherwise we get double-encoded + * entities. See libxml2 commit f506ec66547ef9bac97a2bf306d368ecea8c0c9e. */ +#if LIBXML_VERSION < 21300 + xmlChar *enc_ns = xmlEncodeSpecialChars(node->doc, BAD_CAST(ns)); xmlns = xmlNewNs(node->doc->children, enc_ns, BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : "")); xmlFree(enc_ns); +#else + xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : "")); +#endif smart_str_free(&prefix); } } diff --git a/ext/soap/php_xml.c b/ext/soap/php_xml.c index 3ff7aa055fd33..20fd91ac4b49e 100644 --- a/ext/soap/php_xml.c +++ b/ext/soap/php_xml.c @@ -92,13 +92,16 @@ xmlDocPtr soap_xmlParseFile(const char *filename) bool old; php_libxml_sanitize_parse_ctxt_options(ctxt); + /* TODO: In libxml2 2.14.0 change this to the new options API so we don't rely on deprecated APIs. */ + PHP_LIBXML_IGNORE_DEPRECATIONS_START ctxt->keepBlanks = 0; + ctxt->options |= XML_PARSE_HUGE; + PHP_LIBXML_IGNORE_DEPRECATIONS_END ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace; ctxt->sax->comment = soap_Comment; ctxt->sax->warning = NULL; ctxt->sax->error = NULL; /*ctxt->sax->fatalError = NULL;*/ - ctxt->options |= XML_PARSE_HUGE; old = php_libxml_disable_entity_loader(1); xmlParseDocument(ctxt); php_libxml_disable_entity_loader(old); @@ -146,7 +149,10 @@ xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size) ctxt->sax->warning = NULL; ctxt->sax->error = NULL; /*ctxt->sax->fatalError = NULL;*/ + /* TODO: In libxml2 2.14.0 change this to the new options API so we don't rely on deprecated APIs. */ + PHP_LIBXML_IGNORE_DEPRECATIONS_START ctxt->options |= XML_PARSE_HUGE; + PHP_LIBXML_IGNORE_DEPRECATIONS_END old = php_libxml_disable_entity_loader(1); xmlParseDocument(ctxt); php_libxml_disable_entity_loader(old); diff --git a/ext/soap/tests/bugs/bug42151.phpt b/ext/soap/tests/bugs/bug42151.phpt index 6f5c0c4207766..2f9c1830ad39c 100644 --- a/ext/soap/tests/bugs/bug42151.phpt +++ b/ext/soap/tests/bugs/bug42151.phpt @@ -25,8 +25,8 @@ try { } echo "ok\n"; ?> ---EXPECT-- -SOAP-ERROR: Parsing WSDL: Couldn't load from 'httpx://' : failed to load external entity "httpx://" +--EXPECTF-- +SOAP-ERROR: Parsing WSDL: Couldn't load from 'httpx://' : failed to load %s ok I don't get executed either. diff --git a/ext/xml/compat.c b/ext/xml/compat.c index 5c41e7d2f5dc7..7b463ebb5112e 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -714,8 +714,7 @@ XML_GetCurrentByteCount(XML_Parser parser) { /* WARNING: this is identical to ByteIndex; it should probably * be different */ - return parser->parser->input->consumed + - (parser->parser->input->cur - parser->parser->input->base); + return XML_GetCurrentByteIndex(parser); } PHP_XML_API const XML_Char *XML_ExpatVersion(void) diff --git a/ext/xmlwriter/php_xmlwriter.c b/ext/xmlwriter/php_xmlwriter.c index df5bbe35554e6..d7ac7387b88b2 100644 --- a/ext/xmlwriter/php_xmlwriter.c +++ b/ext/xmlwriter/php_xmlwriter.c @@ -1004,7 +1004,8 @@ static void php_xmlwriter_flush(INTERNAL_FUNCTION_PARAMETERS, int force_string) } output_bytes = xmlTextWriterFlush(ptr); if (buffer) { - RETVAL_STRING((char *) buffer->content); + const xmlChar *content = xmlBufferContent(buffer); + RETVAL_STRING((const char *) content); if (empty) { xmlBufferEmpty(buffer); } From a5a63f2904ee3943be1b3de5bd243538808ae0e9 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:32:05 +0200 Subject: [PATCH 28/57] [ci skip] NEWS --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index f33c3842df40e..45afcaf352d32 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,9 @@ PHP NEWS . Fixed bug GH-14638 (null dereference after XML parsing failure). (David Carlier) +- Treewide: + . Fix compatibility with libxml2 2.13.2. (nielsdos) + 04 Jul 2024, PHP 8.2.21 - Core: From a380cdb996a25457063a8358e2ea14d5c0bd3018 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 4 Jul 2024 15:36:37 +0200 Subject: [PATCH 29/57] [skip ci] Fix exlusion of buggy Symfony test --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 76d478bc3b5cf..61545aeac59da 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -359,7 +359,7 @@ jobs: # Test causes a heap-buffer-overflow but I cannot reproduce it locally... php -r '$c = file_get_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php"); $c = str_replace("public function testSanitizeDeepNestedString()", "/** @group skip */\n public function testSanitizeDeepNestedString()", $c); file_put_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php", $c);' # Buggy FFI test in Symfony, see https://github.com/symfony/symfony/issues/47668 - php -r '$c = file_get_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php"); $c = str_replace("*/\n public function testCastNonTrailingCharPointer()", "* @group skip\n */\n public function testCastNonTrailingCharPointer()", $c); file_put_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php", $c);' + php -r '$c = file_get_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php"); $c = str_replace("public function testCastNonTrailingCharPointer()", "/** @group skip */\n public function testCastNonTrailingCharPointer()", $c); file_put_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php", $c);' export ASAN_OPTIONS=exitcode=139 export SYMFONY_DEPRECATIONS_HELPER=max[total]=999 X=0 From 89c3e0346a0c67e68c3e625cf463a9195cbfc7d3 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 4 Jul 2024 13:48:42 +0200 Subject: [PATCH 30/57] Fix GH-14808: Unexpected null pointer in Zend/zend_string.h with empty output buffer The output buffer can be NULL when the number of bytes is zero. Closes GH-14815. --- NEWS | 4 ++++ main/output.c | 6 +++++- tests/output/gh14808.phpt | 13 +++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tests/output/gh14808.phpt diff --git a/NEWS b/NEWS index 45afcaf352d32..a4940d1743482 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,10 @@ PHP NEWS - LibXML: . Fixed bug GH-14563 (Build failure with libxml2 v2.13.0). (nielsdos) +- Output: + . Fixed bug GH-14808 (Unexpected null pointer in Zend/zend_string.h with + empty output buffer). (nielsdos) + - PDO: . Fixed bug GH-14712 (Crash with PDORow access to null property). (David Carlier) diff --git a/main/output.c b/main/output.c index 7b5bc49dab87e..e894c4729d58f 100644 --- a/main/output.c +++ b/main/output.c @@ -380,7 +380,11 @@ PHPAPI int php_output_get_level(void) PHPAPI int php_output_get_contents(zval *p) { if (OG(active)) { - ZVAL_STRINGL(p, OG(active)->buffer.data, OG(active)->buffer.used); + if (OG(active)->buffer.used) { + ZVAL_STRINGL(p, OG(active)->buffer.data, OG(active)->buffer.used); + } else { + ZVAL_EMPTY_STRING(p); + } return SUCCESS; } else { ZVAL_NULL(p); diff --git a/tests/output/gh14808.phpt b/tests/output/gh14808.phpt new file mode 100644 index 0000000000000..7a3f57ba51c5d --- /dev/null +++ b/tests/output/gh14808.phpt @@ -0,0 +1,13 @@ +--TEST-- +GH-14808 (Unexpected null pointer in Zend/zend_string.h with empty output buffer) +--FILE-- + +--EXPECTF-- +Warning: Undefined variable $args in %s on line %d +NULL +string(0) "" From 68a0efedebd8ffb228ca0209035d8af696bda13c Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Wed, 3 Jul 2024 19:42:17 -0400 Subject: [PATCH 31/57] ext/standard/tests: 32bit wordwrap tests aren't just for Windows The test in strings/wordwrap_memory_limit.phpt has a counterpart in strings/wordwrap_memory_limit_win32.phpt. The two are conditional on both the OS name and the size of an int (32- versus 64-bits). A Gentoo Linux user has however reported that the 64-bit test fails on a 32-bit system, with precisely the error message that the "win32" test is expecting. I don't have any 32-bit hardware to test myself, but I think it's reasonable to conclude that the OS name is not an essential part of the test: it's simply 32- versus 64-bit. This commit drops the conditionals for the OS name. Now one test will be run on 32-bit systems, and the other on 64-bit systems, regardless of the OS name. Bug: https://bugs.gentoo.org/935382 --- ext/standard/tests/strings/wordwrap_memory_limit.phpt | 2 +- ...memory_limit_win32.phpt => wordwrap_memory_limit_32bit.phpt} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename ext/standard/tests/strings/{wordwrap_memory_limit_win32.phpt => wordwrap_memory_limit_32bit.phpt} (78%) diff --git a/ext/standard/tests/strings/wordwrap_memory_limit.phpt b/ext/standard/tests/strings/wordwrap_memory_limit.phpt index 21340153faea1..e64aef96c9a14 100644 --- a/ext/standard/tests/strings/wordwrap_memory_limit.phpt +++ b/ext/standard/tests/strings/wordwrap_memory_limit.phpt @@ -2,7 +2,7 @@ No overflow should occur during the memory_limit check for wordwrap() --SKIPIF-- --INI-- diff --git a/ext/standard/tests/strings/wordwrap_memory_limit_win32.phpt b/ext/standard/tests/strings/wordwrap_memory_limit_32bit.phpt similarity index 78% rename from ext/standard/tests/strings/wordwrap_memory_limit_win32.phpt rename to ext/standard/tests/strings/wordwrap_memory_limit_32bit.phpt index e0e76b5800ce2..72f449d8e0679 100644 --- a/ext/standard/tests/strings/wordwrap_memory_limit_win32.phpt +++ b/ext/standard/tests/strings/wordwrap_memory_limit_32bit.phpt @@ -2,7 +2,7 @@ No overflow should occur during the memory_limit check for wordwrap() --SKIPIF-- --INI-- From 27dd393be9036a9cbdb8529b1ca3a4552810b0e7 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Thu, 4 Jul 2024 07:49:01 -0400 Subject: [PATCH 32/57] ext/standard/tests: strings/wordwrap_memory_limit_32bit.phpt has two outputs It turns out that on a 32-bit system, this test can produce either the "usual" expected output from the 64-bit test, OR the 32-bit-only integer overflow message. We copy the dual expected outputs from chunk_split_variation1_32bit.phpt to handle both cases. This fixes an earlier commit that split the two tests based only on the size of an int (32-bit versus 64-bit). The CI reveals that, at least on a debug/zts build, the "64-bit" memory limit error (and not the integer overflow error) is still produced. --- ext/standard/tests/strings/wordwrap_memory_limit_32bit.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/tests/strings/wordwrap_memory_limit_32bit.phpt b/ext/standard/tests/strings/wordwrap_memory_limit_32bit.phpt index 72f449d8e0679..36d22cc859b5b 100644 --- a/ext/standard/tests/strings/wordwrap_memory_limit_32bit.phpt +++ b/ext/standard/tests/strings/wordwrap_memory_limit_32bit.phpt @@ -16,4 +16,4 @@ wordwrap($str, 1, $str2); ?> --EXPECTF-- -Fatal error: Possible integer overflow in memory allocation (4294901777 + %d) in %s on line %d +Fatal error: %rAllowed memory size of %d bytes exhausted%s\(tried to allocate %d bytes\)|Possible integer overflow in memory allocation \(4294901777 \+ %d\)%r in %s on line %d From 1006e1021e959444dcde1ca1eae773863bfc200a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:56:04 +0200 Subject: [PATCH 33/57] NEWS for GH-14814 Closes GH-14814. --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index a4940d1743482..5e468d881bf41 100644 --- a/NEWS +++ b/NEWS @@ -39,6 +39,9 @@ PHP NEWS . Fixed bug GH-14638 (null dereference after XML parsing failure). (David Carlier) +- Standard: + . Fix 32-bit wordwrap test failures. (orlitzky) + - Treewide: . Fix compatibility with libxml2 2.13.2. (nielsdos) From 39ed9993f7d956dfe7efa30928f667debe2260a4 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 4 Jul 2024 09:07:54 -0700 Subject: [PATCH 34/57] Fix GH-13688: Test curl_basic_008 can fail (#13693) .invalid is a reserved TLD that should never be caught. --- ext/curl/tests/curl_basic_008.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/curl/tests/curl_basic_008.phpt b/ext/curl/tests/curl_basic_008.phpt index cd4496528ceeb..353c44327c5e8 100644 --- a/ext/curl/tests/curl_basic_008.phpt +++ b/ext/curl/tests/curl_basic_008.phpt @@ -6,7 +6,7 @@ TestFest 2009 - AFUP - Perrick Penet curl --SKIPIF-- Date: Thu, 4 Jul 2024 18:07:00 +0200 Subject: [PATCH 35/57] Fix GH-14553: Bug in phpdbg8.3 (also 8.1 and 8.2) echo output - trimmed at NULL byte (?) This broke in 6318040df2b6c6f4824b99fd27369179d29ee93b when phpdbg stopped using its custom printing routines. By relying on standard printing routines, the embedded NUL bytes are causing the strings to be cut off, even when using %.*s. Solve this by going straight to the output routine, which is what the printf routine would've done anyway. Closes GH-14822. --- NEWS | 1 + sapi/phpdbg/phpdbg.c | 2 +- sapi/phpdbg/phpdbg_out.c | 2 +- sapi/phpdbg/phpdbg_out.h | 2 ++ sapi/phpdbg/tests/gh10715.phpt | Bin 192 -> 147 bytes sapi/phpdbg/tests/gh14553.phpt | 14 ++++++++++++++ 6 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 sapi/phpdbg/tests/gh14553.phpt diff --git a/NEWS b/NEWS index 5e468d881bf41..74c017b3fbf1c 100644 --- a/NEWS +++ b/NEWS @@ -31,6 +31,7 @@ PHP NEWS - PHPDBG: . Fixed bug GH-14596 (crashes with ASAN and ZEND_RC_DEBUG=1). (David Carlier) + . Fixed bug GH-14553 (echo output trimmed at NULL byte). (nielsdos) - Shmop: . Fixed bug GH-14537 (shmop Windows 11 crashes the process). (nielsdos) diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 3aa0b7b60d7e9..d9cc8f5e891e0 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -845,7 +845,7 @@ static void php_sapi_phpdbg_register_vars(zval *track_vars_array) /* {{{ */ static inline size_t php_sapi_phpdbg_ub_write(const char *message, size_t length) /* {{{ */ { - return phpdbg_script(P_STDOUT, "%.*s", (int) length, message); + return phpdbg_process_print(PHPDBG_G(io)[PHPDBG_STDOUT].fd, P_STDOUT, message, (int) length); } /* }}} */ /* beginning of struct, see main/streams/plain_wrapper.c line 111 */ diff --git a/sapi/phpdbg/phpdbg_out.c b/sapi/phpdbg/phpdbg_out.c index af2f3b98d2bad..63b61fb8eab04 100644 --- a/sapi/phpdbg/phpdbg_out.c +++ b/sapi/phpdbg/phpdbg_out.c @@ -40,7 +40,7 @@ PHPDBG_API int _phpdbg_asprintf(char **buf, const char *format, ...) { return ret; } -static int phpdbg_process_print(int fd, int type, const char *msg, int msglen) { +int phpdbg_process_print(int fd, int type, const char *msg, int msglen) { char *msgout = NULL; int msgoutlen = FAILURE; diff --git a/sapi/phpdbg/phpdbg_out.h b/sapi/phpdbg/phpdbg_out.h index 828e147a1b7e9..1a54bb7ec284a 100644 --- a/sapi/phpdbg/phpdbg_out.h +++ b/sapi/phpdbg/phpdbg_out.h @@ -59,6 +59,8 @@ PHPDBG_API void phpdbg_free_err_buf(void); PHPDBG_API void phpdbg_activate_err_buf(bool active); PHPDBG_API int phpdbg_output_err_buf(const char *strfmt, ...); +int phpdbg_process_print(int fd, int type, const char *msg, int msglen); + /* {{{ For separation */ #define SEPARATE "------------------------------------------------" /* }}} */ diff --git a/sapi/phpdbg/tests/gh10715.phpt b/sapi/phpdbg/tests/gh10715.phpt index 13edd9afdd8f05df2744b3d5d1257c827d219c40..63d98cae107364557482a3e5b5be52e060f695b8 100644 GIT binary patch delta 48 xcmX@WIGJ%mmZq*QS3yyJZb6BiLbP9gNk(Q~xxLEadBE{jzV&NZb4>FVo7FxoEjACkAVvS4>%uH diff --git a/sapi/phpdbg/tests/gh14553.phpt b/sapi/phpdbg/tests/gh14553.phpt new file mode 100644 index 0000000000000..bcf61c0a9fb4d --- /dev/null +++ b/sapi/phpdbg/tests/gh14553.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-14553 (Bug in phpdbg8.3 (also 8.1 and 8.2) echo output - trimmed at NULL byte (?)) +--PHPDBG-- +r +q +--FILE-- + +--EXPECTF-- +[Successful compilation of %s] +prompt> hello%0world +[Script ended normally] +prompt> From 1e5f46fb20f822b1777449fbc3d554b573d200cd Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 6 Jul 2024 01:59:01 +0200 Subject: [PATCH 36/57] Fix test conflict between gzfile_basic.phpt and gzfile_basic2.phpt [ci skip] This should fix the nightly failure. --- ext/zlib/tests/gzfile_basic2.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/zlib/tests/gzfile_basic2.phpt b/ext/zlib/tests/gzfile_basic2.phpt index f53aec8da0322..2b59656a6f314 100644 --- a/ext/zlib/tests/gzfile_basic2.phpt +++ b/ext/zlib/tests/gzfile_basic2.phpt @@ -9,7 +9,7 @@ hello world is a very common test for all languages EOT; -$dirname = 'gzfile_temp'; +$dirname = 'gzfile_temp2'; $filename = $dirname.'/gzfile_basic2.txt'; mkdir($dirname); $h = fopen($filename, 'w'); From 8dc799aac7b3c5f7be639c0f15d3f294a7b194a7 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 5 Jul 2024 20:11:34 +0200 Subject: [PATCH 37/57] Port XML_GetCurrentByteIndex to public APIs This is necessary to avoid a deprecation break in libxml2 2.14.x. --- ext/xml/compat.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/ext/xml/compat.c b/ext/xml/compat.c index 7b463ebb5112e..bc46f001c05cf 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -705,8 +705,21 @@ XML_GetCurrentColumnNumber(XML_Parser parser) PHP_XML_API int XML_GetCurrentByteIndex(XML_Parser parser) { - return parser->parser->input->consumed + - (parser->parser->input->cur - parser->parser->input->base); + /* We have to temporarily disable the encoder to satisfy the note from the manual: + * "This function returns byte index according to UTF-8 encoded text disregarding if input is in another encoding." + * Although that should probably be corrected at one point? (TODO) */ + xmlCharEncodingHandlerPtr encoder = NULL; + xmlParserInputPtr input = parser->parser->input; + if (input->buf) { + encoder = input->buf->encoder; + input->buf->encoder = NULL; + } + long result = xmlByteConsumed(parser->parser); + if (encoder) { + input->buf->encoder = encoder; + } + /* TODO: at one point this should return long probably to make sure that files greater than 2 GiB are handled correctly. */ + return (int) result; } PHP_XML_API int From 6490a1827100c0b5da01bf9de915921ea586a281 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 5 Jul 2024 20:32:09 +0200 Subject: [PATCH 38/57] Stop relying on the sax2 flag directly Setting this directly will become deprecated in libxml2 2.14. --- ext/xml/compat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/xml/compat.c b/ext/xml/compat.c index bc46f001c05cf..910063f6def57 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -476,8 +476,9 @@ XML_ParserCreate_MM(const XML_Char *encoding, const XML_Memory_Handling_Suite *m parser->parser->replaceEntities = 1; parser->parser->wellFormed = 0; if (sep != NULL) { + /* Note: sax2 flag will be set due to the magic number in `initialized` in php_xml_compat_handlers */ + ZEND_ASSERT(parser->parser->sax->initialized == XML_SAX2_MAGIC); parser->use_namespace = 1; - parser->parser->sax2 = 1; parser->_ns_separator = xmlStrdup(sep); } else { /* Reset flag as XML_SAX2_MAGIC is needed for xmlCreatePushParserCtxt From 823d0588f767b392ea74850c4586721b7079b588 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 5 Jul 2024 20:38:07 +0200 Subject: [PATCH 39/57] Stop relying on lastError directly Reading this directly will become deprecated in libxml2 2.14. --- ext/xml/compat.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ext/xml/compat.c b/ext/xml/compat.c index 910063f6def57..d8548bf4dc980 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -564,10 +564,14 @@ XML_SetEndNamespaceDeclHandler(XML_Parser parser, XML_EndNamespaceDeclHandler en PHP_XML_API int XML_Parse(XML_Parser parser, const XML_Char *data, int data_len, int is_final) { - int error; + int error = xmlParseChunk(parser->parser, (char *) data, data_len, is_final); - error = xmlParseChunk(parser->parser, (char *) data, data_len, is_final); - return !error && parser->parser->lastError.level <= XML_ERR_WARNING; + if (!error) { + const xmlError *error_data = xmlCtxtGetLastError(parser->parser); + return !error_data || error_data->level <= XML_ERR_WARNING; + } + + return 0; } PHP_XML_API int From e5e15fd2293e381212786d95790eecbd41630517 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 5 Jul 2024 20:52:56 +0200 Subject: [PATCH 40/57] Stop setting parse options directly Setting this directly will be deprecated in libxml2 2.14. --- ext/xml/compat.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/xml/compat.c b/ext/xml/compat.c index d8548bf4dc980..242cc4ba7c40c 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -471,9 +471,8 @@ XML_ParserCreate_MM(const XML_Char *encoding, const XML_Memory_Handling_Suite *m } php_libxml_sanitize_parse_ctxt_options(parser->parser); - xmlCtxtUseOptions(parser->parser, XML_PARSE_OLDSAX); + xmlCtxtUseOptions(parser->parser, XML_PARSE_OLDSAX | XML_PARSE_NOENT); - parser->parser->replaceEntities = 1; parser->parser->wellFormed = 0; if (sep != NULL) { /* Note: sax2 flag will be set due to the magic number in `initialized` in php_xml_compat_handlers */ From a66afbbe09e91fcbd7d65a9b6d03a0af19aeb778 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 6 Jul 2024 13:46:42 +0200 Subject: [PATCH 41/57] NEWS for compatibility in XML Closes GH-14836. --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 74c017b3fbf1c..883b3c162b163 100644 --- a/NEWS +++ b/NEWS @@ -46,6 +46,9 @@ PHP NEWS - Treewide: . Fix compatibility with libxml2 2.13.2. (nielsdos) +- XML: + . Move away from to-be-deprecated libxml fields. (nielsdos) + 04 Jul 2024, PHP 8.2.21 - Core: From 67259e451d5d58b4842776c5696a66d74e157609 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 5 Jul 2024 23:34:09 +0200 Subject: [PATCH 42/57] Fix GH-14834: Error installing PHP when --with-pear is used libxml2 2.13 makes changes to how the parsing state is set, update our code accordingly. In particular, it started reporting entities within attributes, while it should only report entities inside text nodes. Closes GH-14837. --- NEWS | 2 ++ ext/xml/compat.c | 2 +- ext/xml/tests/gh14834.phpt | 29 +++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 ext/xml/tests/gh14834.phpt diff --git a/NEWS b/NEWS index 883b3c162b163..d382469764cd9 100644 --- a/NEWS +++ b/NEWS @@ -48,6 +48,8 @@ PHP NEWS - XML: . Move away from to-be-deprecated libxml fields. (nielsdos) + . Fixed bug GH-14834 (Error installing PHP when --with-pear is used). + (nielsdos) 04 Jul 2024, PHP 8.2.21 diff --git a/ext/xml/compat.c b/ext/xml/compat.c index 242cc4ba7c40c..5f55dc62b3687 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -375,7 +375,7 @@ _get_entity(void *user, const xmlChar *name) if (ret == NULL) ret = xmlGetDocEntity(parser->parser->myDoc, name); - if (ret == NULL || (parser->parser->instate != XML_PARSER_ENTITY_VALUE && parser->parser->instate != XML_PARSER_ATTRIBUTE_VALUE)) { + if (ret == NULL || parser->parser->instate == XML_PARSER_CONTENT) { if (ret == NULL || ret->etype == XML_INTERNAL_GENERAL_ENTITY || ret->etype == XML_INTERNAL_PARAMETER_ENTITY || ret->etype == XML_INTERNAL_PREDEFINED_ENTITY) { /* Predefined entities will expand unless no cdata handler is present */ if (parser->h_default && ! (ret && ret->etype == XML_INTERNAL_PREDEFINED_ENTITY && parser->h_cdata)) { diff --git a/ext/xml/tests/gh14834.phpt b/ext/xml/tests/gh14834.phpt new file mode 100644 index 0000000000000..2781ba2ed0941 --- /dev/null +++ b/ext/xml/tests/gh14834.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-14834 (Error installing PHP when --with-pear is used) +--EXTENSIONS-- +xml +--FILE-- + + +]> + + &foo; + +XML; + +$parser = xml_parser_create(); +xml_set_character_data_handler($parser, function($_, $data) { + var_dump($data); +}); +xml_parse($parser, $xml, true); +?> +--EXPECT-- +string(3) " + " +string(3) "ent" +string(7) " & " +string(1) " +" From 0b6289dab85ba0f08a3bd377eb884f30947c6a2f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 6 Jul 2024 14:41:44 +0200 Subject: [PATCH 43/57] [ci skip] Test is for libxml only --- ext/xml/tests/gh14834.phpt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ext/xml/tests/gh14834.phpt b/ext/xml/tests/gh14834.phpt index 2781ba2ed0941..1b7dfd1575722 100644 --- a/ext/xml/tests/gh14834.phpt +++ b/ext/xml/tests/gh14834.phpt @@ -2,6 +2,11 @@ GH-14834 (Error installing PHP when --with-pear is used) --EXTENSIONS-- xml +--SKIPIF-- + --FILE-- Date: Wed, 3 Jul 2024 22:07:38 +0100 Subject: [PATCH 44/57] Fix GH-14774 time_sleep_until overflow. --- NEWS | 1 + ext/standard/basic_functions.c | 6 ++++++ ext/standard/tests/misc/gh14774.phpt | 23 +++++++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 ext/standard/tests/misc/gh14774.phpt diff --git a/NEWS b/NEWS index d382469764cd9..f99079d04dbc8 100644 --- a/NEWS +++ b/NEWS @@ -42,6 +42,7 @@ PHP NEWS - Standard: . Fix 32-bit wordwrap test failures. (orlitzky) + . Fixed bug GH-14774 (time_sleep_until overflow). (David Carlier) - Treewide: . Fix compatibility with libxml2 2.13.2. (nielsdos) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index b4a723a546818..a368d0ac7f269 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1228,6 +1228,7 @@ PHP_FUNCTION(time_sleep_until) struct timespec php_req, php_rem; uint64_t current_ns, target_ns, diff_ns; const uint64_t ns_per_sec = 1000000000; + const double top_target_sec = (double)(UINT64_MAX / ns_per_sec); ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_DOUBLE(target_secs) @@ -1237,6 +1238,11 @@ PHP_FUNCTION(time_sleep_until) RETURN_FALSE; } + if (UNEXPECTED(!(target_secs >= 0 && target_secs <= top_target_sec))) { + zend_argument_value_error(1, "must be between 0 and %" PRIu64, (uint64_t)top_target_sec); + RETURN_THROWS(); + } + target_ns = (uint64_t) (target_secs * ns_per_sec); current_ns = ((uint64_t) tm.tv_sec) * ns_per_sec + ((uint64_t) tm.tv_usec) * 1000; if (target_ns < current_ns) { diff --git a/ext/standard/tests/misc/gh14774.phpt b/ext/standard/tests/misc/gh14774.phpt new file mode 100644 index 0000000000000..1f9cd921e03a6 --- /dev/null +++ b/ext/standard/tests/misc/gh14774.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-14774 time_sleep_until overflow +--SKIPIF-- + +--FILE-- +getMessage() . PHP_EOL; + } +} +?> +--EXPECTF-- +time_sleep_until(): Argument #1 ($timestamp) must be between 0 and %d +time_sleep_until(): Argument #1 ($timestamp) must be between 0 and %d +time_sleep_until(): Argument #1 ($timestamp) must be between 0 and %d +time_sleep_until(): Argument #1 ($timestamp) must be between 0 and %d +time_sleep_until(): Argument #1 ($timestamp) must be between 0 and %d +time_sleep_until(): Argument #1 ($timestamp) must be between 0 and %d From 0d4e0c013ec088640580662822f6e37e65df8955 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 6 Jul 2024 22:46:27 +0200 Subject: [PATCH 45/57] Fix GH-14639: Member access within null pointer in ext/spl/spl_observer.c `spl_object_storage_attach_handle` creates an entry already, but only fills it in at the end with `spl_object_storage_create_element` which allocates memory. In this case the allocation fails and we're left with a NULL slot. Doing the allocation first isn't an option because we want to check whether the slot is occupied before allocating memory. The simplest solution is to set the entry to NULL and check for a NULL pointer upon destruction. Closes GH-14849. --- NEWS | 4 ++++ ext/spl/spl_observer.c | 12 ++++++++---- ext/spl/tests/gh14639.phpt | 21 +++++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 ext/spl/tests/gh14639.phpt diff --git a/NEWS b/NEWS index f99079d04dbc8..9c6a61c624848 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,10 @@ PHP NEWS . Fixed bug GH-14638 (null dereference after XML parsing failure). (David Carlier) +- SPL: + . Fixed bug GH-14639 (Member access within null pointer in + ext/spl/spl_observer.c). (nielsdos) + - Standard: . Fix 32-bit wordwrap test failures. (orlitzky) . Fixed bug GH-14774 (time_sleep_until overflow). (David Carlier) diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 339bd0b6e5d22..21b19cffa38ad 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -118,9 +118,11 @@ static void spl_object_storage_free_hash(spl_SplObjectStorage *intern, zend_hash static void spl_object_storage_dtor(zval *element) /* {{{ */ { spl_SplObjectStorageElement *el = Z_PTR_P(element); - zend_object_release(el->obj); - zval_ptr_dtor(&el->inf); - efree(el); + if (el) { + zend_object_release(el->obj); + zval_ptr_dtor(&el->inf); + efree(el); + } } /* }}} */ static spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, zend_hash_key *key) /* {{{ */ @@ -168,8 +170,10 @@ static spl_SplObjectStorageElement *spl_object_storage_attach_handle(spl_SplObje return pelement; } + /* NULL initialization necessary because `spl_object_storage_create_element` could bail out due to OOM. */ + ZVAL_PTR(entry_zv, NULL); pelement = spl_object_storage_create_element(obj, inf); - ZVAL_PTR(entry_zv, pelement); + Z_PTR_P(entry_zv) = pelement; return pelement; } /* }}} */ diff --git a/ext/spl/tests/gh14639.phpt b/ext/spl/tests/gh14639.phpt new file mode 100644 index 0000000000000..1b6f621d27bd3 --- /dev/null +++ b/ext/spl/tests/gh14639.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-14639 (Member access within null pointer in ext/spl/spl_observer.c) +--INI-- +memory_limit=2M +--SKIPIF-- + +--FILE-- + 0; $i--) { + $object = new StdClass(); + $object->a = str_repeat("a", 2); + $b->attach($object); +} +?> +--EXPECTF-- +Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d From b44ad27a7828db6e2699fd56184d056e349d2f3b Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 6 Jul 2024 21:39:32 +0200 Subject: [PATCH 46/57] Fix GH-14550: No warning message when Zend DTrace is enabled that opcache.jit is implictly disabled Closes GH-14847. --- NEWS | 4 ++++ ext/opcache/jit/zend_jit.c | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 9c6a61c624848..75d98e0b53639 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,10 @@ PHP NEWS - LibXML: . Fixed bug GH-14563 (Build failure with libxml2 v2.13.0). (nielsdos) +- Opcache: + . Fixed bug GH-14550 (No warning message when Zend DTrace is enabled that + opcache.jit is implictly disabled). (nielsdos) + - Output: . Fixed bug GH-14808 (Unexpected null pointer in Zend/zend_string.h with empty output buffer). (nielsdos) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 7ff691b3c9b4b..ce091509785d6 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -4877,7 +4877,9 @@ ZEND_EXT_API int zend_jit_check_support(void) } if (zend_execute_ex != execute_ex) { - if (strcmp(sapi_module.name, "phpdbg") != 0) { + if (zend_dtrace_enabled) { + zend_error(E_WARNING, "JIT is incompatible with DTrace. JIT disabled."); + } else if (strcmp(sapi_module.name, "phpdbg") != 0) { zend_error(E_WARNING, "JIT is incompatible with third party extensions that override zend_execute_ex(). JIT disabled."); } JIT_G(enabled) = 0; From c34def581a99f0591ee21802e21684e754f34544 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 7 Jul 2024 21:53:58 +0200 Subject: [PATCH 47/57] Fix memory leak in tidy_repair_file() When dealing with a file, we must free the contents if the function fails. While here, also fix the error message because previously it sounded like the filename was too long while in fact the file itself is too large. Closes GH-14862. --- NEWS | 3 +++ ext/tidy/tests/parsing_file_too_large.phpt | 7 +++++++ ext/tidy/tidy.c | 7 ++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 75d98e0b53639..411c5de823e17 100644 --- a/NEWS +++ b/NEWS @@ -52,6 +52,9 @@ PHP NEWS . Fix 32-bit wordwrap test failures. (orlitzky) . Fixed bug GH-14774 (time_sleep_until overflow). (David Carlier) +- Tidy: + . Fix memory leak in tidy_repair_file(). (nielsdos) + - Treewide: . Fix compatibility with libxml2 2.13.2. (nielsdos) diff --git a/ext/tidy/tests/parsing_file_too_large.phpt b/ext/tidy/tests/parsing_file_too_large.phpt index 46196c0a5fdce..a0118ba9ebdce 100644 --- a/ext/tidy/tests/parsing_file_too_large.phpt +++ b/ext/tidy/tests/parsing_file_too_large.phpt @@ -47,6 +47,12 @@ try { } catch (\Throwable $e) { echo $e::class, ': ', $e->getMessage(), PHP_EOL; } + +try { + tidy_repair_file($path); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> --CLEAN-- Date: Mon, 8 Jul 2024 15:03:13 -0300 Subject: [PATCH 48/57] Declare that this test needs iconv extension Otherwise it would fail with the usual recommended ./configure invocation used for RMs testing (i.e. --disable-all). --- tests/output/gh14808.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/output/gh14808.phpt b/tests/output/gh14808.phpt index 7a3f57ba51c5d..32addcbc76370 100644 --- a/tests/output/gh14808.phpt +++ b/tests/output/gh14808.phpt @@ -1,5 +1,7 @@ --TEST-- GH-14808 (Unexpected null pointer in Zend/zend_string.h with empty output buffer) +--EXTENSIONS-- +iconv --FILE-- Date: Tue, 9 Jul 2024 00:14:28 +0200 Subject: [PATCH 49/57] Fix GH-14741: Segmentation fault in Zend/zend_types.h The create_obj handler of InternalIterator is overwritten, but not the clone_obj handler. This is not allowed. In PHP 8.2 this didn't cause a segfault because the standard object handler was used for the clone instead of the internal handler. So then it allocates and frees the object using the standard object handlers. In 8.3 however, the object is created using the standard object handler and freed using the custom handler, resulting in the buffer overflow. Even though bisect points to 1e1ea4f this only reveals the bug. Closes GH-14882. --- NEWS | 1 + Zend/zend_interfaces.c | 1 + ext/zend_test/tests/gh14741.phpt | 17 +++++++++++++++++ 3 files changed, 19 insertions(+) create mode 100644 ext/zend_test/tests/gh14741.phpt diff --git a/NEWS b/NEWS index 411c5de823e17..db78d1404db09 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ PHP NEWS . Fixed bug GH-14590 (Memory leak in FPM test gh13563-conf-bool-env.phpt. (nielsdos) . Fixed OSS-Fuzz #69765. (nielsdos) + . Fixed bug GH-14741 (Segmentation fault in Zend/zend_types.h). (nielsdos) - Dom: . Fixed bug GH-14702 (DOMDocument::xinclude() crash). (nielsdos) diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 42fbccd4a746f..b8cc5e94caca8 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -666,6 +666,7 @@ ZEND_API void zend_register_interfaces(void) memcpy(&zend_internal_iterator_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + zend_internal_iterator_handlers.clone_obj = NULL; zend_internal_iterator_handlers.free_obj = zend_internal_iterator_free; } /* }}} */ diff --git a/ext/zend_test/tests/gh14741.phpt b/ext/zend_test/tests/gh14741.phpt new file mode 100644 index 0000000000000..389692f3de2bd --- /dev/null +++ b/ext/zend_test/tests/gh14741.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-14741 (Segmentation fault in Zend/zend_types.h) +--EXTENSIONS-- +zend_test +--FILE-- +getIterator(); +try { + clone $it; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +Trying to clone an uncloneable object of class InternalIterator +TraversableTest::drop From 09957ab9a874f90cc4769622c856adca0c6d216c Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Wed, 10 Jul 2024 08:20:31 -0400 Subject: [PATCH 50/57] ext/gd/tests/gh10614.phpt: skip if no PNG support This test uses imagecreatefrompng(), which won't be there if libgd was built without PNG support. Closes GH-14905. --- NEWS | 3 +++ ext/gd/tests/gh10614.phpt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/NEWS b/NEWS index db78d1404db09..7cb1737412748 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,9 @@ PHP NEWS - Dom: . Fixed bug GH-14702 (DOMDocument::xinclude() crash). (nielsdos) +- Gd: + . ext/gd/tests/gh10614.phpt: skip if no PNG support. (orlitzky) + - LibXML: . Fixed bug GH-14563 (Build failure with libxml2 v2.13.0). (nielsdos) diff --git a/ext/gd/tests/gh10614.phpt b/ext/gd/tests/gh10614.phpt index c0689141837cd..1b91115d748d2 100644 --- a/ext/gd/tests/gh10614.phpt +++ b/ext/gd/tests/gh10614.phpt @@ -5,6 +5,9 @@ gd --SKIPIF-- =')) die("skip test requires GD 2.3.4 or older"); +if (!(imagetypes() & IMG_PNG)) { + die("skip No PNG support"); +} ?> --FILE-- Date: Thu, 11 Jul 2024 14:09:40 +0200 Subject: [PATCH 51/57] Fix GH-14888: README.REDIST.BINS refers to non-existing LICENSE [ci skip] The LICENSE file of libmagic had been inadvertently removed when the lib had been upgraded to 5.43. So we add the file `COPYING` from that release[1], and rename it to `LICENSE`. [1] Closes GH-14917. --- NEWS | 4 ++++ ext/fileinfo/libmagic/LICENSE | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 ext/fileinfo/libmagic/LICENSE diff --git a/NEWS b/NEWS index 0f87ee43bfe2b..a7c4f1cea92a4 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,10 @@ PHP NEWS - Dom: . Fixed bug GH-14702 (DOMDocument::xinclude() crash). (nielsdos) +- Fileinfo: + . Fixed bug GH-14888 (README.REDIST.BINS refers to non-existing LICENSE). + (cmb) + - Gd: . ext/gd/tests/gh10614.phpt: skip if no PNG support. (orlitzky) diff --git a/ext/fileinfo/libmagic/LICENSE b/ext/fileinfo/libmagic/LICENSE new file mode 100644 index 0000000000000..16410a17f2f5b --- /dev/null +++ b/ext/fileinfo/libmagic/LICENSE @@ -0,0 +1,29 @@ +$File: COPYING,v 1.2 2018/09/09 20:33:28 christos Exp $ +Copyright (c) Ian F. Darwin 1986, 1987, 1989, 1990, 1991, 1992, 1994, 1995. +Software written by Ian F. Darwin and others; +maintained 1994- Christos Zoulas. + +This software is not subject to any export provision of the United States +Department of Commerce, and may be exported to any country or planet. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice immediately at the beginning of the file, without modification, + this list of conditions, and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. From 38501ed48a6a8d9ad57605d6a49e796230ac4b42 Mon Sep 17 00:00:00 2001 From: Joe Cai Date: Fri, 12 Jul 2024 20:13:44 +1000 Subject: [PATCH 52/57] Fix GH-14930: Custom stream wrapper dir_readdir output truncated to 255 characters in PHP 8.3 Revert "Reserve less file space if possible in a directory entry" This reverts commit 00c1e7bf0f1c7244589ce8756f0367497cf1ce15. Closes GH-14933. --- NEWS | 4 ++++ ext/standard/tests/streams/gh14930.phpt | 27 +++++++++++++++++++++++++ main/php_streams.h | 4 ---- 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 ext/standard/tests/streams/gh14930.phpt diff --git a/NEWS b/NEWS index a7c4f1cea92a4..930bc31864407 100644 --- a/NEWS +++ b/NEWS @@ -58,6 +58,10 @@ PHP NEWS . Fix 32-bit wordwrap test failures. (orlitzky) . Fixed bug GH-14774 (time_sleep_until overflow). (David Carlier) +- Streams: + . Fixed bug GH-14930 (Custom stream wrapper dir_readdir output truncated to + 255 characters in PHP 8.3). (Joe Cai) + - Tidy: . Fix memory leak in tidy_repair_file(). (nielsdos) diff --git a/ext/standard/tests/streams/gh14930.phpt b/ext/standard/tests/streams/gh14930.phpt new file mode 100644 index 0000000000000..7e034a81235a7 --- /dev/null +++ b/ext/standard/tests/streams/gh14930.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-14930: Custom stream wrapper dir_readdir output truncated to 255 characters in PHP 8.3 +--FILE-- + +--EXPECT-- +string(288) "very-long-filename-ieNoquiaC6ijeiy9beejaiphoriejo2cheehooGou8uhoh7eh0gefahyuQuohd7eec9auso9eeFah2Maedohsemi1eetoo5fo5biePh5eephai7SiuguipouLeemequ2oope9aigoQu5efak2aLeri9ithaiJ9eew3dianaiHoo1aexaighiitee6geghiequ5nohhiikahwee8ohk2Soip2Aikeithohdeitiedeiku7DiTh2eep3deitiedeiku7DiTh2ee.txt" diff --git a/main/php_streams.h b/main/php_streams.h index 31b80de986053..33b14ff4eb3df 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -107,11 +107,7 @@ typedef struct _php_stream_statbuf { } php_stream_statbuf; typedef struct _php_stream_dirent { -#ifdef NAME_MAX - char d_name[NAME_MAX + 1]; -#else char d_name[MAXPATHLEN]; -#endif unsigned char d_type; } php_stream_dirent; From b456ae8d34bbdd6bb50c789ec92ded39a6fdb4f5 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Thu, 21 Mar 2024 13:22:46 +0300 Subject: [PATCH 53/57] Restore Warning instead of Fatal Error in gd_webp.c According to the docs (https://www.php.net/manual/en/function.imagecreatefromwebp.php and https://www.php.net/manual/en/function.imagewebp.php), `false` should be returned on errors (similar to other functions of the `gd` extension), but actually all errors result in a `Fatal Error`. It doesn't look normal when trying to read an empty file or a file in the wrong format causes the program to stop. The problem seems to be related to a mega-patch that replaced `zend_error` with `zend_error_noreturn` almost everywhere. My patch fixes this behavior by switching from `zend_error_noerror` to `gd_error` (i.e. to `E_WARNING` level). All necessary memory cleanup is already in the code (as it was before the "zend_error_noreturn" patch). Close GH-13774 --- NEWS | 1 + ext/gd/libgd/gd_webp.c | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 7cb1737412748..d5aa0983d597f 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,7 @@ PHP NEWS - Gd: . ext/gd/tests/gh10614.phpt: skip if no PNG support. (orlitzky) + . restored warning instead of fata error. (dryabov) - LibXML: . Fixed bug GH-14563 (Build failure with libxml2 v2.13.0). (nielsdos) diff --git a/ext/gd/libgd/gd_webp.c b/ext/gd/libgd/gd_webp.c index a0d8a0cf49f5c..4e270db150179 100644 --- a/ext/gd/libgd/gd_webp.c +++ b/ext/gd/libgd/gd_webp.c @@ -3,6 +3,7 @@ #include #include #include "gd.h" +#include "gd_errors.h" #include "gdhelpers.h" #ifdef HAVE_LIBWEBP @@ -56,7 +57,7 @@ gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile) if (filedata) { gdFree(filedata); } - zend_error(E_ERROR, "WebP decode: realloc failed"); + gd_error("WebP decode: realloc failed"); return NULL; } @@ -67,7 +68,7 @@ gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile) } while (n>0 && n!=EOF); if (WebPGetInfo(filedata,size, &width, &height) == 0) { - zend_error(E_ERROR, "gd-webp cannot get webp info"); + gd_error("gd-webp cannot get webp info"); gdFree(filedata); return NULL; } @@ -79,7 +80,7 @@ gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile) } argb = WebPDecodeARGB(filedata, size, &width, &height); if (!argb) { - zend_error(E_ERROR, "gd-webp cannot allocate temporary buffer"); + gd_error("gd-webp cannot allocate temporary buffer"); gdFree(filedata); gdImageDestroy(im); return NULL; @@ -113,7 +114,7 @@ void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality) } if (!gdImageTrueColor(im)) { - zend_error(E_ERROR, "Palette image not supported by webp"); + gd_error("Palette image not supported by webp"); return; } @@ -159,7 +160,7 @@ void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality) } if (out_size == 0) { - zend_error(E_ERROR, "gd-webp encoding failed"); + gd_error("gd-webp encoding failed"); goto freeargb; } gdPutBuf(out, out_size, outfile); From 6d0db528962bb29df71a368aa4dbfa10511b5418 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sat, 13 Jul 2024 19:19:44 +0200 Subject: [PATCH 54/57] Add test case for GH-13774 Besides demonstrating the new behavior, this test also ensures that the bundled and external libgd now behave the same. It has to be noted, though, that we only test one of the five code paths. Closes GH-14945. --- ext/gd/tests/gh13774.phpt | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 ext/gd/tests/gh13774.phpt diff --git a/ext/gd/tests/gh13774.phpt b/ext/gd/tests/gh13774.phpt new file mode 100644 index 0000000000000..8245564efbad8 --- /dev/null +++ b/ext/gd/tests/gh13774.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-13774 (Restore Warning instead of Fatal Error in gd_webp.c) +--EXTENSIONS-- +gd +--SKIPIF-- + +--FILE-- + +--CLEAN-- + +--EXPECTF-- +Warning: imagecreatefromwebp(): gd-webp cannot get webp info in %s on line %d + +Warning: imagecreatefromwebp(): "%s" is not a valid WEBP file in %s on line %d +bool(false) From 02a60be24d80484aa59d0f55f2a8da77faafe3b9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 11 Jul 2024 18:12:38 +0200 Subject: [PATCH 55/57] Fix skip condition of gh13082.phpt The test failure is not particularly related to Travis, but rather is caused by the GD font file to only be suitable for platforms where `int` stores 32bit values in little endian byte order. This platform dependence is documented in the source code[1]. Thus we fix the skip condition and skip reason accordingly. An alternative would be to dynamically create the font file just before running the test, but that appears to be overkill. [1] Closes GH-14922. --- ext/gd/tests/gh13082.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/gd/tests/gh13082.phpt b/ext/gd/tests/gh13082.phpt index edfca9d850fdc..4289040adf63f 100644 --- a/ext/gd/tests/gh13082.phpt +++ b/ext/gd/tests/gh13082.phpt @@ -3,7 +3,7 @@ GH-13082 - imagefontwidth/height unexpectedly throwing an exception on a valid G --EXTENSIONS-- gd --SKIPIF-- - + --FILE-- Date: Tue, 16 Jul 2024 11:55:55 +0200 Subject: [PATCH 56/57] Fix use-after-free in property coercion with __toString() This was only partially fixed in PHP-8.3. Backports and fixes the case for both initialized and uninitialized property writes. Fixes GH-14969 Closes GH-14971 --- NEWS | 2 ++ Zend/tests/gh14969.phpt | 47 +++++++++++++++++++++++++++++++++++++ Zend/zend_object_handlers.c | 4 ++-- 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/gh14969.phpt diff --git a/NEWS b/NEWS index d5aa0983d597f..2276e3ff22b69 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS (nielsdos) . Fixed OSS-Fuzz #69765. (nielsdos) . Fixed bug GH-14741 (Segmentation fault in Zend/zend_types.h). (nielsdos) + . Fixed bug GH-14969 (Use-after-free in property coercion with __toString()). + (ilutov) - Dom: . Fixed bug GH-14702 (DOMDocument::xinclude() crash). (nielsdos) diff --git a/Zend/tests/gh14969.phpt b/Zend/tests/gh14969.phpt new file mode 100644 index 0000000000000..dedbaa7456e00 --- /dev/null +++ b/Zend/tests/gh14969.phpt @@ -0,0 +1,47 @@ +--TEST-- +GH-14969: Crash on coercion with throwing __toString() +--FILE-- +prop = $c; +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} +var_dump($d); + +$c = new C(); +$d->prop = 'foo'; +try { + $d->prop = $c; +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} +var_dump($d); + +?> +--EXPECTF-- +C::__toString +object(D)#%d (0) { + ["prop"]=> + uninitialized(string) +} +C::__toString +object(D)#2 (1) { + ["prop"]=> + string(3) "foo" +} diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 58301da038ce0..d4586e53e4b4a 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -819,7 +819,7 @@ ZEND_API zval *zend_std_write_property(zend_object *zobj, zend_string *name, zva ZVAL_COPY_VALUE(&tmp, value); if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, property_uses_strict_types()))) { - Z_TRY_DELREF_P(value); + zval_ptr_dtor(&tmp); variable_ptr = &EG(error_zval); goto exit; } @@ -890,7 +890,7 @@ ZEND_API zval *zend_std_write_property(zend_object *zobj, zend_string *name, zva ZVAL_COPY_VALUE(&tmp, value); if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, property_uses_strict_types()))) { - zval_ptr_dtor(value); + zval_ptr_dtor(&tmp); goto exit; } value = &tmp; From ace55c8f67f57a2aa1c357e2ce9da5f349a11fbb Mon Sep 17 00:00:00 2001 From: Eric Mann Date: Tue, 30 Jul 2024 06:44:37 -0700 Subject: [PATCH 57/57] Update versions for PHP 8.3.10 --- NEWS | 2 +- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 4c6cbbb8ca310..5d1e07bf8eaf2 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.3.10 +01 Aug 2024, PHP 8.3.10 - Core: . Fixed bug GH-13922 (Fixed support for systems with diff --git a/Zend/zend.h b/Zend/zend.h index 7b375c58067fd..dbfd54c2c95e1 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.3.10-dev" +#define ZEND_VERSION "4.3.10" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 0f9526cc0a52f..8599086e1ddda 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.3.10-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.3.10],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index afe90c887c4e2..a0988355140e4 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -3,6 +3,6 @@ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 3 #define PHP_RELEASE_VERSION 10 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.3.10-dev" +#define PHP_EXTRA_VERSION "" +#define PHP_VERSION "8.3.10" #define PHP_VERSION_ID 80310