From 1b45efb6fb9dd37c2c6f2079ba2ab851f12e84e0 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 14 Jun 2022 10:20:45 +0300 Subject: [PATCH 001/440] Fix type inference This fixes oss-fuzz #47920 --- Zend/Optimizer/zend_inference.c | 2 +- ext/opcache/tests/opt/inference_010.phpt | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/opt/inference_010.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index d27e5fd0f0a53..4d29b65325ab1 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -3227,7 +3227,7 @@ static zend_always_inline int _zend_update_type_info( tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN); } if (opline->op2_type == IS_UNUSED) { - if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL)) { + if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { key_type |= MAY_BE_ARRAY_PACKED; } if (t1 & MAY_BE_ARRAY) { diff --git a/ext/opcache/tests/opt/inference_010.phpt b/ext/opcache/tests/opt/inference_010.phpt new file mode 100644 index 0000000000000..b07362ccfe51d --- /dev/null +++ b/ext/opcache/tests/opt/inference_010.phpt @@ -0,0 +1,18 @@ +--TEST-- +Type inference 010: FRTCH_DIM_W +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECTF-- +Deprecated: Automatic conversion of false to array is deprecated in %sinference_010.php on line 4 +DONE From 729be469ae1c50251607b8978647f8b510b45b46 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 14 Jun 2022 11:59:35 +0300 Subject: [PATCH 002/440] Fix type inference This dixes oss-fuzz #47921 --- Zend/Optimizer/zend_inference.c | 20 +++++++++++++++----- ext/opcache/tests/opt/inference_011.phpt | 17 +++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 ext/opcache/tests/opt/inference_011.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 4d29b65325ab1..867d2a5ddb578 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -3231,20 +3231,30 @@ static zend_always_inline int _zend_update_type_info( key_type |= MAY_BE_ARRAY_PACKED; } if (t1 & MAY_BE_ARRAY) { - key_type |= (MAY_BE_HASH_ONLY(t1) || (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE))) ? + key_type |= MAY_BE_HASH_ONLY(t1) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; } } else { if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) { - key_type |= (MAY_BE_HASH_ONLY(t1) || (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE))) ? - MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; + if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { + key_type |= MAY_BE_ARRAY_PACKED; + } + if (t1 & MAY_BE_ARRAY) { + key_type |= MAY_BE_HASH_ONLY(t1) ? + MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; + } } if (t2 & MAY_BE_STRING) { key_type |= MAY_BE_ARRAY_KEY_STRING; if (opline->op2_type != IS_CONST) { // FIXME: numeric string - key_type |= (MAY_BE_HASH_ONLY(t1) || (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE))) ? - MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; + if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { + key_type |= MAY_BE_ARRAY_PACKED; + } + if (t1 & MAY_BE_ARRAY) { + key_type |= MAY_BE_HASH_ONLY(t1) ? + MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; + } } } if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) { diff --git a/ext/opcache/tests/opt/inference_011.phpt b/ext/opcache/tests/opt/inference_011.phpt new file mode 100644 index 0000000000000..58f7078b61eda --- /dev/null +++ b/ext/opcache/tests/opt/inference_011.phpt @@ -0,0 +1,17 @@ +--TEST-- +Type inference 011: FETCH_DIM_FUNC_ARG +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECTF-- +DONE From 0b8e471b3c358271a5316196bf9f370039d965c4 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 14 Jun 2022 12:44:37 +0300 Subject: [PATCH 003/440] Fix use after free This fixes oss-fuzz #47997 --- .../tests/streams/user_streams_context_001.phpt | 15 +++++++++++++++ main/streams/userspace.c | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/streams/user_streams_context_001.phpt diff --git a/ext/standard/tests/streams/user_streams_context_001.phpt b/ext/standard/tests/streams/user_streams_context_001.phpt new file mode 100644 index 0000000000000..c59905cf4bd8a --- /dev/null +++ b/ext/standard/tests/streams/user_streams_context_001.phpt @@ -0,0 +1,15 @@ +--TEST-- +User streams and incrrectly typed context +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught TypeError: Cannot assign resource to property Wrapper::$context of type Foo in %suser_streams_context_001.php:5 +Stack trace: +#0 %suser_streams_context_001.php(5): dir('foo://') +#1 {main} + thrown in %suser_streams_context_001.php on line 5 diff --git a/main/streams/userspace.c b/main/streams/userspace.c index 271d0cdffbecc..5f9a5c4221193 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -289,8 +289,8 @@ static void user_stream_create_object(struct php_user_stream_wrapper *uwrap, php } if (context) { - add_property_resource(object, "context", context->res); GC_ADDREF(context->res); + add_property_resource(object, "context", context->res); } else { add_property_null(object, "context"); } From 03e72e7a878fc9adca2d9a0276f9c9a9cf6aa0ad Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 14 Jun 2022 11:42:24 +0200 Subject: [PATCH 004/440] Update curl/tests/check_win_config.phpt That was apparently missed in cec20f615db844f1b77a5685ad266452602a98a3. --- ext/curl/tests/check_win_config.phpt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ext/curl/tests/check_win_config.phpt b/ext/curl/tests/check_win_config.phpt index a8dc4252d2fae..b3beb044a7cfc 100644 --- a/ext/curl/tests/check_win_config.phpt +++ b/ext/curl/tests/check_win_config.phpt @@ -48,6 +48,12 @@ PSL => No HTTPS_PROXY => Yes MULTI_SSL => %s BROTLI => %s +ALTSVC => Yes +HTTP3 => No +UNICODE => No +ZSTD => No +HSTS => Yes +GSASL => No Protocols => dict, file, ftp, ftps, gopher, %r(gophers, )?%rhttp, https, imap, imaps, ldap, ldaps, %r(mqtt, )?%rpop3, pop3s, rtsp, scp, sftp, smb, smbs, smtp, smtps, telnet, tftp Host => %s-pc-win32 SSL Version => OpenSSL/%s From 3a29c2e15467fd20102ad1ccba86722dfbd389e6 Mon Sep 17 00:00:00 2001 From: jcm Date: Mon, 13 Jun 2022 19:55:28 +0200 Subject: [PATCH 005/440] Add test for iconv_mime_encode() for input-charset and output-charset Closes GH-8766. --- ext/iconv/tests/iconv_mime_encode_001.phpt | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 ext/iconv/tests/iconv_mime_encode_001.phpt diff --git a/ext/iconv/tests/iconv_mime_encode_001.phpt b/ext/iconv/tests/iconv_mime_encode_001.phpt new file mode 100644 index 0000000000000..f4d9469eeaaae --- /dev/null +++ b/ext/iconv/tests/iconv_mime_encode_001.phpt @@ -0,0 +1,33 @@ +--TEST-- +iconv_mime_encode(): Encoding parameter exceeds the maximum allowed for preference "input-charset" and "output-charset" +--EXTENSIONS-- +iconv +--INI-- +iconv.internal_charset=iso-8859-1 +--FILE-- + "ISO-8859-1".$extra, + "output-charset" => "UTF-8", + "line-length" => 76, + "line-break-chars" => "\n", + "scheme" => "B" +]; + +$result = iconv_mime_encode("Subject", "Prüfung", $preferences); +var_dump($result); + +$preferences["input-charset"] = "ISO-8859-1"; +$preferences["output-charset"] = "UTF-8".$extra; + +$result = iconv_mime_encode("Subject", "Prüfung", $preferences); +var_dump($result); +?> +--EXPECTF-- +Warning: iconv_mime_encode(): Encoding parameter exceeds the maximum allowed length of %d characters in %s on line %d +bool(false) + +Warning: iconv_mime_encode(): Encoding parameter exceeds the maximum allowed length of %d characters in %s on line %d +bool(false) From 1cd8074743d1a13529cf2dbd72bfb2b0ea0ffe25 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 14 Jun 2022 13:57:44 +0300 Subject: [PATCH 006/440] JIT: Fix missing register store This fixes oss-fuzz #48023 --- ext/opcache/jit/zend_jit_x86.dasc | 10 ++++++++++ ext/opcache/tests/jit/reg_alloc_015.phpt | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 ext/opcache/tests/jit/reg_alloc_015.phpt diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 3bde0e59b6281..c907e7ee1c2df 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -3967,6 +3967,16 @@ static int zend_jit_update_regs(dasm_State **Dst, uint32_t var, zend_jit_addr sr } else { ZEND_UNREACHABLE(); } + } else if (Z_MODE(dst) == IS_REG && Z_STORE(dst)) { + dst = ZEND_ADDR_MEM_ZVAL(ZREG_FP, var); + if (!zend_jit_spill_store(Dst, src, dst, info, + JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE || + JIT_G(current_frame) == NULL || + STACK_MEM_TYPE(JIT_G(current_frame)->stack, EX_VAR_TO_NUM(var)) == IS_UNKNOWN || + (1 << STACK_MEM_TYPE(JIT_G(current_frame)->stack, EX_VAR_TO_NUM(var))) != (info & MAY_BE_ANY) + )) { + return 0; + } } return 1; } diff --git a/ext/opcache/tests/jit/reg_alloc_015.phpt b/ext/opcache/tests/jit/reg_alloc_015.phpt new file mode 100644 index 0000000000000..579b34dadcc70 --- /dev/null +++ b/ext/opcache/tests/jit/reg_alloc_015.phpt @@ -0,0 +1,22 @@ +--TEST-- +Register Alloction 015: Missing store +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +> -$y; + } +} +foo() +?> +DONE +--EXPECTF-- +Warning: Undefined variable $y in %sreg_alloc_015.php on line 3 + +Warning: Undefined variable $y in %sreg_alloc_015.php on line 3 +DONE From 971b07ea60172a80ee308e91c7a7912eea8a571f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 14 Jun 2022 15:03:50 +0300 Subject: [PATCH 007/440] JIT: Fix incorrect reference-counting This fixes oss-fuzz #47937 --- ext/opcache/jit/zend_jit_helpers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 0f312fb415cd9..f953d704ca090 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -811,7 +811,7 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_rw_helper(zend_array *ht, zval *di opline = EX(opline); zend_incompatible_double_to_long_error(Z_DVAL_P(dim)); if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) { - if (GC_REFCOUNT(ht)) { + if (!GC_REFCOUNT(ht)) { zend_array_destroy(ht); } if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { @@ -841,7 +841,7 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_rw_helper(zend_array *ht, zval *di opline = EX(opline); zend_use_resource_as_offset(dim); if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) { - if (GC_REFCOUNT(ht)) { + if (!GC_REFCOUNT(ht)) { zend_array_destroy(ht); } if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { From 390538af2ed5cd18e3096ad70597035dbca52139 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 15 Jun 2022 08:57:17 +0200 Subject: [PATCH 008/440] Fix GH-8781 ZipArchive::close deletes zip file without updating stat cache --- ext/zip/php_zip.c | 3 +++ ext/zip/tests/bug_gh8781.phpt | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 ext/zip/tests/bug_gh8781.phpt diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 14fa3e784ab1f..d00d050204ed5 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -1562,6 +1562,9 @@ PHP_METHOD(ZipArchive, close) ze_obj->err_sys = 0; } + /* clear cache as empty zip are not created but deleted */ + php_clear_stat_cache(1, ze_obj->filename, ze_obj->filename_len); + efree(ze_obj->filename); ze_obj->filename = NULL; ze_obj->filename_len = 0; diff --git a/ext/zip/tests/bug_gh8781.phpt b/ext/zip/tests/bug_gh8781.phpt new file mode 100644 index 0000000000000..25eadb70575df --- /dev/null +++ b/ext/zip/tests/bug_gh8781.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug GH-8781 (ZipArchive deletes zip file with no contents) +--SKIPIF-- + +--FILE-- +open($file, ZipArchive::CREATE | ZipArchive::OVERWRITE); +$zip->close(); + +var_dump(is_file($file)); +?> +--EXPECT-- +bool(true) +bool(false) + From 26feb2e6f26273e3b79ef0505c073fbceac30407 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 15 Jun 2022 15:38:37 +0200 Subject: [PATCH 009/440] NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 10e0e919f0b5c..dfbdd981223a2 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,10 @@ PHP NEWS . Fixed errorInfo() result on successful PDOStatement->execute(). (Yurunsoft) . Fixed handling of single-key connection strings. (Calvin Buckley) +- Zip: + . Fixed bug GH-8781 (ZipArchive::close deletes zip file without updating stat + cache). (Remi) + 09 Jun 2022, PHP 8.0.20 - CLI: From e3c5237b4f8af6eb5b78f5017fb836a36e93b9e1 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 15 Jun 2022 15:39:24 +0200 Subject: [PATCH 010/440] NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 8eb5196ff48fb..490c7f749fed6 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,10 @@ PHP NEWS - PDO_ODBC: . Fixed handling of single-key connection strings. (Calvin Buckley) +- Zip: + . Fixed bug GH-8781 (ZipArchive::close deletes zip file without updating stat + cache). (Remi) + 09 Jun 2022, PHP 8.1.7 - CLI: From 9e9141f7126c507c2790bbbeede5abb99a0dc766 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 15 Jun 2022 17:55:14 +0200 Subject: [PATCH 011/440] Use HTTPS URLs in resource files Although it is unlikely that anybody ever sees these URLs, since they are not shown in the file property sheet, it's overdue to switch to HTTPS. --- win32/build/confutils.js | 4 ++-- win32/build/template.rc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/win32/build/confutils.js b/win32/build/confutils.js index 9bf1bf28141d4..83d4bafdaaab4 100644 --- a/win32/build/confutils.js +++ b/win32/build/confutils.js @@ -1077,7 +1077,7 @@ function generate_version_info_resource(makefiletarget, basename, creditspath, s var thanks = ""; var logo = ""; var debug = ""; - var project_url = "http://www.php.net"; + var project_url = "https://www.php.net"; var project_header = creditspath + "/php_" + basename + ".h"; var versioning = ""; @@ -1105,7 +1105,7 @@ function generate_version_info_resource(makefiletarget, basename, creditspath, s if (creditspath.match(new RegExp("pecl"))) { /* PECL project url - this will eventually work correctly for all */ - project_url = "http://pecl.php.net/" + basename; + project_url = "https://pecl.php.net/" + basename; /* keep independent versioning PECL-specific for now */ if (FSO.FileExists(project_header)) { diff --git a/win32/build/template.rc b/win32/build/template.rc index 15813d4ab93af..602e828f45117 100644 --- a/win32/build/template.rc +++ b/win32/build/template.rc @@ -27,7 +27,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #endif #ifndef URL -#define URL "http://www.php.net/" +#define URL "https://www.php.net/" #endif #ifndef EXT_VERSION From b1223ee35fd0634e15f2ba41976a56454dd233f9 Mon Sep 17 00:00:00 2001 From: twosee Date: Thu, 16 Jun 2022 19:02:53 +0800 Subject: [PATCH 012/440] Use get_active_function_or_method_name() for zend_forbid_dynamic_call() (#8762) A slight imperfection in https://github.com/php/php-src/pull/7443. As a zend_API, we should also consider other extensions that may call it in methods. This change will not break the behavior of php-src. --- Zend/zend_API.h | 5 +++- ext/zend_test/test.c | 17 +++++++++++ ext/zend_test/test.stub.php | 5 ++++ ext/zend_test/test_arginfo.h | 26 ++++++++++++++++- .../tests/zend_forbid_dynamic_call.phpt | 29 +++++++++++++++++++ 5 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 ext/zend_test/tests/zend_forbid_dynamic_call.phpt diff --git a/Zend/zend_API.h b/Zend/zend_API.h index a2d4e60d7be0d..b21228840c0ce 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -714,7 +714,10 @@ static zend_always_inline zend_result zend_forbid_dynamic_call(void) ZEND_ASSERT(ex != NULL && ex->func != NULL); if (ZEND_CALL_INFO(ex) & ZEND_CALL_DYNAMIC) { - zend_throw_error(NULL, "Cannot call %s() dynamically", get_active_function_name()); + zend_string *function_or_method_name = get_active_function_or_method_name(); + zend_throw_error(NULL, "Cannot call %.*s() dynamically", + (int) ZSTR_LEN(function_or_method_name), ZSTR_VAL(function_or_method_name)); + zend_string_release(function_or_method_name); return FAILURE; } diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 2fbabe7ef647b..6adab9f255cbf 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -41,6 +41,7 @@ static zend_class_entry *zend_test_attribute; static zend_class_entry *zend_test_parameter_attribute; static zend_class_entry *zend_test_class_with_method_with_parameter_attribute; static zend_class_entry *zend_test_child_class_with_method_with_parameter_attribute; +static zend_class_entry *zend_test_forbid_dynamic_call; static zend_class_entry *zend_test_ns_foo_class; static zend_class_entry *zend_test_ns2_foo_class; static zend_class_entry *zend_test_ns2_ns_foo_class; @@ -552,6 +553,20 @@ static ZEND_METHOD(ZendTestChildClassWithMethodWithParameterAttribute, override) RETURN_LONG(4); } +static ZEND_METHOD(ZendTestForbidDynamicCall, call) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + zend_forbid_dynamic_call(); +} + +static ZEND_METHOD(ZendTestForbidDynamicCall, callStatic) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + zend_forbid_dynamic_call(); +} + PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals) @@ -643,6 +658,8 @@ PHP_MINIT_FUNCTION(zend_test) ZVAL_PSTRING(&attr->args[0].value, "value4"); } + zend_test_forbid_dynamic_call = register_class_ZendTestForbidDynamicCall(); + zend_test_ns_foo_class = register_class_ZendTestNS_Foo(); zend_test_ns2_foo_class = register_class_ZendTestNS2_Foo(); zend_test_ns2_ns_foo_class = register_class_ZendTestNS2_ZendSubNS_Foo(); diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index d58cea27dfc33..08122b6c02581 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -60,6 +60,11 @@ class ZendTestChildClassWithMethodWithParameterAttribute extends ZendTestClassWi public function override(string $parameter): int {} } + final class ZendTestForbidDynamicCall { + public function call(): void {} + public static function callStatic(): void {} + } + enum ZendTestUnitEnum { case Foo; case Bar; diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index d682b53755096..26ed9f72f78a3 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: 71d8e1e6e5a997e9b443fbce4136d0025b67830b */ + * Stub hash: 2d42ea64a5114eae618a6dfb642c2640f568f5db */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -114,6 +114,10 @@ ZEND_END_ARG_INFO() #define arginfo_class_ZendTestChildClassWithMethodWithParameterAttribute_override arginfo_zend_test_parameter_with_attribute +#define arginfo_class_ZendTestForbidDynamicCall_call arginfo_zend_test_void_return + +#define arginfo_class_ZendTestForbidDynamicCall_callStatic arginfo_zend_test_void_return + #define arginfo_class_ZendTestNS_Foo_method arginfo_zend_test_void_return #define arginfo_class_ZendTestNS2_Foo_method arginfo_zend_test_void_return @@ -153,6 +157,8 @@ static ZEND_METHOD(ZendTestParameterAttribute, __construct); static ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute, no_override); static ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute, override); static ZEND_METHOD(ZendTestChildClassWithMethodWithParameterAttribute, override); +static ZEND_METHOD(ZendTestForbidDynamicCall, call); +static ZEND_METHOD(ZendTestForbidDynamicCall, callStatic); static ZEND_METHOD(ZendTestNS_Foo, method); static ZEND_METHOD(ZendTestNS2_Foo, method); static ZEND_METHOD(ZendTestNS2_ZendSubNS_Foo, method); @@ -235,6 +241,13 @@ static const zend_function_entry class_ZendTestChildClassWithMethodWithParameter }; +static const zend_function_entry class_ZendTestForbidDynamicCall_methods[] = { + ZEND_ME(ZendTestForbidDynamicCall, call, arginfo_class_ZendTestForbidDynamicCall_call, ZEND_ACC_PUBLIC) + ZEND_ME(ZendTestForbidDynamicCall, callStatic, arginfo_class_ZendTestForbidDynamicCall_callStatic, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_FE_END +}; + + static const zend_function_entry class_ZendTestUnitEnum_methods[] = { ZEND_FE_END }; @@ -408,6 +421,17 @@ static zend_class_entry *register_class_ZendTestChildClassWithMethodWithParamete return class_entry; } +static zend_class_entry *register_class_ZendTestForbidDynamicCall(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "ZendTestForbidDynamicCall", class_ZendTestForbidDynamicCall_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + class_entry->ce_flags |= ZEND_ACC_FINAL; + + return class_entry; +} + static zend_class_entry *register_class_ZendTestUnitEnum(void) { zend_class_entry *class_entry = zend_register_internal_enum("ZendTestUnitEnum", IS_UNDEF, class_ZendTestUnitEnum_methods); diff --git a/ext/zend_test/tests/zend_forbid_dynamic_call.phpt b/ext/zend_test/tests/zend_forbid_dynamic_call.phpt new file mode 100644 index 0000000000000..77d8649f5322d --- /dev/null +++ b/ext/zend_test/tests/zend_forbid_dynamic_call.phpt @@ -0,0 +1,29 @@ +--TEST-- +Zend: Test zend_forbid_dynamic_call() for methods +--EXTENSIONS-- +zend_test +--FILE-- +call(); +ZendTestForbidDynamicCall::callStatic(); + +try { + $call = [$object, 'call']; + $call(); +} catch (Error $error) { + echo $error->getMessage(), "\n"; +} + +try { + $callStatic = [ZendTestForbidDynamicCall::class, 'callStatic']; + $callStatic(); +} catch (Error $error) { + echo $error->getMessage(), "\n"; +} + +?> +--EXPECT-- +Cannot call ZendTestForbidDynamicCall::call() dynamically +Cannot call ZendTestForbidDynamicCall::callStatic() dynamically From a83363e3612e4cd586a51582f234096b2b277f13 Mon Sep 17 00:00:00 2001 From: Heiko Weber Date: Wed, 15 Jun 2022 23:17:00 +0200 Subject: [PATCH 013/440] FPM: Fix use after free in `fpm_evaluate_full_path` Closes #8796. --- NEWS | 1 + sapi/fpm/fpm/fpm_conf.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index dfbdd981223a2..e5de8dbb32bc3 100644 --- a/NEWS +++ b/NEWS @@ -45,6 +45,7 @@ PHP NEWS . Fixed ACL build check on MacOS. (David Carlier) . Fixed bug #72185: php-fpm writes empty fcgi record causing nginx 502. (Jakub Zelenka, loveharmful) + . Fixes use after free. (Heiko Weber). - Mysqlnd: . Fixed bug #81719: mysqlnd/pdo password buffer overflow. (CVE-2022-31626) diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c index 42f75a475df5f..32935b57a7547 100644 --- a/sapi/fpm/fpm/fpm_conf.c +++ b/sapi/fpm/fpm/fpm_conf.c @@ -766,8 +766,8 @@ static int fpm_evaluate_full_path(char **path, struct fpm_worker_pool_s *wp, cha } if (strlen(*path) > strlen("$prefix")) { - free(*path); tmp = strdup((*path) + strlen("$prefix")); + free(*path); *path = tmp; } else { free(*path); From a87f4dd93005f595d23b87f570775f8fc3887c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Pr=C3=ADvozn=C3=ADk?= Date: Thu, 16 Jun 2022 15:34:37 +0200 Subject: [PATCH 014/440] check_parameters.php: Make the script's retval reflect errors When the check_parameters.php script meets an error it prints it out but the exit value is not affected, it's still 0. This does not fly with projects that want to run this script as a part of their test suite. Therefore, make the script return 0 on success and 2 if any error was reported. Signed-off-by: Michal Privoznik Closes GH-8790. --- scripts/dev/check_parameters.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/dev/check_parameters.php b/scripts/dev/check_parameters.php index f8e905cc021eb..a68f5ebe5fdce 100755 --- a/scripts/dev/check_parameters.php +++ b/scripts/dev/check_parameters.php @@ -51,7 +51,7 @@ /** reports an error, according to its level */ function error($str, $level = 0) { - global $current_file, $current_function, $line; + global $current_file, $current_function, $line, $error_reported; if ($level <= REPORT_LEVEL) { if (strpos($current_file,PHPDIR) === 0) { @@ -60,6 +60,7 @@ function error($str, $level = 0) $filename = $current_file; } echo $filename , " [$line] $current_function : $str\n"; + $error_reported = true; } } @@ -372,6 +373,9 @@ function recurse($path) } } +$error_reported = false; foreach ($dirs as $dir) { recurse(realpath($dir)); } + +exit($error_reported === false ? 0 : 2); From 2c166647f1a54dfa768b4dda680c5953f54b9c3a Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Thu, 16 Jun 2022 20:49:00 +0100 Subject: [PATCH 015/440] Fix phpize to include _GNU_SOURCE by default This is to address the issue at https://github.com/php/php-src/commit/067df263448ee26013cddee1065bc9c1f028bd23#commitcomment-61578732 --- scripts/phpize.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/phpize.m4 b/scripts/phpize.m4 index 1f0cbd70eb075..616d16420a5a1 100644 --- a/scripts/phpize.m4 +++ b/scripts/phpize.m4 @@ -164,7 +164,7 @@ all_targets='$(PHP_MODULES) $(PHP_ZEND_EX)' install_targets="install-modules install-headers" phplibdir="`pwd`/modules" CPPFLAGS="$CPPFLAGS -DHAVE_CONFIG_H" -CFLAGS_CLEAN='$(CFLAGS)' +CFLAGS_CLEAN='$(CFLAGS) -D_GNU_SOURCE' CXXFLAGS_CLEAN='$(CXXFLAGS)' test "$prefix" = "NONE" && prefix="/usr/local" From 36990aab8eda82984d4c9c7ddaeb2c131b31382c Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Thu, 9 Jun 2022 16:57:37 +0100 Subject: [PATCH 016/440] Fixed bug #77243 (Weekdays are calculated incorrectly for negative years) --- ext/date/lib/dow.c | 2 +- ext/date/tests/bug49585.phpt | 2 +- ext/date/tests/bug75851.phpt | 4 +- ext/date/tests/bug77243-001.phpt | 34 ++++++++++++++++ ext/date/tests/bug77243-002.phpt | 68 ++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 ext/date/tests/bug77243-001.phpt create mode 100644 ext/date/tests/bug77243-002.phpt diff --git a/ext/date/lib/dow.c b/ext/date/lib/dow.c index 52f43b1a89d26..c288e5db97281 100644 --- a/ext/date/lib/dow.c +++ b/ext/date/lib/dow.c @@ -52,7 +52,7 @@ static timelib_sll timelib_day_of_week_ex(timelib_sll y, timelib_sll m, timelib_ /* Only valid for Gregorian calendar, commented out as we don't handle * Julian calendar. We just return the 'wrong' day of week to be * consistent. */ - c1 = century_value(y / 100); + c1 = century_value(positive_mod(y, 400) / 100); y1 = positive_mod(y, 100); m1 = timelib_is_leap(y) ? m_table_leap[m] : m_table_common[m]; dow = positive_mod((c1 + y1 + m1 + (y1 / 4) + d), 7); diff --git a/ext/date/tests/bug49585.phpt b/ext/date/tests/bug49585.phpt index d21bba6c5ce0b..c078618b3d96b 100644 --- a/ext/date/tests/bug49585.phpt +++ b/ext/date/tests/bug49585.phpt @@ -13,5 +13,5 @@ var_dump($date->format('c')); ?> --EXPECT-- string(32) "Fri, 01 Jan -1500 00:00:00 +0000" -string(38) "Mon, 01 Jan -2147483648 00:00:00 +0000" +string(38) "Tue, 01 Jan -2147483648 00:00:00 +0000" string(32) "-2147483648-01-01T00:00:00+00:00" diff --git a/ext/date/tests/bug75851.phpt b/ext/date/tests/bug75851.phpt index d447792b93161..0427e09885cd9 100644 --- a/ext/date/tests/bug75851.phpt +++ b/ext/date/tests/bug75851.phpt @@ -13,9 +13,9 @@ echo date(DATE_ATOM."\n".DATE_RFC2822."\nc\nr\no\ny\nY\nU\n\n", PHP_INT_MAX); ?> --EXPECT-- -292277022657-01-27T08:29:52+00:00 -Fri, 27 Jan -292277022657 08:29:52 +0000 +Sun, 27 Jan -292277022657 08:29:52 +0000 -292277022657-01-27T08:29:52+00:00 -Fri, 27 Jan -292277022657 08:29:52 +0000 +Sun, 27 Jan -292277022657 08:29:52 +0000 -292277022657 -57 -292277022657 diff --git a/ext/date/tests/bug77243-001.phpt b/ext/date/tests/bug77243-001.phpt new file mode 100644 index 0000000000000..e52b4530716c5 --- /dev/null +++ b/ext/date/tests/bug77243-001.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #77243 (Weekdays are calculated incorrectly for negative years) +--FILE-- + +--EXPECT-- +-0001-12-24 -1-51-5 +-0001-12-25 -1-51-6 +-0001-12-26 -1-51-7 +-0001-12-27 -1-52-1 +-0001-12-28 -1-52-2 +-0001-12-29 -1-52-3 +-0001-12-30 -1-52-4 +-0001-12-31 -1-52-5 +0000-01-01 -1-52-6 +0000-01-02 -1-52-7 +0000-01-03 0-01-1 +0000-01-04 0-01-2 +0000-01-05 0-01-3 +0000-01-06 0-01-4 +0000-01-07 0-01-5 +0000-01-08 0-01-6 +0000-01-09 0-01-7 +0000-01-10 0-02-1 +0000-01-11 0-02-2 +0000-01-12 0-02-3 diff --git a/ext/date/tests/bug77243-002.phpt b/ext/date/tests/bug77243-002.phpt new file mode 100644 index 0000000000000..40ea576aae3c1 --- /dev/null +++ b/ext/date/tests/bug77243-002.phpt @@ -0,0 +1,68 @@ +--TEST-- +Bug #77243 (Weekdays are calculated incorrectly for negative years) +--FILE-- + +--EXPECT-- +-0102-12-26 -102-52-1 +-0102-12-27 -102-52-2 +-0102-12-28 -102-52-3 +-0102-12-29 -102-52-4 +-0102-12-30 -102-52-5 +-0102-12-31 -102-52-6 +-0101-01-01 -102-52-7 +-0101-01-02 -101-01-1 +-0101-01-03 -101-01-2 +-0101-01-04 -101-01-3 +-0101-01-05 -101-01-4 +-0101-01-06 -101-01-5 +-0101-01-07 -101-01-6 +-0101-01-08 -101-01-7 + + +-0101-12-26 -101-52-2 +-0101-12-27 -101-52-3 +-0101-12-28 -101-52-4 +-0101-12-29 -101-52-5 +-0101-12-30 -101-52-6 +-0101-12-31 -101-52-7 +-0100-01-01 -100-01-1 +-0100-01-02 -100-01-2 +-0100-01-03 -100-01-3 +-0100-01-04 -100-01-4 +-0100-01-05 -100-01-5 +-0100-01-06 -100-01-6 +-0100-01-07 -100-01-7 +-0100-01-08 -100-02-1 + + +-0100-12-26 -100-52-3 +-0100-12-27 -100-52-4 +-0100-12-28 -100-52-5 +-0100-12-29 -100-52-6 +-0100-12-30 -100-52-7 +-0100-12-31 -99-01-1 +-0099-01-01 -99-01-2 +-0099-01-02 -99-01-3 +-0099-01-03 -99-01-4 +-0099-01-04 -99-01-5 +-0099-01-05 -99-01-6 +-0099-01-06 -99-01-7 +-0099-01-07 -99-02-1 +-0099-01-08 -99-02-2 From b23dfe4986236d7f03fdd4c44df7c16f4c0aa308 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Fri, 10 Jun 2022 11:11:53 +0100 Subject: [PATCH 017/440] Skip tests on 32-bit --- ext/date/tests/bug77243-001.phpt | 2 ++ ext/date/tests/bug77243-002.phpt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ext/date/tests/bug77243-001.phpt b/ext/date/tests/bug77243-001.phpt index e52b4530716c5..b347d033429e0 100644 --- a/ext/date/tests/bug77243-001.phpt +++ b/ext/date/tests/bug77243-001.phpt @@ -1,5 +1,7 @@ --TEST-- Bug #77243 (Weekdays are calculated incorrectly for negative years) +--SKIPIF-- + --FILE-- --FILE-- Date: Fri, 17 Jun 2022 14:12:53 +0200 Subject: [PATCH 018/440] Deprecate zend_atol() / add zend_ini_parse_quantity() (#7951) Add zend_ini_parse_quantity() and deprecate zend_atol(), zend_atoi() zend_atol() and zend_atoi() don't just do number parsing. They also check for a 'K', 'M', or 'G' at the end of the string, and multiply the parsed value out accordingly. Unfortunately, they ignore any other non-numerics between the numeric component and the last character in the string. This means that numbers such as the following are both valid and non-intuitive in their final output. * "123KMG" is interpreted as "123G" -> 132070244352 * "123G " is interpreted as "123 " -> 123 * "123GB" is interpreted as "123B" -> 123 * "123 I like tacos." is also interpreted as "123." -> 123 Currently, in php-src these functions are used only for parsing ini values. In this change we deprecate zend_atol(), zend_atoi(), and introduce a new function with the same behavior, but with the ability to report invalid inputs to the caller. The function's name also makes the behavior less unexpected: zend_ini_parse_quantity(). Co-authored-by: Sara Golemon --- UPGRADING | 85 ++ UPGRADING.INTERNALS | 3 + Zend/tests/zend_ini_parse_quantity.phpt | 897 ++++++++++++++++++ Zend/tests/zend_ini_parse_quantity_error.phpt | 79 ++ ...zend_ini_parse_quantity_ini_set_error.phpt | 13 + ..._ini_parse_quantity_ini_setting_error.phpt | 13 + .../zend_ini_parse_quantity_overflow.phpt | 101 ++ .../zend_ini_parse_uquantity_overflow.phpt | 117 +++ Zend/zend.c | 4 +- Zend/zend_ini.c | 210 +++- Zend/zend_ini.h | 46 + Zend/zend_operators.c | 11 +- Zend/zend_operators.h | 7 +- ext/bcmath/bcmath.c | 2 +- ext/opcache/tests/bug71843.phpt | 2 +- ext/opcache/tests/bug74431.phpt | 2 +- ext/opcache/zend_accelerator_module.c | 10 +- ext/standard/basic_functions.c | 3 +- .../parse_ini_numeric_entry_name.phpt | 23 + ext/zend_test/php_test.h | 1 + ext/zend_test/test.c | 40 +- ext/zend_test/test.stub.php | 3 + ext/zend_test/test_arginfo.h | 12 +- ext/zlib/zlib.c | 2 +- main/main.c | 2 +- 25 files changed, 1666 insertions(+), 22 deletions(-) create mode 100644 Zend/tests/zend_ini_parse_quantity.phpt create mode 100644 Zend/tests/zend_ini_parse_quantity_error.phpt create mode 100644 Zend/tests/zend_ini_parse_quantity_ini_set_error.phpt create mode 100644 Zend/tests/zend_ini_parse_quantity_ini_setting_error.phpt create mode 100644 Zend/tests/zend_ini_parse_quantity_overflow.phpt create mode 100644 Zend/tests/zend_ini_parse_uquantity_overflow.phpt create mode 100644 ext/standard/tests/general_functions/parse_ini_numeric_entry_name.phpt diff --git a/UPGRADING b/UPGRADING index e28498efe9a80..7ae56581edad4 100644 --- a/UPGRADING +++ b/UPGRADING @@ -342,6 +342,91 @@ PHP 8.2 UPGRADE NOTES 11. Changes to INI File Handling ======================================== +- Parsing of some ill-formatted values will now trigger a warning when this was + silently ignored before. Interpretation of these values is not changed, for + backwards compatibility. This affects the following settings: + . bcmath.scale + . com.code_page + . default_socket_timeout + . fiber.stack_size + . hard_timeout + . intl.error_level + . ldap.max_links + . max_input_nesting_level + . max_input_vars + . mbstring.regex_retry_limit + . mbstring.regex_stack_limit + . mysqli.allow_local_infile + . mysqli.allow_persistent + . mysqli.default_port + . mysqli.max_links + . mysqli.max_persistent + . mysqli.reconnect + . mysqli.rollback_on_cached_plink + . mysqlnd.log_mask + . mysqlnd.mempool_default_size + . mysqlnd.net_read_buffer_size + . mysqlnd.net_read_timeout + . oci8.default_prefetch + . oci8.max_persistent + . oci8.persistent_timeout + . oci8.ping_interval + . oci8.prefetch_lob_size + . oci8.privileged_connect + . oci8.statement_cache_size + . odbc.allow_persistent + . odbc.check_persistent + . odbc.defaultbinmode + . odbc.default_cursortype + . odbc.defaultlrl + . odbc.max_links + . odbc.max_persistent + . opcache.consistency_checks + . opcache.file_update_protection + . opcache.force_restart_timeout + . opcache.interned_strings_buffer + . opcache.jit_bisect_limit + . opcache.jit_blacklist_root_trace + . opcache.jit_blacklist_side_trace + . opcache.jit_debug + . opcache.jit_hot_func + . opcache.jit_hot_loop + . opcache.jit_hot_return + . opcache.jit_hot_side_exit + . opcache.jit_max_exit_counters + . opcache.jit_max_loop_unrolls + . opcache.jit_max_polymorphic_calls + . opcache.jit_max_recursive_calls + . opcache.jit_max_recursive_returns + . opcache.jit_max_root_traces + . opcache.jit_max_side_traces + . opcache.log_verbosity_level + . opcache.max_file_size + . opcache.opt_debug_level + . opcache.optimization_level + . opcache.revalidate_freq + . output_buffering + . pcre.backtrack_limit + . pcre.recursion_limit + . pgsql.max_links + . pgsql.max_persistent + . post_max_size + . realpath_cache_size + . realpath_cache_ttl + . session.cache_expire + . session.cookie_lifetime + . session.gc_divisor + . session.gc_maxlifetime + . session.gc_probability + . soap.wsdl_cache_limit + . soap.wsdl_cache_ttl + . unserialize_max_depth + . upload_max_filesize + . user_ini.cache_ttl + . xmlrpc_error_number + . zend.assertions + . zlib.output_compression_level + ======================================== 12. Windows Support ======================================== diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 64cfbee3cf11b..e411bdba99031 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -29,6 +29,9 @@ PHP 8.2 INTERNALS UPGRADE NOTES * A new ZEND_THREEWAY_COMPARE() macro has been introduced which does a three-way comparison of two integers and returns -1, 0 or 1 if the LHS is smaller, equal or larger than the RHS +* Deprecated zend_atoi() and zend_atol(). Use ZEND_STRTOL() for general purpose + string to long conversion, or a variant of zend_ini_parse_quantity() for + parsing ini quantities. ======================== 2. Build system changes diff --git a/Zend/tests/zend_ini_parse_quantity.phpt b/Zend/tests/zend_ini_parse_quantity.phpt new file mode 100644 index 0000000000000..09f0a731452b8 --- /dev/null +++ b/Zend/tests/zend_ini_parse_quantity.phpt @@ -0,0 +1,897 @@ +--TEST-- +Test parsing of quantities +--EXTENSIONS-- +zend_test +--FILE-- + '0', + 'No overflow 002' => '1', + 'No overflow 003' => '100', + 'No overflow 004' => strval(PHP_INT_MAX), + 'No overflow 005' => strval(PHP_INT_MIN), + 'No overflow 006' => '2K', + 'No overflow 007' => '-2K', + 'Subject overflow 001' => increment(strval(PHP_INT_MAX)), + 'Subject overflow 002' => decrement(strval(PHP_INT_MIN)), + 'Multiplier overflow 001' => strval(PHP_INT_MAX).'K', + 'Multiplier overflow 002' => strval(PHP_INT_MIN).'K', +]; + +foreach ($tests as $name => $value) { + printf("# %s: \"%s\"\n", $name, $value); + printf("%d\n", zend_test_zend_ini_parse_quantity($value)); + print "\n"; + print "----------\n"; +} + +--EXPECTF-- +# No overflow 001: "0" +0 + +---------- +# No overflow 002: "1" +1 + +---------- +# No overflow 003: "100" +100 + +---------- +# No overflow 004: "%d" +%d + +---------- +# No overflow 005: "-%d" +-%d + +---------- +# No overflow 006: "2K" +2048 + +---------- +# No overflow 007: "-2K" +-2048 + +---------- +# Subject overflow 001: "%d" + +Warning: Invalid quantity "%d": value is out of range, using overflow result for backwards compatibility in %s on line %d +%s + +---------- +# Subject overflow 002: "-%d" + +Warning: Invalid quantity "-%d": value is out of range, using overflow result for backwards compatibility in %s on line %d +%s + +---------- +# Multiplier overflow 001: "%dK" + +Warning: Invalid quantity "%dK": value is out of range, using overflow result for backwards compatibility in %s on line %d +%s + +---------- +# Multiplier overflow 002: "-%dK" + +Warning: Invalid quantity "-%dK": value is out of range, using overflow result for backwards compatibility in %s on line %d +%s + +---------- diff --git a/Zend/tests/zend_ini_parse_uquantity_overflow.phpt b/Zend/tests/zend_ini_parse_uquantity_overflow.phpt new file mode 100644 index 0000000000000..6dd3ed05076be --- /dev/null +++ b/Zend/tests/zend_ini_parse_uquantity_overflow.phpt @@ -0,0 +1,117 @@ +--TEST-- +Test zend_ini_parse_uquantity() overflow handling +--EXTENSIONS-- +zend_test +--FILE-- + '0', + 'No overflow 002' => '1', + 'No overflow 003' => '100', + 'No overflow 004' => strval(PHP_INT_MAX), + 'No overflow 005' => '2K', + 'No overflow 006' => '-1', + 'No overflow 007' => ' -1', + 'No overflow 008' => '-1 ', + 'No overflow 009' => ' -1 ', + 'Subject overflow 001' => base_convert(str_repeat('1', PHP_INT_SIZE*8+1), 2, 10), + 'Subject overflow 002' => '-'.base_convert(str_repeat('1', PHP_INT_SIZE*8+1), 2, 10), + 'Subject overflow 003' => strval(PHP_INT_MIN), + 'Subject overflow 004' => '-2', + 'Subject overflow 005' => '-1K', + 'Subject overflow 006' => '-1 K', + 'Multiplier overflow 001' => strval(PHP_INT_MAX).'K', +]; + +foreach ($tests as $name => $value) { + printf("# %s: \"%s\"\n", $name, $value); + printf("%u\n", zend_test_zend_ini_parse_uquantity($value)); + print "\n"; + print "----------\n"; +} + +printf("# zend_test_zend_ini_parse_uquantity(\"-1\") === -1\n"); +var_dump(zend_test_zend_ini_parse_uquantity("-1") === -1); + +--EXPECTF-- +# No overflow 001: "0" +0 + +---------- +# No overflow 002: "1" +1 + +---------- +# No overflow 003: "100" +100 + +---------- +# No overflow 004: "%d" +%d + +---------- +# No overflow 005: "2K" +2048 + +---------- +# No overflow 006: "-1" +%d + +---------- +# No overflow 007: " -1" +%d + +---------- +# No overflow 008: "-1 " +%d + +---------- +# No overflow 009: " -1 " +%d + +---------- +# Subject overflow 001: "%d" + +Warning: Invalid quantity "%d": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# Subject overflow 002: "-%d" + +Warning: Invalid quantity "-%d": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# Subject overflow 003: "-%d" + +Warning: Invalid quantity "-%d": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# Subject overflow 004: "-2" + +Warning: Invalid quantity "-2": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# Subject overflow 005: "-1K" + +Warning: Invalid quantity "-1K": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# Subject overflow 006: "-1 K" + +Warning: Invalid quantity "-1 K": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# Multiplier overflow 001: "%dK" + +Warning: Invalid quantity "%dK": value is out of range, using overflow result for backwards compatibility in %s on line %d +%d + +---------- +# zend_test_zend_ini_parse_uquantity("-1") === -1 +bool(true) diff --git a/Zend/zend.c b/Zend/zend.c index 97d937db5a2ed..7d0eacda58c65 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -146,7 +146,7 @@ static ZEND_INI_MH(OnUpdateAssertions) /* {{{ */ { zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); - zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name); if (stage != ZEND_INI_STAGE_STARTUP && stage != ZEND_INI_STAGE_SHUTDOWN && @@ -176,7 +176,7 @@ static ZEND_INI_MH(OnSetExceptionStringParamMaxLen) /* {{{ */ static ZEND_INI_MH(OnUpdateFiberStackSize) /* {{{ */ { if (new_value) { - EG(fiber_stack_size) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + EG(fiber_stack_size) = zend_ini_parse_quantity_warn(new_value, entry->name); } else { EG(fiber_stack_size) = ZEND_FIBER_DEFAULT_C_STACK_SIZE; } diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index f4f17c7ba18ef..406de810e2b5c 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -24,12 +24,17 @@ #include "zend_operators.h" #include "zend_strtod.h" #include "zend_modules.h" +#include "zend_smart_str.h" static HashTable *registered_zend_ini_directives; #define NO_VALUE_PLAINTEXT "no value" #define NO_VALUE_HTML "no value" +static inline bool zend_is_whitespace(char c) { + return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f'; +} + /* * hash_apply functions */ @@ -536,6 +541,207 @@ ZEND_API bool zend_ini_parse_bool(zend_string *str) } } +typedef enum { + ZEND_INI_PARSE_QUANTITY_SIGNED, + ZEND_INI_PARSE_QUANTITY_UNSIGNED, +} zend_ini_parse_quantity_signed_result_t; + +static zend_ulong zend_ini_parse_quantity_internal(zend_string *value, zend_ini_parse_quantity_signed_result_t signed_result, zend_string **errstr) /* {{{ */ +{ + char *digits_end = NULL; + char *str = ZSTR_VAL(value); + char *str_end = &str[ZSTR_LEN(value)]; + char *digits = str; + bool overflow = false; + zend_ulong factor; + smart_str invalid = {0}; + smart_str interpreted = {0}; + smart_str chr = {0}; + + /* Ignore leading whitespace. ZEND_STRTOL() also skips leading whitespaces, + * but we need the position of the first non-whitespace later. */ + while (digits < str_end && zend_is_whitespace(*digits)) ++digits; + + /* Ignore trailing whitespace */ + while (digits < str_end && zend_is_whitespace(*(str_end-1))) --str_end; + + if (digits == str_end) { + *errstr = NULL; + return 0; + } + + zend_ulong retval; + errno = 0; + + if (signed_result == ZEND_INI_PARSE_QUANTITY_SIGNED) { + retval = (zend_ulong) ZEND_STRTOL(digits, &digits_end, 0); + } else { + retval = ZEND_STRTOUL(digits, &digits_end, 0); + } + + if (errno == ERANGE) { + overflow = true; + } else if (signed_result == ZEND_INI_PARSE_QUANTITY_UNSIGNED) { + /* ZEND_STRTOUL() does not report a range error when the subject starts + * with a minus sign, so we check this here. Ignore "-1" as it is + * commonly used as max value, for instance in memory_limit=-1. */ + if (digits[0] == '-' && !(digits_end - digits == 2 && digits_end == str_end && digits[1] == '1')) { + overflow = true; + } + } + + if (UNEXPECTED(digits_end == digits)) { + /* No leading digits */ + + /* Escape the string to avoid null bytes and to make non-printable chars + * visible */ + smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value)); + smart_str_0(&invalid); + + *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no valid leading digits, interpreting as \"0\" for backwards compatibility", + ZSTR_VAL(invalid.s)); + + smart_str_free(&invalid); + return 0; + } + + /* Allow for whitespace between integer portion and any suffix character */ + while (digits_end < str_end && zend_is_whitespace(*digits_end)) ++digits_end; + + /* No exponent suffix. */ + if (digits_end == str_end) { + goto end; + } + + switch (*(str_end-1)) { + case 'g': + case 'G': + factor = 1<<30; + break; + case 'm': + case 'M': + factor = 1<<20; + break; + case 'k': + case 'K': + factor = 1<<10; + break; + default: + /* Unknown suffix */ + smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value)); + smart_str_0(&invalid); + smart_str_append_escaped(&interpreted, str, digits_end - str); + smart_str_0(&interpreted); + smart_str_append_escaped(&chr, str_end-1, 1); + smart_str_0(&chr); + + *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": unknown multipler \"%s\", interpreting as \"%s\" for backwards compatibility", + ZSTR_VAL(invalid.s), ZSTR_VAL(chr.s), ZSTR_VAL(interpreted.s)); + + smart_str_free(&invalid); + smart_str_free(&interpreted); + smart_str_free(&chr); + + return retval; + } + + if (!overflow) { + if (signed_result == ZEND_INI_PARSE_QUANTITY_SIGNED) { + zend_long sretval = (zend_long)retval; + if (sretval > 0) { + overflow = (zend_long)retval > ZEND_LONG_MAX / (zend_long)factor; + } else { + overflow = (zend_long)retval < ZEND_LONG_MIN / (zend_long)factor; + } + } else { + overflow = retval > ZEND_ULONG_MAX / factor; + } + } + + retval *= factor; + + if (UNEXPECTED(digits_end != str_end-1)) { + /* More than one character in suffix */ + smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value)); + smart_str_0(&invalid); + smart_str_append_escaped(&interpreted, str, digits_end - str); + smart_str_0(&interpreted); + smart_str_append_escaped(&chr, str_end-1, 1); + smart_str_0(&chr); + + *errstr = zend_strpprintf(0, "Invalid quantity \"%s\", interpreting as \"%s%s\" for backwards compatibility", + ZSTR_VAL(invalid.s), ZSTR_VAL(interpreted.s), ZSTR_VAL(chr.s)); + + smart_str_free(&invalid); + smart_str_free(&interpreted); + smart_str_free(&chr); + + return retval; + } + +end: + if (UNEXPECTED(overflow)) { + smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value)); + smart_str_0(&invalid); + + /* Not specifying the resulting value here because the caller may make + * additional conversions. Not specifying the allowed range + * because the caller may do narrower range checks. */ + *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": value is out of range, using overflow result for backwards compatibility", + ZSTR_VAL(invalid.s)); + + smart_str_free(&invalid); + smart_str_free(&interpreted); + smart_str_free(&chr); + + return retval; + } + + *errstr = NULL; + return retval; +} +/* }}} */ + +ZEND_API zend_long zend_ini_parse_quantity(zend_string *value, zend_string **errstr) /* {{{ */ +{ + return (zend_long) zend_ini_parse_quantity_internal(value, ZEND_INI_PARSE_QUANTITY_SIGNED, errstr); +} +/* }}} */ + +ZEND_API zend_ulong zend_ini_parse_uquantity(zend_string *value, zend_string **errstr) /* {{{ */ +{ + return zend_ini_parse_quantity_internal(value, ZEND_INI_PARSE_QUANTITY_UNSIGNED, errstr); +} +/* }}} */ + +ZEND_API zend_long zend_ini_parse_quantity_warn(zend_string *value, zend_string *setting) /* {{{ */ +{ + zend_string *errstr; + zend_long retval = zend_ini_parse_quantity(value, &errstr); + + if (errstr) { + zend_error(E_WARNING, "Invalid \"%s\" setting. %s", ZSTR_VAL(setting), ZSTR_VAL(errstr)); + zend_string_release(errstr); + } + + return retval; +} +/* }}} */ + +ZEND_API zend_long zend_ini_parse_uquantity_warn(zend_string *value, zend_string *setting) /* {{{ */ +{ + zend_string *errstr; + zend_long retval = zend_ini_parse_uquantity(value, &errstr); + + if (errstr) { + zend_error(E_WARNING, "Invalid \"%s\" setting. %s", ZSTR_VAL(setting), ZSTR_VAL(errstr)); + zend_string_release(errstr); + } + + return retval; +} +/* }}} */ + ZEND_INI_DISP(zend_ini_boolean_displayer_cb) /* {{{ */ { int value; @@ -624,14 +830,14 @@ ZEND_API ZEND_INI_MH(OnUpdateBool) /* {{{ */ ZEND_API ZEND_INI_MH(OnUpdateLong) /* {{{ */ { zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); - *p = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + *p = zend_ini_parse_quantity_warn(new_value, entry->name); return SUCCESS; } /* }}} */ ZEND_API ZEND_INI_MH(OnUpdateLongGEZero) /* {{{ */ { - zend_long tmp = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + zend_long tmp = zend_ini_parse_quantity_warn(new_value, entry->name); if (tmp < 0) { return FAILURE; } diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h index 23258ec0ca8b5..5f6847f11a132 100644 --- a/Zend/zend_ini.h +++ b/Zend/zend_ini.h @@ -90,6 +90,52 @@ ZEND_API char *zend_ini_string_ex(const char *name, size_t name_length, int orig ZEND_API zend_string *zend_ini_get_value(zend_string *name); ZEND_API bool zend_ini_parse_bool(zend_string *str); +/** + * Parses an ini quantity + * + * The value parameter must be a string in the form + * + * sign? digits ws* multipler? + * + * with + * + * sign: [+-] + * digit: [0-9] + * digits: digit+ + * ws: [ \t\n\r\v\f] + * multipler: [KMG] + * + * Leading and trailing whitespaces are ignored. + * + * If the string is empty or consists only of only whitespaces, 0 is returned. + * + * Digits is parsed as decimal unless the first digit is '0', in which case + * digits is parsed as octal. + * + * The multiplier is case-insensitive. K, M, and G multiply the quantity by + * 2**10, 2**20, and 2**30, respectively. + * + * For backwards compatibility, ill-formatted values are handled as follows: + * - No leading digits: value is treated as '0' + * - Invalid multiplier: multiplier is ignored + * - Invalid characters between digits and multiplier: invalid characters are + * ignored + * - Integer overflow: The result of the overflow is returned + * + * In any of these cases an error string is stored in *errstr (caller must + * release it), otherwise *errstr is set to NULL. + */ +ZEND_API zend_long zend_ini_parse_quantity(zend_string *value, zend_string **errstr); + +/** + * Unsigned variant of zend_ini_parse_quantity + */ +ZEND_API zend_ulong zend_ini_parse_uquantity(zend_string *value, zend_string **errstr); + +ZEND_API zend_long zend_ini_parse_quantity_warn(zend_string *value, zend_string *setting); + +ZEND_API zend_long zend_ini_parse_uquantity_warn(zend_string *value, zend_string *setting); + ZEND_API zend_result zend_ini_register_displayer(const char *name, uint32_t name_length, void (*displayer)(zend_ini_entry *ini_entry, int type)); ZEND_API ZEND_INI_DISP(zend_ini_boolean_displayer_cb); diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index a35edc01501c0..3690162418fa3 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -118,7 +118,7 @@ ZEND_API const unsigned char zend_toupper_map[256] = { 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, -0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff +0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff }; @@ -136,7 +136,7 @@ ZEND_API const unsigned char zend_toupper_map[256] = { zend_binary_strncasecmp */ -ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) /* {{{ */ +static zend_long ZEND_FASTCALL zend_atol_internal(const char *str, size_t str_len) /* {{{ */ { if (!str_len) { str_len = strlen(str); @@ -168,9 +168,14 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) /* { } /* }}} */ +ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) +{ + return zend_atol_internal(str, str_len); +} + ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, size_t str_len) { - return (int) zend_atol(str, str_len); + return (int) zend_atol_internal(str, str_len); } /* {{{ convert_object_to_type: dst will be either ctype or UNDEF */ diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 346706d22beae..de02a406d575e 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -468,8 +468,11 @@ ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables(HashTable *ht1, HashTable ZEND_API int ZEND_FASTCALL zend_compare_arrays(zval *a1, zval *a2); ZEND_API int ZEND_FASTCALL zend_compare_objects(zval *o1, zval *o2); -ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, size_t str_len); -ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len); +/** Deprecatd in favor of ZEND_STRTOL() */ +ZEND_ATTRIBUTE_DEPRECATED ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, size_t str_len); + +/** Deprecatd in favor of ZEND_STRTOL() */ +ZEND_ATTRIBUTE_DEPRECATED ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len); #define convert_to_null_ex(zv) convert_to_null(zv) #define convert_to_boolean_ex(zv) convert_to_boolean(zv) diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index 1b50764b828aa..d6147269b0ebb 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -62,7 +62,7 @@ ZEND_INI_MH(OnUpdateScale) int *p; zend_long tmp; - tmp = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + tmp = zend_ini_parse_quantity_warn(new_value, entry->name); if (tmp < 0 || tmp > INT_MAX) { return FAILURE; } diff --git a/ext/opcache/tests/bug71843.phpt b/ext/opcache/tests/bug71843.phpt index 66ccd823627f4..71756d3b7e87a 100644 --- a/ext/opcache/tests/bug71843.phpt +++ b/ext/opcache/tests/bug71843.phpt @@ -3,7 +3,7 @@ Bug #71843 (null ptr deref ZEND_RETURN_SPEC_CONST_HANDLER (zend_vm_execute.h:347 --INI-- opcache.enable=1 opcache.enable_cli=1 -opcache.optimization_level=0xFFFFBFFF +opcache.optimization_level=0x7FFFBFFF --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/bug74431.phpt b/ext/opcache/tests/bug74431.phpt index bbfe0b9d6a551..87233ea02197a 100644 --- a/ext/opcache/tests/bug74431.phpt +++ b/ext/opcache/tests/bug74431.phpt @@ -3,7 +3,7 @@ Bug #74431 - foreach infinite loop --INI-- opcache.enable=1 opcache.enable_cli=1 -opcache.optimization_level=0xffffffff +opcache.optimization_level=0x7fffffff --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 5bdfe7a373a73..2271920b302c7 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -165,7 +165,7 @@ static ZEND_INI_MH(OnUpdateJit) static ZEND_INI_MH(OnUpdateJitDebug) { zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); - zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name); if (zend_jit_debug_config(*p, val, stage) == SUCCESS) { *p = val; @@ -176,7 +176,7 @@ static ZEND_INI_MH(OnUpdateJitDebug) static ZEND_INI_MH(OnUpdateCounter) { - zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name); if (val >= 0 && val < 256) { zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); *p = val; @@ -188,7 +188,7 @@ static ZEND_INI_MH(OnUpdateCounter) static ZEND_INI_MH(OnUpdateUnrollC) { - zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name); if (val > 0 && val < ZEND_JIT_TRACE_MAX_CALL_DEPTH) { zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); *p = val; @@ -201,7 +201,7 @@ static ZEND_INI_MH(OnUpdateUnrollC) static ZEND_INI_MH(OnUpdateUnrollR) { - zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name); if (val >= 0 && val < ZEND_JIT_TRACE_MAX_RET_DEPTH) { zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); *p = val; @@ -214,7 +214,7 @@ static ZEND_INI_MH(OnUpdateUnrollR) static ZEND_INI_MH(OnUpdateUnrollL) { - zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + zend_long val = zend_ini_parse_quantity_warn(new_value, entry->name); if (val > 0 && val < ZEND_JIT_TRACE_MAX_LOOPS_UNROLL) { zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); *p = val; diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 91a5ae6519c5f..5123174569fa3 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -2506,8 +2506,9 @@ static void php_simple_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int cal break; } + /* entry in the form x[a]=b where x might need to be an array index */ if (!(Z_STRLEN_P(arg1) > 1 && Z_STRVAL_P(arg1)[0] == '0') && is_numeric_string(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1), NULL, NULL, 0) == IS_LONG) { - zend_ulong key = (zend_ulong) zend_atol(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1)); + zend_ulong key = (zend_ulong) ZEND_STRTOUL(Z_STRVAL_P(arg1), NULL, 0); if ((find_hash = zend_hash_index_find(Z_ARRVAL_P(arr), key)) == NULL) { array_init(&hash); find_hash = zend_hash_index_add_new(Z_ARRVAL_P(arr), key, &hash); diff --git a/ext/standard/tests/general_functions/parse_ini_numeric_entry_name.phpt b/ext/standard/tests/general_functions/parse_ini_numeric_entry_name.phpt new file mode 100644 index 0000000000000..a359a9f38285b --- /dev/null +++ b/ext/standard/tests/general_functions/parse_ini_numeric_entry_name.phpt @@ -0,0 +1,23 @@ +--TEST-- +parse_ini_string with numeric entry name +--FILE-- + + array(1) { + [0]=> + string(1) "1" + } + ["2M"]=> + array(1) { + [0]=> + string(1) "2" + } +} diff --git a/ext/zend_test/php_test.h b/ext/zend_test/php_test.h index a08c080ee3730..1c0b24f0d0849 100644 --- a/ext/zend_test/php_test.h +++ b/ext/zend_test/php_test.h @@ -53,6 +53,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test) int register_passes; bool print_stderr_mshutdown; zend_test_fiber *active_fiber; + zend_long quantity_value; ZEND_END_MODULE_GLOBALS(zend_test) extern ZEND_DECLARE_MODULE_GLOBALS(zend_test) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 6adab9f255cbf..33a0e62e505dc 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -380,6 +380,40 @@ static ZEND_FUNCTION(zend_get_unit_enum) RETURN_OBJ_COPY(zend_enum_get_case_cstr(zend_test_unit_enum, "Foo")); } +static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity) +{ + zend_string *str; + zend_string *errstr; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(str) + ZEND_PARSE_PARAMETERS_END(); + + RETVAL_LONG(zend_ini_parse_quantity(str, &errstr)); + + if (errstr) { + zend_error(E_WARNING, "%s", ZSTR_VAL(errstr)); + zend_string_release(errstr); + } +} + +static ZEND_FUNCTION(zend_test_zend_ini_parse_uquantity) +{ + zend_string *str; + zend_string *errstr; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(str) + ZEND_PARSE_PARAMETERS_END(); + + RETVAL_LONG((zend_long)zend_ini_parse_uquantity(str, &errstr)); + + if (errstr) { + zend_error(E_WARNING, "%s", ZSTR_VAL(errstr)); + zend_string_release(errstr); + } +} + static ZEND_FUNCTION(namespaced_func) { ZEND_PARSE_PARAMETERS_NONE(); @@ -571,6 +605,7 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.print_stderr_mshutdown", "0", PHP_INI_SYSTEM, OnUpdateBool, print_stderr_mshutdown, zend_zend_test_globals, zend_test_globals) + STD_PHP_INI_ENTRY("zend_test.quantity_value", "0", PHP_INI_ALL, OnUpdateLong, quantity_value, zend_zend_test_globals, zend_test_globals) PHP_INI_END() void (*old_zend_execute_ex)(zend_execute_data *execute_data); @@ -768,7 +803,10 @@ ZEND_GET_MODULE(zend_test) /* The important part here is the ZEND_FASTCALL. */ PHP_ZEND_TEST_API int ZEND_FASTCALL bug78270(const char *str, size_t str_len) { - return (int) zend_atol(str, str_len); + char * copy = zend_strndup(str, str_len); + int r = (int) ZEND_ATOL(copy); + free(copy); + return r; } PHP_ZEND_TEST_API struct bug79096 bug79096(void) diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 08122b6c02581..13b2fd346e7b1 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -125,6 +125,9 @@ function zend_test_parameter_with_attribute(string $parameter): int {} function zend_get_current_func_name(): string {} function zend_call_method(object|string $obj_or_class, string $method, mixed $arg1 = UNKNOWN, mixed $arg2 = UNKNOWN): mixed {} + + function zend_test_zend_ini_parse_quantity(string $str): int {} + function zend_test_zend_ini_parse_uquantity(string $str): int {} } namespace ZendTestNS { diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index 26ed9f72f78a3..8c8e67d26954a 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: 2d42ea64a5114eae618a6dfb642c2640f568f5db */ + * Stub hash: 1a23b7473e5b4525352445545c6b3ab374c4e949 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -85,6 +85,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_call_method, 0, 2, IS_MIXED ZEND_ARG_TYPE_INFO(0, arg2, IS_MIXED, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_zend_ini_parse_quantity, 0, 1, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_zend_test_zend_ini_parse_uquantity arginfo_zend_test_zend_ini_parse_quantity + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ZendTestNS2_ZendSubNS_namespaced_func, 0, 0, _IS_BOOL, 0) ZEND_END_ARG_INFO() @@ -146,6 +152,8 @@ static ZEND_FUNCTION(zend_get_unit_enum); static ZEND_FUNCTION(zend_test_parameter_with_attribute); static ZEND_FUNCTION(zend_get_current_func_name); static ZEND_FUNCTION(zend_call_method); +static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity); +static ZEND_FUNCTION(zend_test_zend_ini_parse_uquantity); static ZEND_FUNCTION(namespaced_func); static ZEND_METHOD(_ZendTestClass, is_object); static ZEND_METHOD(_ZendTestClass, __toString); @@ -186,6 +194,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(zend_test_parameter_with_attribute, arginfo_zend_test_parameter_with_attribute) ZEND_FE(zend_get_current_func_name, arginfo_zend_get_current_func_name) ZEND_FE(zend_call_method, arginfo_zend_call_method) + ZEND_FE(zend_test_zend_ini_parse_quantity, arginfo_zend_test_zend_ini_parse_quantity) + ZEND_FE(zend_test_zend_ini_parse_uquantity, arginfo_zend_test_zend_ini_parse_uquantity) ZEND_NS_FE("ZendTestNS2\\ZendSubNS", namespaced_func, arginfo_ZendTestNS2_ZendSubNS_namespaced_func) ZEND_FE_END }; diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index a53fb2acc4593..37e35eb8c277c 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -1277,7 +1277,7 @@ static PHP_INI_MH(OnUpdate_zlib_output_compression) } else if (zend_string_equals_literal_ci(new_value, "on")) { int_value = 1; } else { - int_value = zend_atoi(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + int_value = (int) zend_ini_parse_quantity_warn(new_value, entry->name); } ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0); diff --git a/main/main.c b/main/main.c index aa1763e5e5642..5c8a079e87de0 100644 --- a/main/main.c +++ b/main/main.c @@ -263,7 +263,7 @@ static PHP_INI_MH(OnChangeMemoryLimit) { size_t value; if (new_value) { - value = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + value = zend_ini_parse_uquantity_warn(new_value, entry->name); } else { value = Z_L(1)<<30; /* effectively, no limit */ } From 827754ac226db2bef15cc7aea42375da2e396f0e Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 17 Jun 2022 15:23:21 +0200 Subject: [PATCH 019/440] Fix type (#8814) --- Zend/zend_ini.c | 4 ++-- Zend/zend_ini.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index 406de810e2b5c..c20227fb31eb6 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -728,10 +728,10 @@ ZEND_API zend_long zend_ini_parse_quantity_warn(zend_string *value, zend_string } /* }}} */ -ZEND_API zend_long zend_ini_parse_uquantity_warn(zend_string *value, zend_string *setting) /* {{{ */ +ZEND_API zend_ulong zend_ini_parse_uquantity_warn(zend_string *value, zend_string *setting) /* {{{ */ { zend_string *errstr; - zend_long retval = zend_ini_parse_uquantity(value, &errstr); + zend_ulong retval = zend_ini_parse_uquantity(value, &errstr); if (errstr) { zend_error(E_WARNING, "Invalid \"%s\" setting. %s", ZSTR_VAL(setting), ZSTR_VAL(errstr)); diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h index 5f6847f11a132..8b09f29ab8c2c 100644 --- a/Zend/zend_ini.h +++ b/Zend/zend_ini.h @@ -134,7 +134,7 @@ ZEND_API zend_ulong zend_ini_parse_uquantity(zend_string *value, zend_string **e ZEND_API zend_long zend_ini_parse_quantity_warn(zend_string *value, zend_string *setting); -ZEND_API zend_long zend_ini_parse_uquantity_warn(zend_string *value, zend_string *setting); +ZEND_API zend_ulong zend_ini_parse_uquantity_warn(zend_string *value, zend_string *setting); ZEND_API zend_result zend_ini_register_displayer(const char *name, uint32_t name_length, void (*displayer)(zend_ini_entry *ini_entry, int type)); From 4a9c00114043f1ed13d2c0f39da81fd63abd3fa9 Mon Sep 17 00:00:00 2001 From: twosee Date: Fri, 17 Jun 2022 22:33:20 +0800 Subject: [PATCH 020/440] Add clean_module_functions() (#8763) Add clean_module_functions() to clean functions which are registered by zend_register_functions(). The general logic of clean_module_functions() is consistent with clean_module_classes(). --- Zend/zend_API.c | 20 +++++++++++++++ ext/dl_test/dl_test.c | 21 ++++++++++++++++ .../dl-use_register_functions_directly.phpt | 25 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 ext/standard/tests/general_functions/dl-use_register_functions_directly.phpt diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 220b76efca6ff..2d3c41eb15f14 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2968,6 +2968,24 @@ static void clean_module_classes(int module_number) /* {{{ */ } /* }}} */ +static int clean_module_function(zval *el, void *arg) /* {{{ */ +{ + zend_function *fe = (zend_function *) Z_PTR_P(el); + zend_module_entry *module = (zend_module_entry *) arg; + if (fe->common.type == ZEND_INTERNAL_FUNCTION && fe->internal_function.module == module) { + return ZEND_HASH_APPLY_REMOVE; + } else { + return ZEND_HASH_APPLY_KEEP; + } +} +/* }}} */ + +static void clean_module_functions(zend_module_entry *module) /* {{{ */ +{ + zend_hash_apply_with_argument(CG(function_table), clean_module_function, module); +} +/* }}} */ + void module_destructor(zend_module_entry *module) /* {{{ */ { #if ZEND_RC_DEBUG @@ -3015,6 +3033,8 @@ void module_destructor(zend_module_entry *module) /* {{{ */ module->module_started=0; if (module->type == MODULE_TEMPORARY && module->functions) { zend_unregister_functions(module->functions, -1, NULL); + /* Clean functions registered separately from module->functions */ + clean_module_functions(module); } #if HAVE_LIBDL diff --git a/ext/dl_test/dl_test.c b/ext/dl_test/dl_test.c index 88a298b0ec88a..4b693fae43163 100644 --- a/ext/dl_test/dl_test.c +++ b/ext/dl_test/dl_test.c @@ -52,6 +52,23 @@ PHP_FUNCTION(dl_test_test2) } /* }}}*/ +/* {{{ PHP_DL_TEST_USE_REGISTER_FUNCTIONS_DIRECTLY */ +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dl_test_use_register_functions_directly, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() + +PHP_FUNCTION(dl_test_use_register_functions_directly) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETURN_STRING("OK"); +} + +static const zend_function_entry php_dl_test_use_register_functions_directly_functions[] = { + ZEND_FENTRY(dl_test_use_register_functions_directly, ZEND_FN(dl_test_use_register_functions_directly), arginfo_dl_test_use_register_functions_directly, 0) + ZEND_FE_END +}; +/* }}} */ + /* {{{ INI */ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("dl_test.long", "0", PHP_INI_ALL, OnUpdateLong, long_value, zend_dl_test_globals, dl_test_globals) @@ -69,6 +86,10 @@ PHP_MINIT_FUNCTION(dl_test) REGISTER_INI_ENTRIES(); } + if (getenv("PHP_DL_TEST_USE_REGISTER_FUNCTIONS_DIRECTLY")) { + zend_register_functions(NULL, php_dl_test_use_register_functions_directly_functions, NULL, type); + } + return SUCCESS; } /* }}} */ diff --git a/ext/standard/tests/general_functions/dl-use_register_functions_directly.phpt b/ext/standard/tests/general_functions/dl-use_register_functions_directly.phpt new file mode 100644 index 0000000000000..e76f927eecfbd --- /dev/null +++ b/ext/standard/tests/general_functions/dl-use_register_functions_directly.phpt @@ -0,0 +1,25 @@ +--TEST-- +dl(): use zend_register_functions() directly +--ENV-- +PHP_DL_TEST_USE_REGISTER_FUNCTIONS_DIRECTLY=1 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(true) +string(2) "OK" From 036bed01ce39fc9938ea6c8cebcaec4a3478c29c Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 17 Jun 2022 13:19:51 +0200 Subject: [PATCH 021/440] Fix imagecreatefromavif() memory leak This has been reported as https://github.com/libgd/libgd/issues/831. We port the respective fix to our bundled libgd. Closes GH-8812. --- NEWS | 3 +++ ext/gd/libgd/gd_avif.c | 52 +++++++++++++++++++++++++++--------------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/NEWS b/NEWS index a423c9a1b6933..23f5bbc9bc373 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,9 @@ PHP NEWS . Fixed bug #78139 (timezone_open accepts invalid timezone string argument). (Derick) +GD: + . Fixed imagecreatefromavif() memory leak. (cmb) + - MBString: . mb_detect_encoding recognizes all letters in Czech alphabet (alexdowad) . mb_detect_encoding recognizes all letters in Hungarian alphabet (alexdowad) diff --git a/ext/gd/libgd/gd_avif.c b/ext/gd/libgd/gd_avif.c index 6b1d448de7baf..30075d2a899c8 100644 --- a/ext/gd/libgd/gd_avif.c +++ b/ext/gd/libgd/gd_avif.c @@ -150,6 +150,11 @@ static avifBool isAvifError(avifResult result, const char *msg) { } +typedef struct avifIOCtxReader { + avifIO io; // this must be the first member for easy casting to avifIO* + avifROData rodata; +} avifIOCtxReader; + /* implements the avifIOReadFunc interface by calling the relevant functions in the gdIOCtx. Our logic is inspired by avifIOMemoryReaderRead() and avifIOFileReaderRead(). @@ -165,8 +170,8 @@ static avifBool isAvifError(avifResult result, const char *msg) { */ static avifResult readFromCtx(avifIO *io, uint32_t readFlags, uint64_t offset, size_t size, avifROData *out) { - void *dataBuf = NULL; gdIOCtx *ctx = (gdIOCtx *) io->data; + avifIOCtxReader *reader = (avifIOCtxReader *) io; // readFlags is unsupported if (readFlags != 0) { @@ -182,28 +187,34 @@ static avifResult readFromCtx(avifIO *io, uint32_t readFlags, uint64_t offset, s if (!ctx->seek(ctx, (int) offset)) return AVIF_RESULT_IO_ERROR; - dataBuf = avifAlloc(size); - if (!dataBuf) { + if (size > reader->rodata.size) { + reader->rodata.data = gdRealloc((void *) reader->rodata.data, size); + reader->rodata.size = size; + } + if (!reader->rodata.data) { gd_error("avif error - couldn't allocate memory"); return AVIF_RESULT_UNKNOWN_ERROR; } // Read the number of bytes requested. // If getBuf() returns a negative value, that means there was an error. - int charsRead = ctx->getBuf(ctx, dataBuf, (int) size); + int charsRead = ctx->getBuf(ctx, (void *) reader->rodata.data, (int) size); if (charsRead < 0) { - avifFree(dataBuf); return AVIF_RESULT_IO_ERROR; } - out->data = dataBuf; + out->data = reader->rodata.data; out->size = charsRead; return AVIF_RESULT_OK; } // avif.h says this is optional, but it seemed easy to implement. static void destroyAvifIO(struct avifIO *io) { - gdFree(io); + avifIOCtxReader *reader = (avifIOCtxReader *) io; + if (reader->rodata.data != NULL) { + gdFree((void *) reader->rodata.data); + } + gdFree(reader); } /* Set up an avifIO object. @@ -217,21 +228,23 @@ static void destroyAvifIO(struct avifIO *io) { // TODO: can we get sizeHint somehow? static avifIO *createAvifIOFromCtx(gdIOCtx *ctx) { - avifIO *io; + struct avifIOCtxReader *reader; - io = gdMalloc(sizeof(*io)); - if (io == NULL) + reader = gdMalloc(sizeof(*reader)); + if (reader == NULL) return NULL; // TODO: setting persistent=FALSE is safe, but it's less efficient. Is it necessary? - io->persistent = AVIF_FALSE; - io->read = readFromCtx; - io->write = NULL; // this function is currently unused; see avif.h - io->destroy = destroyAvifIO; - io->sizeHint = 0; // sadly, we don't get this information from the gdIOCtx. - io->data = ctx; - - return io; + reader->io.persistent = AVIF_FALSE; + reader->io.read = readFromCtx; + reader->io.write = NULL; // this function is currently unused; see avif.h + reader->io.destroy = destroyAvifIO; + reader->io.sizeHint = 0; // sadly, we don't get this information from the gdIOCtx. + reader->io.data = ctx; + reader->rodata.data = NULL; + reader->rodata.size = 0; + + return (avifIO *) reader; } @@ -576,6 +589,9 @@ void gdImageAvifCtx(gdImagePtr im, gdIOCtx *outfile, int quality, int speed) if (avifOutput.data) avifRWDataFree(&avifOutput); + + if (avifIm) + avifImageDestroy(avifIm); } void gdImageAvifEx(gdImagePtr im, FILE *outFile, int quality, int speed) From 5bb3e233db60593087bb786d6421abbff215af3b Mon Sep 17 00:00:00 2001 From: tobil4sk Date: Sun, 24 Apr 2022 20:52:53 +0200 Subject: [PATCH 022/440] Implement #77726: Allow null character in regex patterns In 8b3c1a3, this was disallowed to fix #55856, which was a security issue caused by the /e modifier. The fix that was made was the "Easier fix" as described in the original report. With this fix, pattern strings are no longer treated as null terminated, so null characters can be placed inside and matched against with regex patterns without security problems, so there is no longer a reason to give the error. Allowing this is consistent with the behaviour of many other languages, including JavaScript, and thanks to PCRE2[0], it does not require manually escaping null characters. Now that we can avoid the error here without the cost of escaping characters, there is really no need anymore to stray here from the conventional behaviour. Currently, null characters are still disallowed before the first delimiter and in the options section at the end of a regex string, but these error messages have been updated. [0] Since PCRE2, pattern strings no longer have to be null terminated, and raw null characters match as normal. Closes GH-8114. --- NEWS | 3 + UPGRADING | 3 + ext/pcre/php_pcre.c | 38 ++++------ ext/pcre/tests/bug73392.phpt | 2 +- ext/pcre/tests/delimiters.phpt | 6 +- ext/pcre/tests/null_bytes.phpt | 76 ++++++++++++------- ext/pcre/tests/preg_grep_error1.phpt | 2 +- ext/pcre/tests/preg_match_all_error1.phpt | 2 +- ext/pcre/tests/preg_match_error1.phpt | 2 +- .../preg_replace_callback_array_error.phpt | 66 ++++++++++++++++ ...eg_replace_callback_array_fatal_error.phpt | 21 +++++ .../tests/preg_replace_callback_error1.phpt | 2 +- ext/pcre/tests/preg_replace_error1.phpt | 2 +- ext/pcre/tests/preg_split_error1.phpt | 2 +- 14 files changed, 170 insertions(+), 57 deletions(-) create mode 100644 ext/pcre/tests/preg_replace_callback_array_error.phpt create mode 100644 ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt diff --git a/NEWS b/NEWS index 0558f682fabb7..cc16bfee8c82f 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,9 @@ GD: - ODBC: . Fixed handling of single-key connection strings. (Calvin Buckley) +- PCRE: + . Implemented FR #77726 (Allow null character in regex patterns). (cmb) + - PDO_ODBC: . Fixed handling of single-key connection strings. (Calvin Buckley) diff --git a/UPGRADING b/UPGRADING index 7ae56581edad4..1f47c862c7af1 100644 --- a/UPGRADING +++ b/UPGRADING @@ -221,6 +221,9 @@ PHP 8.2 UPGRADE NOTES - OCI8: . The minimum Oracle Client library version required is now 11.2. +- PCRE: + . NUL characters (\0) in pattern strings are now supported. + - SQLite3: . sqlite3.defensive is now PHP_INI_USER. diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 840d696019796..1061441074f9d 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -624,7 +624,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in pcre_cache_entry new_entry; int rc; zend_string *key; - pcre_cache_entry *ret; + pcre_cache_entry *ret; if (locale_aware && BG(ctype_string)) { key = zend_string_concat2( @@ -645,16 +645,16 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in } p = ZSTR_VAL(regex); + const char* end_p = ZSTR_VAL(regex) + ZSTR_LEN(regex); /* Parse through the leading whitespace, and display a warning if we get to the end without encountering a delimiter. */ while (isspace((int)*(unsigned char *)p)) p++; - if (*p == 0) { + if (p >= end_p) { if (key != regex) { zend_string_release_ex(key, 0); } - php_error_docref(NULL, E_WARNING, - p < ZSTR_VAL(regex) + ZSTR_LEN(regex) ? "Null byte in regex" : "Empty regular expression"); + php_error_docref(NULL, E_WARNING, "Empty regular expression"); pcre_handle_exec_error(PCRE2_ERROR_INTERNAL); return NULL; } @@ -662,11 +662,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in /* Get the delimiter and display a warning if it is alphanumeric or a backslash. */ delimiter = *p++; - if (isalnum((int)*(unsigned char *)&delimiter) || delimiter == '\\') { + if (isalnum((int)*(unsigned char *)&delimiter) || delimiter == '\\' || delimiter == '\0') { if (key != regex) { zend_string_release_ex(key, 0); } - php_error_docref(NULL,E_WARNING, "Delimiter must not be alphanumeric or backslash"); + php_error_docref(NULL, E_WARNING, "Delimiter must not be alphanumeric, backslash, or NUL"); pcre_handle_exec_error(PCRE2_ERROR_INTERNAL); return NULL; } @@ -682,8 +682,8 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in /* We need to iterate through the pattern, searching for the ending delimiter, but skipping the backslashed delimiters. If the ending delimiter is not found, display a warning. */ - while (*pp != 0) { - if (*pp == '\\' && pp[1] != 0) pp++; + while (pp < end_p) { + if (*pp == '\\' && pp + 1 < end_p) pp++; else if (*pp == delimiter) break; pp++; @@ -695,8 +695,8 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in * reach the end of the pattern without matching, display a warning. */ int brackets = 1; /* brackets nesting level */ - while (*pp != 0) { - if (*pp == '\\' && pp[1] != 0) pp++; + while (pp < end_p) { + if (*pp == '\\' && pp + 1 < end_p) pp++; else if (*pp == end_delimiter && --brackets <= 0) break; else if (*pp == start_delimiter) @@ -705,13 +705,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in } } - if (*pp == 0) { + if (pp >= end_p) { if (key != regex) { zend_string_release_ex(key, 0); } - if (pp < ZSTR_VAL(regex) + ZSTR_LEN(regex)) { - php_error_docref(NULL,E_WARNING, "Null byte in regex"); - } else if (start_delimiter == end_delimiter) { + if (start_delimiter == end_delimiter) { php_error_docref(NULL,E_WARNING, "No ending delimiter '%c' found", delimiter); } else { php_error_docref(NULL,E_WARNING, "No ending matching delimiter '%c' found", delimiter); @@ -729,7 +727,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in /* Parse through the options, setting appropriate flags. Display a warning if we encounter an unknown modifier. */ - while (pp < ZSTR_VAL(regex) + ZSTR_LEN(regex)) { + while (pp < end_p) { switch (*pp++) { /* Perl compatible options */ case 'i': coptions |= PCRE2_CASELESS; break; @@ -764,9 +762,9 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in default: if (pp[-1]) { - php_error_docref(NULL,E_WARNING, "Unknown modifier '%c'", pp[-1]); + php_error_docref(NULL, E_WARNING, "Unknown modifier '%c'", pp[-1]); } else { - php_error_docref(NULL,E_WARNING, "Null byte in regex"); + php_error_docref(NULL, E_WARNING, "NUL is not a valid modifier"); } pcre_handle_exec_error(PCRE2_ERROR_INTERNAL); efree(pattern); @@ -2438,12 +2436,6 @@ PHP_FUNCTION(preg_replace_callback_array) } ZEND_HASH_FOREACH_STR_KEY_VAL(pattern, str_idx_regex, replace) { - if (!str_idx_regex) { - php_error_docref(NULL, E_WARNING, "Delimiter must not be alphanumeric or backslash"); - RETVAL_NULL(); - goto error; - } - if (!zend_is_callable_ex(replace, NULL, 0, NULL, &fcc, NULL)) { zend_argument_type_error(1, "must contain only valid callbacks"); goto error; diff --git a/ext/pcre/tests/bug73392.phpt b/ext/pcre/tests/bug73392.phpt index 7546f5d99fb8d..a1cb3ac8480a0 100644 --- a/ext/pcre/tests/bug73392.phpt +++ b/ext/pcre/tests/bug73392.phpt @@ -21,5 +21,5 @@ var_dump(preg_replace_callback_array( ), 'a')); ?> --EXPECTF-- -Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric or backslash in %sbug73392.php on line %d +Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %sbug73392.php on line %d NULL diff --git a/ext/pcre/tests/delimiters.phpt b/ext/pcre/tests/delimiters.phpt index 1826f8730a337..beeebc8cbc2e3 100644 --- a/ext/pcre/tests/delimiters.phpt +++ b/ext/pcre/tests/delimiters.phpt @@ -12,6 +12,7 @@ var_dump(preg_match('~a', '')); var_dump(preg_match('@\@\@@', '@@')); var_dump(preg_match('//z', '@@')); var_dump(preg_match('{', '')); +var_dump(preg_match("\0\0", '')); ?> --EXPECTF-- @@ -22,7 +23,7 @@ Warning: preg_match(): Empty regular expression in %sdelimiters.php on line 4 bool(false) int(1) -Warning: preg_match(): Delimiter must not be alphanumeric or backslash in %sdelimiters.php on line 6 +Warning: preg_match(): Delimiter must not be alphanumeric, backslash, or NUL in %sdelimiters.php on line 6 bool(false) int(1) @@ -35,3 +36,6 @@ bool(false) Warning: preg_match(): No ending matching delimiter '}' found in %sdelimiters.php on line 11 bool(false) + +Warning: preg_match(): Delimiter must not be alphanumeric, backslash, or NUL in %sdelimiters.php on line 12 +bool(false) diff --git a/ext/pcre/tests/null_bytes.phpt b/ext/pcre/tests/null_bytes.phpt index 9a3f433ffb1bc..e9db61dae045e 100644 --- a/ext/pcre/tests/null_bytes.phpt +++ b/ext/pcre/tests/null_bytes.phpt @@ -3,40 +3,64 @@ Zero byte test --FILE-- ---EXPECTF-- -Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 3 +var_dump(preg_match("\0[]i", "")); +var_dump(preg_match("[\0]i", "")); +var_dump(preg_match("[\0]i", "\0")); +var_dump(preg_match("[]\0i", "")); +var_dump(preg_match("[]i\0", "")); +var_dump(preg_match("[\\\0]i", "")); +var_dump(preg_match("[\\\0]i", "\\\0")); -Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 4 +var_dump(preg_match("/abc\0def/", "abc")); +var_dump(preg_match("/abc\0def/", "abc\0def")); +var_dump(preg_match("/abc\0def/", "abc\0fed")); -Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 5 +var_dump(preg_match("[abc\0def]", "abc")); +var_dump(preg_match("[abc\0def]", "abc\0def")); +var_dump(preg_match("[abc\0def]", "abc\0fed")); -Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 6 +preg_replace("/foo/e\0/i", "echo('Eek');", ""); -Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 7 +?> +--EXPECTF-- +Warning: preg_match(): Delimiter must not be alphanumeric, backslash, or NUL in %snull_bytes.php on line 3 +bool(false) +int(0) +int(1) -Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 9 +Warning: preg_match(): NUL is not a valid modifier in %snull_bytes.php on line 6 +bool(false) -Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 10 +Warning: preg_match(): NUL is not a valid modifier in %snull_bytes.php on line 7 +bool(false) +int(0) +int(1) -Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 11 +Warning: preg_match(): Delimiter must not be alphanumeric, backslash, or NUL in %snull_bytes.php on line 11 +bool(false) +int(0) +int(1) -Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 12 +Warning: preg_match(): NUL is not a valid modifier in %snull_bytes.php on line 14 +bool(false) -Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 13 +Warning: preg_match(): NUL is not a valid modifier in %snull_bytes.php on line 15 +bool(false) +int(0) +int(1) +int(0) +int(1) +int(0) +int(0) +int(1) +int(0) -Warning: preg_replace(): Null byte in regex in %snull_bytes.php on line 15 +Warning: preg_replace(): NUL is not a valid modifier in %snull_bytes.php on line 27 diff --git a/ext/pcre/tests/preg_grep_error1.phpt b/ext/pcre/tests/preg_grep_error1.phpt index 3079c0b4b0249..0042536450756 100644 --- a/ext/pcre/tests/preg_grep_error1.phpt +++ b/ext/pcre/tests/preg_grep_error1.phpt @@ -37,7 +37,7 @@ echo "Done" Arg value is abcdef -Warning: preg_grep(): Delimiter must not be alphanumeric or backslash in %spreg_grep_error1.php on line %d +Warning: preg_grep(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_grep_error1.php on line %d bool(false) Arg value is /[a-zA-Z] diff --git a/ext/pcre/tests/preg_match_all_error1.phpt b/ext/pcre/tests/preg_match_all_error1.phpt index d25bfe99c6e6d..01e0615ad38f2 100644 --- a/ext/pcre/tests/preg_match_all_error1.phpt +++ b/ext/pcre/tests/preg_match_all_error1.phpt @@ -38,7 +38,7 @@ var_dump($matches); Arg value is abcdef -Warning: preg_match_all(): Delimiter must not be alphanumeric or backslash in %spreg_match_all_error1.php on line %d +Warning: preg_match_all(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_match_all_error1.php on line %d bool(false) NULL diff --git a/ext/pcre/tests/preg_match_error1.phpt b/ext/pcre/tests/preg_match_error1.phpt index 7a7106270f0e8..e97ddb9267512 100644 --- a/ext/pcre/tests/preg_match_error1.phpt +++ b/ext/pcre/tests/preg_match_error1.phpt @@ -34,7 +34,7 @@ try { Arg value is abcdef -Warning: preg_match(): Delimiter must not be alphanumeric or backslash in %spreg_match_error1.php on line %d +Warning: preg_match(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_match_error1.php on line %d bool(false) Arg value is /[a-zA-Z] diff --git a/ext/pcre/tests/preg_replace_callback_array_error.phpt b/ext/pcre/tests/preg_replace_callback_array_error.phpt new file mode 100644 index 0000000000000..7a73d5b00c211 --- /dev/null +++ b/ext/pcre/tests/preg_replace_callback_array_error.phpt @@ -0,0 +1,66 @@ +--TEST-- +preg_replace_callback_array() errors +--FILE-- + 'b', + "" => function () { return "ok"; }), 'a')); + +var_dump(preg_replace_callback_array( + array( + "/a/" => 'b', + null => function () { return "ok"; }), 'a')); + +// backslashes + +var_dump(preg_replace_callback_array( + array( + "/a/" => 'b', + "\\b\\" => function () { return "ok"; }), 'a')); + +// alphanumeric delimiters + +var_dump(preg_replace_callback_array( + array( + "/a/" => 'b', + "aba" => function () { return "ok"; }), 'a')); + +var_dump(preg_replace_callback_array( + array( + "/a/" => 'b', + "1b1" => function () { return "ok"; }), 'a')); + +// null character delimiter + +var_dump(preg_replace_callback_array( + array( + "/a/" => 'b', + "\0b\0" => function () { return "ok"; }), 'a')); + +?> +--EXPECTF-- +Warning: preg_replace_callback_array(): Empty regular expression in %spreg_replace_callback_array_error.php on line 12 +NULL + +Warning: preg_replace_callback_array(): Empty regular expression in %spreg_replace_callback_array_error.php on line 17 +NULL + +Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_callback_array_error.php on line 24 +NULL + +Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_callback_array_error.php on line 31 +NULL + +Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_callback_array_error.php on line 36 +NULL + +Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_callback_array_error.php on line 43 +NULL \ No newline at end of file diff --git a/ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt b/ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt new file mode 100644 index 0000000000000..0b018627de74a --- /dev/null +++ b/ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt @@ -0,0 +1,21 @@ +--TEST-- +preg_replace_callback_array() invalid callable +--FILE-- + 'b', + "/b/" => 'invalid callable'), 'a')); + +--EXPECTF-- +Fatal error: Uncaught TypeError: preg_replace_callback_array(): Argument #1 ($pattern) must contain only valid callbacks in %spreg_replace_callback_array_fatal_error.php:11 +Stack trace: +#0 %spreg_replace_callback_array_fatal_error.php(11): preg_replace_callback_array(Array, 'a') +#1 {main} + thrown in %spreg_replace_callback_array_fatal_error.php on line 11 diff --git a/ext/pcre/tests/preg_replace_callback_error1.phpt b/ext/pcre/tests/preg_replace_callback_error1.phpt index eb6478e506952..bd659bec9e5a8 100644 --- a/ext/pcre/tests/preg_replace_callback_error1.phpt +++ b/ext/pcre/tests/preg_replace_callback_error1.phpt @@ -30,7 +30,7 @@ foreach($regex_array as $regex_value) { Arg value is abcdef -Warning: preg_replace_callback(): Delimiter must not be alphanumeric or backslash in %s on line %d +Warning: preg_replace_callback(): Delimiter must not be alphanumeric, backslash, or NUL in %s on line %d NULL Arg value is /[a-zA-Z] diff --git a/ext/pcre/tests/preg_replace_error1.phpt b/ext/pcre/tests/preg_replace_error1.phpt index ccd3554745606..6ea93d1544977 100644 --- a/ext/pcre/tests/preg_replace_error1.phpt +++ b/ext/pcre/tests/preg_replace_error1.phpt @@ -33,7 +33,7 @@ try { Arg value is abcdef -Warning: preg_replace(): Delimiter must not be alphanumeric or backslash in %spreg_replace_error1.php on line %d +Warning: preg_replace(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_error1.php on line %d NULL Arg value is /[a-zA-Z] diff --git a/ext/pcre/tests/preg_split_error1.phpt b/ext/pcre/tests/preg_split_error1.phpt index 4d0fb9e22a45e..5ffb9f08ac3b1 100644 --- a/ext/pcre/tests/preg_split_error1.phpt +++ b/ext/pcre/tests/preg_split_error1.phpt @@ -36,7 +36,7 @@ try { Arg value is abcdef -Warning: preg_split(): Delimiter must not be alphanumeric or backslash in %spreg_split_error1.php on line %d +Warning: preg_split(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_split_error1.php on line %d bool(false) Arg value is /[a-zA-Z] From a8497cb8fea5d1eee1f99058817c56788f132e2a Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 17 Jun 2022 19:34:48 +0200 Subject: [PATCH 023/440] [ci skip] Fix NEWS format --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 23f5bbc9bc373..e89fbe0157b3a 100644 --- a/NEWS +++ b/NEWS @@ -19,7 +19,7 @@ PHP NEWS . Fixed bug #78139 (timezone_open accepts invalid timezone string argument). (Derick) -GD: +- GD: . Fixed imagecreatefromavif() memory leak. (cmb) - MBString: From d84b972658fe623b465ce0f3b6632de1e1875534 Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Fri, 17 Jun 2022 19:51:58 -0400 Subject: [PATCH 024/440] Fixed CURLOPT_TLSAUTH_TYPE is not treated as a string option. --- NEWS | 3 +++ ext/curl/interface.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index bc5d9fa38c308..edfa4f701756d 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2022, PHP 8.0.21 +- Curl: + . Fixed CURLOPT_TLSAUTH_TYPE is not treated as a string option. (Pierrick) + - Date: . Fixed bug #74671 (DST timezone abbreviation has incorrect offset). (Derick) . Fixed bug #77243 (Weekdays are calculated incorrectly for negative years). diff --git a/ext/curl/interface.c b/ext/curl/interface.c index ca49334207390..134de48d6fe22 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -2298,7 +2298,6 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i case CURLOPT_RTSP_REQUEST: case CURLOPT_RTSP_SERVER_CSEQ: case CURLOPT_WILDCARDMATCH: - case CURLOPT_TLSAUTH_TYPE: case CURLOPT_GSSAPI_DELEGATION: case CURLOPT_ACCEPTTIMEOUT_MS: case CURLOPT_SSL_OPTIONS: @@ -2417,6 +2416,7 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i case CURLOPT_MAIL_FROM: case CURLOPT_RTSP_STREAM_URI: case CURLOPT_RTSP_TRANSPORT: + case CURLOPT_TLSAUTH_TYPE: case CURLOPT_TLSAUTH_PASSWORD: case CURLOPT_TLSAUTH_USERNAME: case CURLOPT_ACCEPT_ENCODING: From 651e0cc187e8941f06d4c25ce965d33c0679a8f1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 14 Jun 2022 15:56:03 +0200 Subject: [PATCH 025/440] Fix GH-8778: Integer arithmethic with large number variants fails When casting a `variant` to `int`, we need to heed the proper `zval` type, which is an signed 64bit integer on x64, while `VT_INT` is only a signed 32bit integer. Closes GH-8779. --- NEWS | 4 ++++ ext/com_dotnet/com_handlers.c | 6 +++++- ext/com_dotnet/tests/gh8778.phpt | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 ext/com_dotnet/tests/gh8778.phpt diff --git a/NEWS b/NEWS index edfa4f701756d..0339d18311253 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2022, PHP 8.0.21 +- COM: + . Fixed bug GH-8778 (Integer arithmethic with large number variants fails). + (cmb) + - Curl: . Fixed CURLOPT_TLSAUTH_TYPE is not treated as a string option. (Pierrick) diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index fb4af4efec2c4..4b8fd09a453fb 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -453,7 +453,11 @@ static int com_object_cast(zend_object *readobj, zval *writeobj, int type) switch(type) { case IS_LONG: case _IS_NUMBER: - vt = VT_INT; +#if SIZEOF_ZEND_LONG == 4 + vt = VT_I4; +#else + vt = VT_I8; +#endif break; case IS_DOUBLE: vt = VT_R8; diff --git a/ext/com_dotnet/tests/gh8778.phpt b/ext/com_dotnet/tests/gh8778.phpt new file mode 100644 index 0000000000000..968804b7c5c81 --- /dev/null +++ b/ext/com_dotnet/tests/gh8778.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug GH-8778 (Integer arithmethic with large number variants fails) +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(4294967296) +int(4294967297) From 7d6821a98a3923deb5345ea4a69dca2b39a2f898 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 15 Jun 2022 18:31:46 +0200 Subject: [PATCH 026/440] Remove superfluous snapshot_build_exclusions These configuration options have been removed, so there is no need to still cater to them. Closes GH-8792. --- win32/build/confutils.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/win32/build/confutils.js b/win32/build/confutils.js index 83d4bafdaaab4..6dbc6a86ba225 100644 --- a/win32/build/confutils.js +++ b/win32/build/confutils.js @@ -450,14 +450,9 @@ can be built that way. \ } var snapshot_build_exclusions = new Array( - 'debug', 'lzf-better-compression', - 'php-build', 'snapshot-template', 'ereg', - 'pcre-regex', 'fastcgi', 'force-cgi-redirect', - 'path-info-check', 'zts', 'ipv6', 'memory-limit', - 'zend-multibyte', 'fd-setsize', 'memory-manager', - 'pgi', 'pgo', 'all-shared', 'config-profile', - 'sanitizer' - ); + 'debug', 'lzf-better-compression', 'php-build', 'snapshot-template', 'zts', + 'ipv6', 'fd-setsize', 'pgi', 'pgo', 'all-shared', 'config-profile', 'sanitizer' + ); var force; // Now set any defaults we might have missed out earlier From 2d986310f1327f44815e7eb2bf7fd653c734be6a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 9 Feb 2022 11:24:45 +0100 Subject: [PATCH 027/440] streams/xp_socket: eliminate poll() when MSG_DONTWAIT is available If there is a zero timeout and MSG_DONTWAIT is available (or the socket is non-blocking), the poll() call is not necessary, and we can just call recv() right away. Before this change: poll([{fd=4, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout) poll([{fd=4, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 1 ([{fd=4, revents=POLLIN}]) recvfrom(4, "HTTP/1.1 301 Moved Permanently\r\n"..., 8192, MSG_DONTWAIT, NULL, NULL) = 348 poll([{fd=4, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 1 ([{fd=4, revents=POLLIN}]) recvfrom(4, "", 1, MSG_PEEK, NULL, NULL) = 0 After this change: recvfrom(4, 0x7ffe0cc719a0, 1, MSG_PEEK|MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable) poll([{fd=4, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 1 ([{fd=4, revents=POLLIN}]) recvfrom(4, "HTTP/1.1 301 Moved Permanently\r\n"..., 8192, MSG_DONTWAIT, NULL, NULL) = 348 recvfrom(4, "", 1, MSG_PEEK|MSG_DONTWAIT, NULL, NULL) = 0 The first poll() is replaced by recvfrom(), and the third poll() is omitted completely. ext/openssl/xp_ssl: eliminate poll() when MSG_DONTWAIT is available If there is a zero timeout and MSG_DONTWAIT is available (or the socket is non-blocking), the poll() call is not necessary, and we can just call recv() right away. Closes GH-8092. --- NEWS | 6 ++++++ ext/openssl/xp_ssl.c | 11 +++++++++-- main/streams/xp_socket.c | 5 +++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 0788a72408cf2..bcb4a01a7b31b 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,9 @@ PHP NEWS - ODBC: . Fixed handling of single-key connection strings. (Calvin Buckley) +- OpenSSL: + . Discard poll calls on socket when no timeout/non blocking/MSG_DONTWAIT. (Max Kellermann) + - PCRE: . Implemented FR #77726 (Allow null character in regex patterns). (cmb) @@ -37,6 +40,9 @@ PHP NEWS - Standard: . Deprecated utf8_encode() and utf8_decode(). (Rowan Tommins) +- Streams: + . Discard poll calls on socket when no timeout/non blocking/MSG_DONTWAIT. (Max Kellermann) + 09 Jun 2022, PHP 8.2.0alpha1 - CLI: diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index ff5716c879153..14f767104fb76 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -46,6 +46,10 @@ #undef X509_EXTENSIONS #endif +#ifndef MSG_DONTWAIT +# define MSG_DONTWAIT 0 +#endif + /* Flags for determining allowed stream crypto methods */ #define STREAM_CRYPTO_IS_CLIENT (1<<0) #define STREAM_CRYPTO_METHOD_SSLv2 (1<<1) @@ -2395,7 +2399,10 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val if (sslsock->s.socket == -1) { alive = 0; - } else if (php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) { + } else if ((!sslsock->ssl_active && value == 0 && (MSG_DONTWAIT || !sslsock->s.is_blocked)) || + php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) { + /* the poll() call was skipped if the socket is non-blocking (or MSG_DONTWAIT is available) and if the timeout is zero */ + /* additionally, we don't use this optimization if SSL is active because in that case, we're not using MSG_DONTWAIT */ if (sslsock->ssl_active) { int n = SSL_peek(sslsock->ssl_handle, &buf, sizeof(buf)); if (n <= 0) { @@ -2413,7 +2420,7 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val alive = 0; } } - } else if (0 == recv(sslsock->s.socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EAGAIN) { + } else if (0 == recv(sslsock->s.socket, &buf, sizeof(buf), MSG_PEEK|MSG_DONTWAIT) && php_socket_errno() != EAGAIN) { alive = 0; } } diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index 10d584fa42415..16464031027c6 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -337,7 +337,8 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void if (sock->socket == -1) { alive = 0; - } else if (php_pollfd_for(sock->socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) { + } else if ((value == 0 && (MSG_DONTWAIT || !sock->is_blocked)) || php_pollfd_for(sock->socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) { + /* the poll() call was skipped if the socket is non-blocking (or MSG_DONTWAIT is available) and if the timeout is zero */ #ifdef PHP_WIN32 int ret; #else @@ -345,7 +346,7 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void #endif int err; - ret = recv(sock->socket, &buf, sizeof(buf), MSG_PEEK); + ret = recv(sock->socket, &buf, sizeof(buf), MSG_PEEK|MSG_DONTWAIT); err = php_socket_errno(); if (0 == ret || /* the counterpart did properly shutdown*/ (0 > ret && err != EWOULDBLOCK && err != EAGAIN && err != EMSGSIZE)) { /* there was an unrecoverable error */ From 49d3dde2114635bbdb3441ce84726ae56d3ca225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Sat, 18 Jun 2022 22:06:50 +0200 Subject: [PATCH 028/440] Declare true return types (#8759) --- Zend/Optimizer/zend_func_infos.h | 26 --------------- Zend/zend_builtin_functions.stub.php | 6 ++-- Zend/zend_builtin_functions_arginfo.h | 7 ++-- build/gen_stub.php | 13 ++++++-- ext/mysqli/mysqli.stub.php | 12 +++---- ext/mysqli/mysqli_arginfo.h | 30 +++++++++-------- ext/sodium/libsodium.stub.php | 3 +- ext/sodium/libsodium_arginfo.h | 4 +-- ext/standard/basic_functions.stub.php | 45 +++++++++----------------- ext/standard/basic_functions_arginfo.h | 25 ++++++++------ sapi/cli/tests/004.phpt | 2 +- 11 files changed, 72 insertions(+), 101 deletions(-) diff --git a/Zend/Optimizer/zend_func_infos.h b/Zend/Optimizer/zend_func_infos.h index 6ace0a5081c6a..9a3c2a2ac35fb 100644 --- a/Zend/Optimizer/zend_func_infos.h +++ b/Zend/Optimizer/zend_func_infos.h @@ -7,9 +7,7 @@ static const func_info_t func_infos[] = { F1("get_class_methods", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), F1("get_included_files", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), FN("set_error_handler", MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_OBJECT|MAY_BE_NULL), - F0("restore_error_handler", MAY_BE_TRUE), FN("set_exception_handler", MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_OBJECT|MAY_BE_NULL), - F0("restore_exception_handler", MAY_BE_TRUE), F1("get_declared_classes", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), F1("get_declared_traits", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), F1("get_declared_interfaces", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), @@ -268,10 +266,8 @@ static const func_info_t func_infos[] = { #endif F1("mysqli_affected_rows", MAY_BE_LONG|MAY_BE_STRING), F1("mysqli_character_set_name", MAY_BE_STRING), - F0("mysqli_close", MAY_BE_TRUE), F1("mysqli_connect", MAY_BE_OBJECT|MAY_BE_FALSE), F1("mysqli_connect_error", MAY_BE_STRING|MAY_BE_NULL), - F0("mysqli_debug", MAY_BE_TRUE), F1("mysqli_error", MAY_BE_STRING), F1("mysqli_error_list", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_ARRAY), F1("mysqli_fetch_field", MAY_BE_OBJECT|MAY_BE_FALSE), @@ -300,7 +296,6 @@ static const func_info_t func_infos[] = { F1("mysqli_real_escape_string", MAY_BE_STRING), F1("mysqli_reap_async_query", MAY_BE_OBJECT|MAY_BE_BOOL), F1("mysqli_stmt_affected_rows", MAY_BE_LONG|MAY_BE_STRING), - F0("mysqli_stmt_close", MAY_BE_TRUE), F1("mysqli_stmt_error", MAY_BE_STRING), F1("mysqli_stmt_error_list", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_ARRAY), F1("mysqli_stmt_get_result", MAY_BE_OBJECT|MAY_BE_FALSE), @@ -311,7 +306,6 @@ static const func_info_t func_infos[] = { F1("mysqli_stmt_result_metadata", MAY_BE_OBJECT|MAY_BE_FALSE), F1("mysqli_stmt_sqlstate", MAY_BE_STRING), F1("mysqli_sqlstate", MAY_BE_STRING), - F0("mysqli_ssl_set", MAY_BE_TRUE), F1("mysqli_stat", MAY_BE_STRING|MAY_BE_FALSE), F1("mysqli_store_result", MAY_BE_OBJECT|MAY_BE_FALSE), F1("mysqli_use_result", MAY_BE_OBJECT|MAY_BE_FALSE), @@ -438,7 +432,6 @@ static const func_info_t func_infos[] = { F1("socket_addrinfo_explain", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_ARRAY), FN("sodium_crypto_kx_client_session_keys", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), FN("sodium_crypto_kx_server_session_keys", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), - F0("sodium_crypto_generichash_update", MAY_BE_TRUE), #if defined(crypto_secretstream_xchacha20poly1305_ABYTES) FN("sodium_crypto_secretstream_xchacha20poly1305_init_push", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), #endif @@ -455,20 +448,9 @@ static const func_info_t func_infos[] = { F1("ob_get_clean", MAY_BE_STRING|MAY_BE_FALSE), F1("ob_list_handlers", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING), F1("ob_get_status", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_ARRAY), - F0("krsort", MAY_BE_TRUE), - F0("ksort", MAY_BE_TRUE), - F0("asort", MAY_BE_TRUE), - F0("arsort", MAY_BE_TRUE), - F0("sort", MAY_BE_TRUE), - F0("usort", MAY_BE_TRUE), - F0("uasort", MAY_BE_TRUE), - F0("uksort", MAY_BE_TRUE), - F0("array_walk", MAY_BE_TRUE), - F0("array_walk_recursive", MAY_BE_TRUE), F1("compact", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF), FN("array_fill", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_ANY), F1("array_fill_keys", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF), - F0("shuffle", MAY_BE_TRUE), F1("array_replace", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF), F1("array_replace_recursive", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF), FN("array_keys", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING), @@ -544,12 +526,6 @@ static const func_info_t func_infos[] = { F1("md5_file", MAY_BE_STRING|MAY_BE_FALSE), F1("sha1", MAY_BE_STRING), F1("sha1_file", MAY_BE_STRING|MAY_BE_FALSE), -#if defined(HAVE_SYSLOG_H) - F0("closelog", MAY_BE_TRUE), -#endif -#if defined(HAVE_SYSLOG_H) - F0("syslog", MAY_BE_TRUE), -#endif #if defined(HAVE_INET_NTOP) F1("inet_ntop", MAY_BE_STRING|MAY_BE_FALSE), #endif @@ -639,9 +615,7 @@ static const func_info_t func_infos[] = { F1("image_type_to_extension", MAY_BE_STRING|MAY_BE_FALSE), F1("getimagesize", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_FALSE), F1("getimagesizefromstring", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_FALSE), - F0("phpinfo", MAY_BE_TRUE), F1("phpversion", MAY_BE_STRING|MAY_BE_FALSE), - F0("phpcredits", MAY_BE_TRUE), F1("php_sapi_name", MAY_BE_STRING|MAY_BE_FALSE), F1("php_uname", MAY_BE_STRING), F1("php_ini_scanned_files", MAY_BE_STRING|MAY_BE_FALSE), diff --git a/Zend/zend_builtin_functions.stub.php b/Zend/zend_builtin_functions.stub.php index 20acca3a47ff7..bf6b8242c5a81 100644 --- a/Zend/zend_builtin_functions.stub.php +++ b/Zend/zend_builtin_functions.stub.php @@ -102,14 +102,12 @@ function user_error(string $message, int $error_level = E_USER_NOTICE): bool {} /** @return callable|null */ function set_error_handler(?callable $callback, int $error_levels = E_ALL) {} -/** @return true */ -function restore_error_handler(): bool {} +function restore_error_handler(): true {} /** @return callable|null */ function set_exception_handler(?callable $callback) {} -/** @return true */ -function restore_exception_handler(): bool {} +function restore_exception_handler(): true {} /** * @return array diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h index 37ea1f7aab1b3..c4bfc3c48b036 100644 --- a/Zend/zend_builtin_functions_arginfo.h +++ b/Zend/zend_builtin_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 69dcb08ae12b6acbba872f7de5018ca5c0aaf669 */ + * Stub hash: 33a976db268b72cee985011198125f652bc6c86d */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_version, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -139,7 +139,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_set_error_handler, 0, 0, 1) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, error_levels, IS_LONG, 0, "E_ALL") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_restore_error_handler, 0, 0, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_restore_error_handler, 0, 0, IS_TRUE, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_set_exception_handler, 0, 0, 1) @@ -207,7 +207,8 @@ ZEND_END_ARG_INFO() #define arginfo_gc_collect_cycles arginfo_func_num_args -#define arginfo_gc_enabled arginfo_restore_error_handler +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gc_enabled, 0, 0, _IS_BOOL, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gc_enable, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() diff --git a/build/gen_stub.php b/build/gen_stub.php index 4fbda773d5a3d..18763844280fa 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -188,6 +188,11 @@ public static function fromNode(Node $node): SimpleType { return new SimpleType($node->toLowerString(), true); } + if ($node->toLowerString() === 'true') { + // TODO PHP-Parser doesn't yet recognize true as a stand-alone built-in type + return new SimpleType($node->toLowerString(), true); + } + if ($node->toLowerString() === 'self') { throw new Exception('The exact class name must be used instead of "self"'); } @@ -380,6 +385,8 @@ public function toTypeCode(): string { return "IS_NULL"; case "false": return "IS_FALSE"; + case "true": + return "IS_TRUE"; default: throw new Exception("Not implemented: $this->name"); } @@ -393,6 +400,8 @@ public function toTypeMask(): string { return "MAY_BE_NULL"; case "false": return "MAY_BE_FALSE"; + case "true": + return "MAY_BE_TRUE"; case "bool": return "MAY_BE_BOOL"; case "int": @@ -443,6 +452,8 @@ public function toOptimizerTypeMaskForArrayValue(): string { return "MAY_BE_ARRAY_OF_NULL"; case "false": return "MAY_BE_ARRAY_OF_FALSE"; + case "true": + return "MAY_BE_ARRAY_OF_TRUE"; case "bool": return "MAY_BE_ARRAY_OF_FALSE|MAY_BE_ARRAY_OF_TRUE"; case "int": @@ -472,8 +483,6 @@ public function toOptimizerTypeMask(): string { } switch ($this->name) { - case "true": - return "MAY_BE_TRUE"; case "resource": return "MAY_BE_RESOURCE"; case "callable": diff --git a/ext/mysqli/mysqli.stub.php b/ext/mysqli/mysqli.stub.php index fe86c8478f223..288882a2a50ad 100644 --- a/ext/mysqli/mysqli.stub.php +++ b/ext/mysqli/mysqli.stub.php @@ -749,8 +749,7 @@ function mysqli_change_user(mysqli $mysql, string $username, string $password, ? /** @refcount 1 */ function mysqli_character_set_name(mysqli $mysql): string {} -/** @return true */ -function mysqli_close(mysqli $mysql): bool {} // TODO make return type void +function mysqli_close(mysqli $mysql): true {} // TODO make return type void function mysqli_commit(mysqli $mysql, int $flags = 0, ?string $name = null): bool {} @@ -776,8 +775,7 @@ function mysqli_data_seek(mysqli_result $result, int $offset): bool {} function mysqli_dump_debug_info(mysqli $mysql): bool {} -/** @return true */ -function mysqli_debug(string $options): bool {} // TODO make return type void +function mysqli_debug(string $options): true {} // TODO make return type void function mysqli_errno(mysqli $mysql): int {} @@ -976,8 +974,7 @@ function mysqli_stmt_bind_param(mysqli_stmt $statement, string $types, mixed &.. function mysqli_stmt_bind_result(mysqli_stmt $statement, mixed &...$vars): bool {} -/** @return true */ -function mysqli_stmt_close(mysqli_stmt $statement): bool {} +function mysqli_stmt_close(mysqli_stmt $statement): true {} function mysqli_stmt_data_seek(mysqli_stmt $statement, int $offset): void {} @@ -1036,7 +1033,6 @@ function mysqli_stmt_sqlstate(mysqli_stmt $statement): string {} /** @refcount 1 */ function mysqli_sqlstate(mysqli $mysql): string {} -/** @return true */ function mysqli_ssl_set( mysqli $mysql, ?string $key, @@ -1044,7 +1040,7 @@ function mysqli_ssl_set( ?string $ca_certificate, ?string $ca_path, ?string $cipher_algos -): bool {} // TODO make return type void +): true {} // TODO make return type void /** @refcount 1 */ function mysqli_stat(mysqli $mysql): string|false {} diff --git a/ext/mysqli/mysqli_arginfo.h b/ext/mysqli/mysqli_arginfo.h index 606d893799dc9..6e0a7f5bb1545 100644 --- a/ext/mysqli/mysqli_arginfo.h +++ b/ext/mysqli/mysqli_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: db2ec0349b8b40e9352569e08cb4a3bd253f0255 */ + * Stub hash: e528bb1e05a85d3d764272c5f3f4256d2608da6c */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_affected_rows, 0, 1, MAY_BE_LONG|MAY_BE_STRING) ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0) @@ -27,7 +27,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_character_set_name, 0, 1, ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_close, 0, 1, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_close, 0, 1, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0) ZEND_END_ARG_INFO() @@ -53,9 +53,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_data_seek, 0, 2, _IS_BOOL ZEND_ARG_TYPE_INFO(0, offset, IS_LONG, 0) ZEND_END_ARG_INFO() -#define arginfo_mysqli_dump_debug_info arginfo_mysqli_close +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_dump_debug_info, 0, 1, _IS_BOOL, 0) + ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0) +ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_debug, 0, 1, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_debug, 0, 1, IS_TRUE, 0) ZEND_ARG_TYPE_INFO(0, options, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -178,14 +180,14 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_kill, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, process_id, IS_LONG, 0) ZEND_END_ARG_INFO() -#define arginfo_mysqli_more_results arginfo_mysqli_close +#define arginfo_mysqli_more_results arginfo_mysqli_dump_debug_info ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_multi_query, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0) ZEND_ARG_TYPE_INFO(0, query, IS_STRING, 0) ZEND_END_ARG_INFO() -#define arginfo_mysqli_next_result arginfo_mysqli_close +#define arginfo_mysqli_next_result arginfo_mysqli_dump_debug_info #define arginfo_mysqli_num_fields arginfo_mysqli_field_tell @@ -201,7 +203,7 @@ ZEND_END_ARG_INFO() #define arginfo_mysqli_set_opt arginfo_mysqli_options -#define arginfo_mysqli_ping arginfo_mysqli_close +#define arginfo_mysqli_ping arginfo_mysqli_dump_debug_info ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_poll, 0, 4, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(1, read, IS_ARRAY, 1) @@ -295,7 +297,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_stmt_bind_result, 0, 1, _ ZEND_ARG_VARIADIC_TYPE_INFO(1, vars, IS_MIXED, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_stmt_close, 0, 1, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_stmt_close, 0, 1, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, statement, mysqli_stmt, 0) ZEND_END_ARG_INFO() @@ -340,9 +342,11 @@ ZEND_END_ARG_INFO() #define arginfo_mysqli_stmt_insert_id arginfo_mysqli_stmt_affected_rows -#define arginfo_mysqli_stmt_more_results arginfo_mysqli_stmt_close +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_stmt_more_results, 0, 1, _IS_BOOL, 0) + ZEND_ARG_OBJ_INFO(0, statement, mysqli_stmt, 0) +ZEND_END_ARG_INFO() -#define arginfo_mysqli_stmt_next_result arginfo_mysqli_stmt_close +#define arginfo_mysqli_stmt_next_result arginfo_mysqli_stmt_more_results #define arginfo_mysqli_stmt_num_rows arginfo_mysqli_stmt_affected_rows @@ -353,7 +357,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_stmt_prepare, 0, 2, _IS_B ZEND_ARG_TYPE_INFO(0, query, IS_STRING, 0) ZEND_END_ARG_INFO() -#define arginfo_mysqli_stmt_reset arginfo_mysqli_stmt_close +#define arginfo_mysqli_stmt_reset arginfo_mysqli_stmt_more_results #define arginfo_mysqli_stmt_result_metadata arginfo_mysqli_stmt_get_result @@ -363,13 +367,13 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_stmt_send_long_data, 0, 3 ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0) ZEND_END_ARG_INFO() -#define arginfo_mysqli_stmt_store_result arginfo_mysqli_stmt_close +#define arginfo_mysqli_stmt_store_result arginfo_mysqli_stmt_more_results #define arginfo_mysqli_stmt_sqlstate arginfo_mysqli_stmt_error #define arginfo_mysqli_sqlstate arginfo_mysqli_character_set_name -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_ssl_set, 0, 6, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_ssl_set, 0, 6, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 1) ZEND_ARG_TYPE_INFO(0, certificate, IS_STRING, 1) diff --git a/ext/sodium/libsodium.stub.php b/ext/sodium/libsodium.stub.php index 9a62357f582ca..edf6d5d224126 100644 --- a/ext/sodium/libsodium.stub.php +++ b/ext/sodium/libsodium.stub.php @@ -152,8 +152,7 @@ function sodium_crypto_generichash_keygen(): string {} /** @sensitive-param $key */ function sodium_crypto_generichash_init(string $key = "", int $length = SODIUM_CRYPTO_GENERICHASH_BYTES): string {} -/** @return true */ -function sodium_crypto_generichash_update(string &$state, string $message): bool {} +function sodium_crypto_generichash_update(string &$state, string $message): true {} function sodium_crypto_generichash_final(string &$state, int $length = SODIUM_CRYPTO_GENERICHASH_BYTES): string {} diff --git a/ext/sodium/libsodium_arginfo.h b/ext/sodium/libsodium_arginfo.h index 052a95fa18452..411bf5c544951 100644 --- a/ext/sodium/libsodium_arginfo.h +++ b/ext/sodium/libsodium_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: d751b690703cb449e249d693d177cdb94087ce82 */ + * Stub hash: ba84ba9ace7a751935d7beead34e3fbb9a511cc7 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_sodium_crypto_aead_aes256gcm_is_available, 0, 0, _IS_BOOL, 0) ZEND_END_ARG_INFO() @@ -223,7 +223,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_sodium_crypto_generichash_init, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, length, IS_LONG, 0, "SODIUM_CRYPTO_GENERICHASH_BYTES") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_sodium_crypto_generichash_update, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_sodium_crypto_generichash_update, 0, 2, IS_TRUE, 0) ZEND_ARG_TYPE_INFO(1, state, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, message, IS_STRING, 0) ZEND_END_ARG_INFO() diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 3ecd69a1de173..5020fa4d2897f 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -82,11 +82,9 @@ function stream_wrapper_restore(string $protocol): bool {} function array_push(array &$array, mixed ...$values): int {} -/** @return true */ -function krsort(array &$array, int $flags = SORT_REGULAR): bool {} +function krsort(array &$array, int $flags = SORT_REGULAR): true {} -/** @return true */ -function ksort(array &$array, int $flags = SORT_REGULAR): bool {} +function ksort(array &$array, int $flags = SORT_REGULAR): true {} /** @compile-time-eval */ function count(Countable|array $value, int $mode = COUNT_NORMAL): int {} @@ -98,25 +96,19 @@ function natsort(array &$array): bool {} function natcasesort(array &$array): bool {} -/** @return true */ -function asort(array &$array, int $flags = SORT_REGULAR): bool {} +function asort(array &$array, int $flags = SORT_REGULAR): true {} -/** @return true */ -function arsort(array &$array, int $flags = SORT_REGULAR): bool {} +function arsort(array &$array, int $flags = SORT_REGULAR): true {} -/** @return true */ -function sort(array &$array, int $flags = SORT_REGULAR): bool {} +function sort(array &$array, int $flags = SORT_REGULAR): true {} function rsort(array &$array, int $flags = SORT_REGULAR): bool {} -/** @return true */ -function usort(array &$array, callable $callback): bool {} +function usort(array &$array, callable $callback): true {} -/** @return true */ -function uasort(array &$array, callable $callback): bool {} +function uasort(array &$array, callable $callback): true {} -/** @return true */ -function uksort(array &$array, callable $callback): bool {} +function uksort(array &$array, callable $callback): true {} function end(array|object &$array): mixed {} @@ -139,11 +131,9 @@ function min(mixed $value, mixed ...$values): mixed {} /** @compile-time-eval */ function max(mixed $value, mixed ...$values): mixed {} -/** @return true */ -function array_walk(array|object &$array, callable $callback, mixed $arg = UNKNOWN): bool {} +function array_walk(array|object &$array, callable $callback, mixed $arg = UNKNOWN): true {} -/** @return true */ -function array_walk_recursive(array|object &$array, callable $callback, mixed $arg = UNKNOWN): bool {} +function array_walk_recursive(array|object &$array, callable $callback, mixed $arg = UNKNOWN): true {} /** * @compile-time-eval @@ -178,8 +168,7 @@ function array_fill_keys(array $keys, mixed $value): array {} */ function range($start, $end, int|float $step = 1): array {} -/** @return true */ -function shuffle(array &$array): bool {} +function shuffle(array &$array): true {} function array_pop(array &$array): mixed {} @@ -697,11 +686,9 @@ function sha1_file(string $filename, bool $binary = false): string|false {} #ifdef HAVE_SYSLOG_H function openlog(string $prefix, int $flags, int $facility): bool {} -/** @return true */ -function closelog(): bool {} +function closelog(): true {} -/** @return true */ -function syslog(int $priority, string $message): bool {} // TODO make return type void +function syslog(int $priority, string $message): true {} // TODO make return type void #endif #ifdef HAVE_INET_NTOP @@ -1424,8 +1411,7 @@ function getimagesizefromstring(string $string, &$image_info = null): array|fals /* info.c */ -/** @return true */ -function phpinfo(int $flags = INFO_ALL): bool {} // make return type void +function phpinfo(int $flags = INFO_ALL): true {} // make return type void /** * @compile-time-eval @@ -1433,8 +1419,7 @@ function phpinfo(int $flags = INFO_ALL): bool {} // make return type void */ function phpversion(?string $extension = null): string|false {} -/** @return true */ -function phpcredits(int $flags = CREDITS_ALL): bool {} +function phpcredits(int $flags = CREDITS_ALL): true {} /** * @compile-time-eval diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index a34a50f074b6c..0b6881a99bd17 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3ce386bb8ab215ad532826e053b8487fd3fd5582 */ + * Stub hash: 90093c63384f7ba56b1c4073b60219cb82843b98 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -74,7 +74,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_push, 0, 1, IS_LONG, 0) ZEND_ARG_VARIADIC_TYPE_INFO(0, values, IS_MIXED, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_krsort, 0, 1, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_krsort, 0, 1, IS_TRUE, 0) ZEND_ARG_TYPE_INFO(1, array, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "SORT_REGULAR") ZEND_END_ARG_INFO() @@ -100,9 +100,12 @@ ZEND_END_ARG_INFO() #define arginfo_sort arginfo_krsort -#define arginfo_rsort arginfo_krsort +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_rsort, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(1, array, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "SORT_REGULAR") +ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_usort, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_usort, 0, 2, IS_TRUE, 0) ZEND_ARG_TYPE_INFO(1, array, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) ZEND_END_ARG_INFO() @@ -138,7 +141,7 @@ ZEND_END_ARG_INFO() #define arginfo_max arginfo_min -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_walk, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_walk, 0, 2, IS_TRUE, 0) ZEND_ARG_TYPE_MASK(1, array, MAY_BE_ARRAY|MAY_BE_OBJECT, NULL) ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) ZEND_ARG_TYPE_INFO(0, arg, IS_MIXED, 0) @@ -186,7 +189,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_range, 0, 2, IS_ARRAY, 0) ZEND_ARG_TYPE_MASK(0, step, MAY_BE_LONG|MAY_BE_DOUBLE, "1") ZEND_END_ARG_INFO() -#define arginfo_shuffle arginfo_natsort +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shuffle, 0, 1, IS_TRUE, 0) + ZEND_ARG_TYPE_INFO(1, array, IS_ARRAY, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_pop, 0, 1, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(1, array, IS_ARRAY, 0) @@ -708,12 +713,12 @@ ZEND_END_ARG_INFO() #endif #if defined(HAVE_SYSLOG_H) -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_closelog, 0, 0, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_closelog, 0, 0, IS_TRUE, 0) ZEND_END_ARG_INFO() #endif #if defined(HAVE_SYSLOG_H) -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_syslog, 0, 2, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_syslog, 0, 2, IS_TRUE, 0) ZEND_ARG_TYPE_INFO(0, priority, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, message, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -1527,7 +1532,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_getimagesizefromstring, 0, 1, MA ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, image_info, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_phpinfo, 0, 0, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_phpinfo, 0, 0, IS_TRUE, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "INFO_ALL") ZEND_END_ARG_INFO() @@ -1535,7 +1540,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_phpversion, 0, 0, MAY_BE_STRING| ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, extension, IS_STRING, 1, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_phpcredits, 0, 0, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_phpcredits, 0, 0, IS_TRUE, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "CREDITS_ALL") ZEND_END_ARG_INFO() diff --git a/sapi/cli/tests/004.phpt b/sapi/cli/tests/004.phpt index 094161a8fafcf..36726f5738af6 100644 --- a/sapi/cli/tests/004.phpt +++ b/sapi/cli/tests/004.phpt @@ -25,7 +25,7 @@ string(155) "Function [ function phpinfo ] { - Parameters [1] { Parameter #0 [ int $flags = INFO_ALL ] } - - Return [ bool ] + - Return [ true ] } " From 526af6ea670cd6294a7b3a0185b49e598b60f38d Mon Sep 17 00:00:00 2001 From: Ayesh Karunaratne Date: Sun, 19 Jun 2022 14:52:06 +0530 Subject: [PATCH 029/440] [ci skip] Add true type support to UPGRADING file Closes GH-8826. --- UPGRADING | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UPGRADING b/UPGRADING index 1f47c862c7af1..b330c28e42630 100644 --- a/UPGRADING +++ b/UPGRADING @@ -71,6 +71,8 @@ PHP 8.2 UPGRADE NOTES RFC: https://wiki.php.net/rfc/null-false-standalone-types . Added support for readonly classes. RFC: https://wiki.php.net/rfc/readonly_classes + . Added support for true type. + RFC: https://wiki.php.net/rfc/true-type - Curl: From e330f443c937c7f45cf9492ddbe0121f88789123 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 12 Jun 2022 22:32:48 +0100 Subject: [PATCH 030/440] Fix bug #67764: fpm: syslog.ident does not work --- NEWS | 3 +++ ext/standard/syslog.c | 7 +------ main/php_syslog.c | 12 ++++++++++++ main/php_syslog.h | 1 + sapi/fpm/fpm/fpm_stdio.c | 2 +- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 0339d18311253..4325fe3ff47e2 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,9 @@ PHP NEWS . Fixed bug #78139 (timezone_open accepts invalid timezone string argument). (Derick) +- FPM: + . Fixed bug #67764 (fpm: syslog.ident don't work). (Jakub Zelenka) + - MBString: . Fixed bug GH-8685 (pcre not ready at mbstring startup). (Remi) diff --git a/ext/standard/syslog.c b/ext/standard/syslog.c index 5926abf34eaff..866a6a3524a04 100644 --- a/ext/standard/syslog.c +++ b/ext/standard/syslog.c @@ -120,11 +120,6 @@ PHP_MSHUTDOWN_FUNCTION(syslog) return SUCCESS; } -void php_openlog(const char *ident, int option, int facility) -{ - openlog(ident, option, facility); - PG(have_called_openlog) = 1; -} /* {{{ Open connection to system logger */ /* @@ -161,7 +156,7 @@ PHP_FUNCTION(closelog) { ZEND_PARSE_PARAMETERS_NONE(); - closelog(); + php_closelog(); if (BG(syslog_device)) { free(BG(syslog_device)); BG(syslog_device)=NULL; diff --git a/main/php_syslog.c b/main/php_syslog.c index 37bf5a7fb615b..7538834cc7c38 100644 --- a/main/php_syslog.c +++ b/main/php_syslog.c @@ -32,6 +32,18 @@ #define syslog std_syslog #endif +void php_openlog(const char *ident, int option, int facility) +{ + openlog(ident, option, facility); + PG(have_called_openlog) = 1; +} + +void php_closelog() +{ + closelog(); + PG(have_called_openlog) = 0; +} + #ifdef PHP_WIN32 PHPAPI void php_syslog(int priority, const char *format, ...) /* {{{ */ { diff --git a/main/php_syslog.h b/main/php_syslog.h index 227baa8b16243..10c6eb7c8d9b1 100644 --- a/main/php_syslog.h +++ b/main/php_syslog.h @@ -37,6 +37,7 @@ BEGIN_EXTERN_C() PHPAPI void php_syslog(int, const char *format, ...); PHPAPI void php_openlog(const char *, int, int); +PHPAPI void php_closelog(); END_EXTERN_C() #endif diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c index 1742467b36816..9454710e536ea 100644 --- a/sapi/fpm/fpm/fpm_stdio.c +++ b/sapi/fpm/fpm/fpm_stdio.c @@ -88,7 +88,7 @@ int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ { #ifdef HAVE_SYSLOG_H if (fpm_globals.error_log_fd == ZLOG_SYSLOG) { - closelog(); /* ensure to close syslog not to interrupt with PHP syslog code */ + php_closelog(); /* ensure to close syslog not to interrupt with PHP syslog code */ } else #endif From 84b570e3aec25bb2b76455b73e70661a201a9953 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sun, 19 Jun 2022 23:18:46 +0200 Subject: [PATCH 031/440] Remove NEWS entries which are not supposed to be there master/NEWS is not supposed to contain changes done prior to RC, if these changes are also in lower branches. --- NEWS | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/NEWS b/NEWS index bcb4a01a7b31b..70e494dc06e51 100644 --- a/NEWS +++ b/NEWS @@ -10,33 +10,16 @@ PHP NEWS . Fixed bug GH-7821 and GH-8418 (Allow arbitrary const expressions in backed enums). (ilutov) -- COM: - . Fixed bug GH-8778 (Integer arithmethic with large number variants fails). - (cmb) - - Curl: . Added new constants from cURL 7.62 to 7.80. (Pierrick) . New function curl_upkeep(). (Pierrick) -- GD: - . Fixed imagecreatefromavif() memory leak. (cmb) - -- MBString: - . Backwards-compatible mappings for 0x5C/0x7E in Shift-JIS are restored, - after they had been changed in 8.1.0. (Alex Dowad) - -- ODBC: - . Fixed handling of single-key connection strings. (Calvin Buckley) - - OpenSSL: . Discard poll calls on socket when no timeout/non blocking/MSG_DONTWAIT. (Max Kellermann) - PCRE: . Implemented FR #77726 (Allow null character in regex patterns). (cmb) -- PDO_ODBC: - . Fixed handling of single-key connection strings. (Calvin Buckley) - - Standard: . Deprecated utf8_encode() and utf8_decode(). (Rowan Tommins) From d9cca443ad38a42fcf1faffa794146114efac00c Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 19 Jun 2022 22:56:44 +0100 Subject: [PATCH 032/440] Fix strict prototype for php_closelog --- main/php_syslog.c | 2 +- main/php_syslog.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/main/php_syslog.c b/main/php_syslog.c index b90719609eab3..fa71a86313466 100644 --- a/main/php_syslog.c +++ b/main/php_syslog.c @@ -77,7 +77,7 @@ void php_openlog(const char *ident, int option, int facility) PG(have_called_openlog) = 1; } -void php_closelog() +void php_closelog(void) { closelog(); PG(have_called_openlog) = 0; diff --git a/main/php_syslog.h b/main/php_syslog.h index e39de02bd0531..f2682d74f2382 100644 --- a/main/php_syslog.h +++ b/main/php_syslog.h @@ -38,7 +38,7 @@ BEGIN_EXTERN_C() PHPAPI void php_syslog_str(int priority, const zend_string* message); PHPAPI void php_syslog(int, const char *format, ...); PHPAPI void php_openlog(const char *, int, int); -PHPAPI void php_closelog(); +PHPAPI void php_closelog(void); END_EXTERN_C() #endif From 229e80c6ef507cc26dbd02f0b392f270e1fb6ebe Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 20 Jun 2022 10:59:37 +0300 Subject: [PATCH 033/440] Fix memory leak This fixes oss-fuzz #48051 --- ext/opcache/Optimizer/block_pass.c | 3 ++- ext/opcache/tests/opt/inline_001.phpt | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/opt/inline_001.phpt diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index bad814ed6ea8c..c8009ae8dec3b 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -295,7 +295,8 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array src->opcode != ZEND_FETCH_STATIC_PROP_R && src->opcode != ZEND_FETCH_DIM_R && src->opcode != ZEND_FETCH_OBJ_R && - src->opcode != ZEND_NEW) { + src->opcode != ZEND_NEW && + src->opcode != ZEND_FETCH_THIS) { src->result_type = IS_UNUSED; MAKE_NOP(opline); ++(*opt_count); diff --git a/ext/opcache/tests/opt/inline_001.phpt b/ext/opcache/tests/opt/inline_001.phpt new file mode 100644 index 0000000000000..063f240c1a74e --- /dev/null +++ b/ext/opcache/tests/opt/inline_001.phpt @@ -0,0 +1,22 @@ +--TEST-- +Fuction inlining 001: FETCH_THIS is incompatible with unused result +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECT-- +DONE From fa75bd078511c80c8be655719c7681fa65798c13 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 20 Jun 2022 11:30:07 +0300 Subject: [PATCH 034/440] Fix incorrect constant propagation for VERIFY_RETURN_TYPE This fixes oss-fuzz #48104 --- Zend/Optimizer/sccp.c | 10 +++++++++- ext/opcache/tests/opt/sccp_041.phpt | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/opt/sccp_041.phpt diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index 8317f9700ca6d..9373ad2adc63d 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -1721,7 +1721,7 @@ static zval *value_from_type_and_range(sccp_ctx *ctx, int var_num, zval *tmp) { } if (!(info->type & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_NULL))) { - if (ssa->vars[var_num].definition >= 0 + if (ssa->vars[var_num].definition >= 0 && ctx->scdf.op_array->opcodes[ssa->vars[var_num].definition].opcode == ZEND_VERIFY_RETURN_TYPE) { return NULL; } @@ -1729,10 +1729,18 @@ static zval *value_from_type_and_range(sccp_ctx *ctx, int var_num, zval *tmp) { return tmp; } if (!(info->type & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_FALSE))) { + if (ssa->vars[var_num].definition >= 0 + && ctx->scdf.op_array->opcodes[ssa->vars[var_num].definition].opcode == ZEND_VERIFY_RETURN_TYPE) { + return NULL; + } ZVAL_FALSE(tmp); return tmp; } if (!(info->type & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_TRUE))) { + if (ssa->vars[var_num].definition >= 0 + && ctx->scdf.op_array->opcodes[ssa->vars[var_num].definition].opcode == ZEND_VERIFY_RETURN_TYPE) { + return NULL; + } ZVAL_TRUE(tmp); return tmp; } diff --git a/ext/opcache/tests/opt/sccp_041.phpt b/ext/opcache/tests/opt/sccp_041.phpt new file mode 100644 index 0000000000000..81b3f90d75723 --- /dev/null +++ b/ext/opcache/tests/opt/sccp_041.phpt @@ -0,0 +1,15 @@ +--TEST-- +SCCP 041: Incorrect constant propagation for VERIFY_RETURN_TYPE +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECT-- +DONE From 93a44f8c502a348899db1ecc417b7e42ce95bf00 Mon Sep 17 00:00:00 2001 From: Heiko Weber Date: Wed, 15 Jun 2022 16:51:06 +0200 Subject: [PATCH 035/440] Fix potential use after free in php_binary_init() Closes GH-8791. --- NEWS | 3 +++ main/main.c | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index 4325fe3ff47e2..584fa704cf49e 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2022, PHP 8.0.21 +- Core: + . Fixed potential use after free in php_binary_init(). (Heiko Weber) + - COM: . Fixed bug GH-8778 (Integer arithmethic with large number variants fails). (cmb) diff --git a/main/main.c b/main/main.c index 7bd5400760f05..a40a4c8c37cdc 100644 --- a/main/main.c +++ b/main/main.c @@ -352,15 +352,15 @@ static void php_binary_init(void) { char *binary_location = NULL; #ifdef PHP_WIN32 - binary_location = (char *)malloc(MAXPATHLEN); - if (binary_location && GetModuleFileName(0, binary_location, MAXPATHLEN) == 0) { - free(binary_location); - PG(php_binary) = NULL; + binary_location = (char *)pemalloc(MAXPATHLEN, 1); + if (GetModuleFileName(0, binary_location, MAXPATHLEN) == 0) { + pefree(binary_location, 1); + binary_location = NULL; } #else if (sapi_module.executable_location) { - binary_location = (char *)malloc(MAXPATHLEN); - if (binary_location && !strchr(sapi_module.executable_location, '/')) { + binary_location = (char *)pemalloc(MAXPATHLEN, 1); + if (!strchr(sapi_module.executable_location, '/')) { char *envpath, *path; int found = 0; @@ -383,11 +383,11 @@ static void php_binary_init(void) efree(path); } if (!found) { - free(binary_location); + pefree(binary_location, 1); binary_location = NULL; } } else if (!VCWD_REALPATH(sapi_module.executable_location, binary_location) || VCWD_ACCESS(binary_location, X_OK)) { - free(binary_location); + pefree(binary_location, 1); binary_location = NULL; } } From e67565f54c0ebc18f2618802ad32b9d896f010e4 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 20 Jun 2022 13:27:01 +0200 Subject: [PATCH 036/440] Zend, ext/opcache: use PR_SET_VMA_ANON_NAME (Linux 5.17) (#8234) The new Linux 5.17 feature PR_SET_VMA_ANON_NAME can give names to anonymous private memory, see: https://lwn.net/Articles/867818/ It can be useful while debugging, to identify which portion of the process's memory belongs to which subsystem. This is how /proc/PID/maps can look like: 555ccd400000-555ccdc00000 r-xp 00000000 00:00 0 [anon:huge_code_pages] 7f6ec6600000-7f6ec6800000 rw-p 00000000 00:00 0 [anon:zend_alloc] The first mapping is the PHP executable copied to anonymous memory by option "opcache.huge_code_pages". The second one is a memory area for the "zend_alloc.h" memory allocator library. Unfortunately, it is not possible to give names to shared memory (MAP_SHARED), because Linux MAP_SHARED really maps /dev/zero (see shmem_zero_setup()), which makes madvise_vma_anon_name() believe this is a file mapping, failing the prctl() with EBADF. --- Zend/zend_alloc.c | 3 ++ Zend/zend_fibers.c | 3 ++ Zend/zend_mmap.h | 44 ++++++++++++++++++++++++++++ ext/opcache/ZendAccelerator.c | 3 ++ ext/opcache/jit/zend_jit_perf_dump.c | 6 +++- 5 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 Zend/zend_mmap.h diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 0ed2ee2a79aec..f25b10360e59a 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -57,6 +57,7 @@ #include "zend_operators.h" #include "zend_multiply.h" #include "zend_bitset.h" +#include "zend_mmap.h" #include #ifdef HAVE_UNISTD_H @@ -475,6 +476,7 @@ static void *zend_mm_mmap(size_t size) #endif ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, mflags, fd, 0); if (ptr != MAP_FAILED) { + zend_mmap_set_name(ptr, size, "zend_alloc"); return ptr; } } @@ -488,6 +490,7 @@ static void *zend_mm_mmap(size_t size) #endif return NULL; } + zend_mmap_set_name(ptr, size, "zend_alloc"); return ptr; #endif } diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 1fec85528fbb3..3bfce69327ec8 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -24,6 +24,7 @@ #include "zend_exceptions.h" #include "zend_builtin_functions.h" #include "zend_observer.h" +#include "zend_mmap.h" #include "zend_fibers.h" #include "zend_fibers_arginfo.h" @@ -211,6 +212,8 @@ static zend_fiber_stack *zend_fiber_stack_allocate(size_t size) return NULL; } + zend_mmap_set_name(pointer, alloc_size, "zend_fiber_stack"); + # if ZEND_FIBER_GUARD_PAGES if (mprotect(pointer, ZEND_FIBER_GUARD_PAGES * page_size, PROT_NONE) < 0) { zend_throw_exception_ex(NULL, 0, "Fiber stack protect failed: mprotect failed: %s (%d)", strerror(errno), errno); diff --git a/Zend/zend_mmap.h b/Zend/zend_mmap.h new file mode 100644 index 0000000000000..53eee61a7ef0c --- /dev/null +++ b/Zend/zend_mmap.h @@ -0,0 +1,44 @@ +/* + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Max Kellermann | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_MMAP_H +#define ZEND_MMAP_H + +#include "zend_portability.h" + +#ifdef __linux__ +# include + +/* fallback definitions if our libc is older than the kernel */ +# ifndef PR_SET_VMA +# define PR_SET_VMA 0x53564d41 +# endif +# ifndef PR_SET_VMA_ANON_NAME +# define PR_SET_VMA_ANON_NAME 0 +# endif +#endif // __linux__ + +/** + * Set a name for the specified memory area. + * + * This feature requires Linux 5.17. + */ +static zend_always_inline void zend_mmap_set_name(const void *start, size_t len, const char *name) +{ +#ifdef __linux__ + prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (unsigned long)start, len, (unsigned long)name); +#endif +} + +#endif /* ZEND_MMAP_H */ diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 8ed0caae85ee7..bf62383b6c274 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -34,6 +34,7 @@ #include "zend_vm.h" #include "zend_inheritance.h" #include "zend_exceptions.h" +#include "zend_mmap.h" #include "main/php_main.h" #include "main/SAPI.h" #include "main/php_streams.h" @@ -2987,6 +2988,8 @@ static int accel_remap_huge_pages(void *start, size_t size, size_t real_size, co # endif } + zend_mmap_set_name(start, size, "zend_huge_code_pages"); + if (ret == start) { memcpy(start, mem, real_size); mprotect(start, size, PROT_READ | PROT_EXEC); diff --git a/ext/opcache/jit/zend_jit_perf_dump.c b/ext/opcache/jit/zend_jit_perf_dump.c index ace998fe9d9ad..32ba5cd934544 100644 --- a/ext/opcache/jit/zend_jit_perf_dump.c +++ b/ext/opcache/jit/zend_jit_perf_dump.c @@ -46,6 +46,7 @@ extern unsigned int thr_self(void); #endif #include "zend_elf.h" +#include "zend_mmap.h" /* * 1) Profile using perf-.map @@ -171,8 +172,9 @@ static void zend_jit_perf_jitdump_open(void) return; } + const size_t page_size = sysconf(_SC_PAGESIZE); jitdump_mem = mmap(NULL, - sysconf(_SC_PAGESIZE), + page_size, PROT_READ|PROT_EXEC, MAP_PRIVATE, jitdump_fd, 0); @@ -182,6 +184,8 @@ static void zend_jit_perf_jitdump_open(void) return; } + zend_mmap_set_name(jitdump_mem, page_size, "zend_jitdump"); + memset(&jit_hdr, 0, sizeof(jit_hdr)); jit_hdr.magic = ZEND_PERF_JITDUMP_HEADER_MAGIC; jit_hdr.version = ZEND_PERF_JITDUMP_HEADER_VERSION; From 6f87a5c6338d0d64d18e3a44b65c19acc9c529e8 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 27 May 2022 13:13:50 +0100 Subject: [PATCH 037/440] Fix GH-8563 Different results for seek() on SplFileObject and SplTempFileObject With memory streams if we get a NULL buffer we must not instantiate an empty line --- NEWS | 3 ++ ext/spl/spl_directory.c | 23 +++++---- .../SplFileObject_fgetcsv_basic.phpt | 2 + .../SplFileObject_key_error001.phpt | 2 +- .../SplFileObject_key_error002.phpt | 2 +- .../fgetcsv_file_empty_lines.phpt | 38 +++++++++++++++ .../foreach_file_empty_lines.phpt | 37 ++++++++++++++ ext/spl/tests/SplFileObject/gh8563.phpt | 48 +++++++++++++++++++ ext/spl/tests/bug81477.phpt | 1 - ext/spl/tests/fileobject_001.phpt | 2 +- 10 files changed, 142 insertions(+), 16 deletions(-) rename ext/spl/tests/{ => SplFileObject}/SplFileObject_fgetcsv_basic.phpt (93%) rename ext/spl/tests/{ => SplFileObject}/SplFileObject_key_error001.phpt (97%) rename ext/spl/tests/{ => SplFileObject}/SplFileObject_key_error002.phpt (97%) create mode 100644 ext/spl/tests/SplFileObject/fgetcsv_file_empty_lines.phpt create mode 100644 ext/spl/tests/SplFileObject/foreach_file_empty_lines.phpt create mode 100644 ext/spl/tests/SplFileObject/gh8563.phpt diff --git a/NEWS b/NEWS index 584fa704cf49e..5c9f640dadba1 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,9 @@ PHP NEWS . Fixed errorInfo() result on successful PDOStatement->execute(). (Yurunsoft) . Fixed handling of single-key connection strings. (Calvin Buckley) +- SPL: + . Fixed bug GH-8563 (Different results for seek() on SplFileObject and SplTempFileObject). (Girgias) + - Zip: . Fixed bug GH-8781 (ZipArchive::close deletes zip file without updating stat cache). (Remi) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 8646ba20b0e7f..0302e3c4ffb6a 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1883,22 +1883,21 @@ static zend_result spl_filesystem_file_read_ex(spl_filesystem_object *intern, bo } if (!buf) { - intern->u.file.current_line = estrdup(""); - intern->u.file.current_line_len = 0; - } else { - if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_DROP_NEW_LINE)) { - if (line_len > 0 && buf[line_len - 1] == '\n') { + return FAILURE; + } + + if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_DROP_NEW_LINE)) { + if (line_len > 0 && buf[line_len - 1] == '\n') { + line_len--; + if (line_len > 0 && buf[line_len - 1] == '\r') { line_len--; - if (line_len > 0 && buf[line_len - 1] == '\r') { - line_len--; - } - buf[line_len] = '\0'; } + buf[line_len] = '\0'; } - - intern->u.file.current_line = buf; - intern->u.file.current_line_len = line_len; } + + intern->u.file.current_line = buf; + intern->u.file.current_line_len = line_len; intern->u.file.current_line_num += line_add; return SUCCESS; diff --git a/ext/spl/tests/SplFileObject_fgetcsv_basic.phpt b/ext/spl/tests/SplFileObject/SplFileObject_fgetcsv_basic.phpt similarity index 93% rename from ext/spl/tests/SplFileObject_fgetcsv_basic.phpt rename to ext/spl/tests/SplFileObject/SplFileObject_fgetcsv_basic.phpt index 2580021426fd3..166a0d7fe0205 100644 --- a/ext/spl/tests/SplFileObject_fgetcsv_basic.phpt +++ b/ext/spl/tests/SplFileObject/SplFileObject_fgetcsv_basic.phpt @@ -13,6 +13,7 @@ fclose($fp); $fo = new SplFileObject('SplFileObject__fgetcsv1.csv'); var_dump($fo->fgetcsv()); +var_dump($fo->fgetcsv()); ?> --CLEAN-- string(1) "5" } +NULL diff --git a/ext/spl/tests/SplFileObject_key_error001.phpt b/ext/spl/tests/SplFileObject/SplFileObject_key_error001.phpt similarity index 97% rename from ext/spl/tests/SplFileObject_key_error001.phpt rename to ext/spl/tests/SplFileObject/SplFileObject_key_error001.phpt index 0c21d0b905e95..7d0e3ae8d9698 100644 --- a/ext/spl/tests/SplFileObject_key_error001.phpt +++ b/ext/spl/tests/SplFileObject/SplFileObject_key_error001.phpt @@ -18,5 +18,5 @@ var_dump($s->key()); var_dump($s->valid()); ?> --EXPECT-- -int(14) +int(12) bool(false) diff --git a/ext/spl/tests/SplFileObject_key_error002.phpt b/ext/spl/tests/SplFileObject/SplFileObject_key_error002.phpt similarity index 97% rename from ext/spl/tests/SplFileObject_key_error002.phpt rename to ext/spl/tests/SplFileObject/SplFileObject_key_error002.phpt index 8fc9b7fef0a58..0834dbc0524fc 100644 --- a/ext/spl/tests/SplFileObject_key_error002.phpt +++ b/ext/spl/tests/SplFileObject/SplFileObject_key_error002.phpt @@ -18,5 +18,5 @@ var_dump($s->key()); var_dump($s->valid()); ?> --EXPECT-- -int(13) +int(12) bool(false) diff --git a/ext/spl/tests/SplFileObject/fgetcsv_file_empty_lines.phpt b/ext/spl/tests/SplFileObject/fgetcsv_file_empty_lines.phpt new file mode 100644 index 0000000000000..464c98fc505b5 --- /dev/null +++ b/ext/spl/tests/SplFileObject/fgetcsv_file_empty_lines.phpt @@ -0,0 +1,38 @@ +--TEST-- +SplFileObject::fgetcsv with empty lines +--FILE-- +fwrite("foo,bar\n"); +$file->fwrite("\n"); +$file->fwrite("baz,qux"); + +$file->rewind(); + + +var_dump($file->fgetcsv()); +var_dump($file->fgetcsv()); +var_dump($file->fgetcsv()); +var_dump($file->fgetcsv()); + +?> +--EXPECT-- +array(2) { + [0]=> + string(3) "foo" + [1]=> + string(3) "bar" +} +array(1) { + [0]=> + NULL +} +array(2) { + [0]=> + string(3) "baz" + [1]=> + string(3) "qux" +} +NULL diff --git a/ext/spl/tests/SplFileObject/foreach_file_empty_lines.phpt b/ext/spl/tests/SplFileObject/foreach_file_empty_lines.phpt new file mode 100644 index 0000000000000..5fefdf0fddd5a --- /dev/null +++ b/ext/spl/tests/SplFileObject/foreach_file_empty_lines.phpt @@ -0,0 +1,37 @@ +--TEST-- +Iterate over SplFileObject with empty lines with CSV flags +--FILE-- +fwrite("foo,bar\n"); +$file->fwrite("\n"); +$file->fwrite("baz,qux"); + +$file->rewind(); + +$file->setFlags(SplFileObject::READ_CSV | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY /* | SplFileObject::DROP_NEW_LINE */); + + +foreach ($file as $line) { + var_dump($line); +} +?> +--EXPECT-- +array(2) { + [0]=> + string(3) "foo" + [1]=> + string(3) "bar" +} +array(1) { + [0]=> + NULL +} +array(2) { + [0]=> + string(3) "baz" + [1]=> + string(3) "qux" +} diff --git a/ext/spl/tests/SplFileObject/gh8563.phpt b/ext/spl/tests/SplFileObject/gh8563.phpt new file mode 100644 index 0000000000000..11309ae8101fa --- /dev/null +++ b/ext/spl/tests/SplFileObject/gh8563.phpt @@ -0,0 +1,48 @@ +--TEST-- +Bug GH-8563: Different results for seek() on SplFileObject and SplTempFileObject +--FILE-- +fwrite("line {$i}" . PHP_EOL); + $file_02->fwrite("line {$i}" . PHP_EOL); + $file_03->fwrite("line {$i}" . PHP_EOL); + $file_04->fwrite("line {$i}" . PHP_EOL); +} + +// reset +$file_01->rewind(); +$file_02->rewind(); +$file_03->rewind(); +$file_04->rewind(); + +// seek +$file_01->seek(INDEX); +$file_02->seek(INDEX); +$file_03->seek(INDEX); +$file_04->seek(INDEX); + +// show results +echo 'file_01: ' . $file_01->key(), PHP_EOL; +echo 'file_02: ' . $file_02->key(), PHP_EOL; +echo 'file_03: ' . $file_03->key(), PHP_EOL; +echo 'file_04: ' . $file_04->key(), PHP_EOL; +?> +--CLEAN-- + +--EXPECT-- +file_01: 4 +file_02: 4 +file_03: 4 +file_04: 4 diff --git a/ext/spl/tests/bug81477.phpt b/ext/spl/tests/bug81477.phpt index f7730a791aa03..421c74dc4d68e 100644 --- a/ext/spl/tests/bug81477.phpt +++ b/ext/spl/tests/bug81477.phpt @@ -21,7 +21,6 @@ string(8) "baz,bat " string(10) "more,data " -string(0) "" --CLEAN-- Date: Mon, 20 Jun 2022 13:07:28 +0100 Subject: [PATCH 038/440] intl ICU C++ code modernisation, making it closer to C++11 (#8650) --- .../codepointiterator_internal.h | 44 +++++++++---------- .../rulebasedbreakiterator_methods.cpp | 7 ++- ext/intl/calendar/calendar_methods.cpp | 10 ++--- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/ext/intl/breakiterator/codepointiterator_internal.h b/ext/intl/breakiterator/codepointiterator_internal.h index 93b903a20bb8a..8090bfbbd3cc3 100644 --- a/ext/intl/breakiterator/codepointiterator_internal.h +++ b/ext/intl/breakiterator/codepointiterator_internal.h @@ -35,51 +35,51 @@ namespace PHP { CodePointBreakIterator& operator=(const CodePointBreakIterator& that); - virtual ~CodePointBreakIterator(); + ~CodePointBreakIterator() override; #if U_ICU_VERSION_MAJOR_NUM >= 70 - virtual bool operator==(const BreakIterator& that) const; + bool operator==(const BreakIterator& that) const override; #else - virtual UBool operator==(const BreakIterator& that) const; + UBool operator==(const BreakIterator& that) const override; #endif - virtual CodePointBreakIterator* clone(void) const; + CodePointBreakIterator* clone(void) const override; - virtual UClassID getDynamicClassID(void) const; + UClassID getDynamicClassID(void) const override; - virtual CharacterIterator& getText(void) const; + CharacterIterator& getText(void) const override; - virtual UText *getUText(UText *fillIn, UErrorCode &status) const; + UText *getUText(UText *fillIn, UErrorCode &status) const override; - virtual void setText(const UnicodeString &text); + void setText(const UnicodeString &text) override; - virtual void setText(UText *text, UErrorCode &status); + void setText(UText *text, UErrorCode &status) override; - virtual void adoptText(CharacterIterator* it); + void adoptText(CharacterIterator* it) override; - virtual int32_t first(void); + int32_t first(void) override; - virtual int32_t last(void); + int32_t last(void) override; - virtual int32_t previous(void); + int32_t previous(void) override; - virtual int32_t next(void); + int32_t next(void) override; - virtual int32_t current(void) const; + int32_t current(void) const override; - virtual int32_t following(int32_t offset); + int32_t following(int32_t offset) override; - virtual int32_t preceding(int32_t offset); + int32_t preceding(int32_t offset) override; - virtual UBool isBoundary(int32_t offset); + UBool isBoundary(int32_t offset) override; - virtual int32_t next(int32_t n); + int32_t next(int32_t n) override; - virtual CodePointBreakIterator *createBufferClone(void *stackBuffer, + CodePointBreakIterator *createBufferClone(void *stackBuffer, int32_t &BufferSize, - UErrorCode &status); + UErrorCode &status) override; - virtual CodePointBreakIterator &refreshInputText(UText *input, UErrorCode &status); + CodePointBreakIterator &refreshInputText(UText *input, UErrorCode &status) override; inline UChar32 getLastCodePoint() { diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp index 2f5658a1e1a81..61e707e6c6deb 100644 --- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp +++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp @@ -13,6 +13,7 @@ */ #include +#include extern "C" { #define USE_BREAKITERATOR_POINTER 1 @@ -163,11 +164,10 @@ U_CFUNC PHP_METHOD(IntlRuleBasedBreakIterator, getRuleStatusVec) ZEND_ASSERT(BREAKITER_ERROR_CODE(bio) == U_BUFFER_OVERFLOW_ERROR); BREAKITER_ERROR_CODE(bio) = U_ZERO_ERROR; - int32_t *rules = new int32_t[num_rules]; - num_rules = fetch_rbbi(bio)->getRuleStatusVec(rules, num_rules, + std::unique_ptr rules = std::unique_ptr(new int32_t[num_rules]); + num_rules = fetch_rbbi(bio)->getRuleStatusVec(rules.get(), num_rules, BREAKITER_ERROR_CODE(bio)); if (U_FAILURE(BREAKITER_ERROR_CODE(bio))) { - delete[] rules; intl_errors_set(BREAKITER_ERROR_P(bio), BREAKITER_ERROR_CODE(bio), "rbbi_get_rule_status_vec: failed obtaining the status values", 0); @@ -178,7 +178,6 @@ U_CFUNC PHP_METHOD(IntlRuleBasedBreakIterator, getRuleStatusVec) for (int32_t i = 0; i < num_rules; i++) { add_next_index_long(return_value, rules[i]); } - delete[] rules; } U_CFUNC PHP_METHOD(IntlRuleBasedBreakIterator, getBinaryRules) diff --git a/ext/intl/calendar/calendar_methods.cpp b/ext/intl/calendar/calendar_methods.cpp index 4f1b52654bb57..52d1b2cb3037d 100644 --- a/ext/intl/calendar/calendar_methods.cpp +++ b/ext/intl/calendar/calendar_methods.cpp @@ -115,11 +115,11 @@ class BugStringCharEnumeration : public StringEnumeration uenum_close(uenum); } - int32_t count(UErrorCode& status) const { + int32_t count(UErrorCode& status) const override { return uenum_count(uenum, &status); } - virtual const UnicodeString* snext(UErrorCode& status) + const UnicodeString* snext(UErrorCode& status) override { int32_t length; const UChar* str = uenum_unext(uenum, &length, &status); @@ -129,7 +129,7 @@ class BugStringCharEnumeration : public StringEnumeration return &unistr.setTo(str, length); } - virtual const char* next(int32_t *resultLength, UErrorCode &status) + const char* next(int32_t *resultLength, UErrorCode &status) override { int32_t length = -1; const char* str = uenum_next(uenum, &length, &status); @@ -144,12 +144,12 @@ class BugStringCharEnumeration : public StringEnumeration return str; } - void reset(UErrorCode& status) + void reset(UErrorCode& status) override { uenum_reset(uenum, &status); } - virtual UClassID getDynamicClassID() const; + UClassID getDynamicClassID() const override; static UClassID U_EXPORT2 getStaticClassID(); From 5cf2659fa55cb6e692bd1fc350b808ef95bc47b4 Mon Sep 17 00:00:00 2001 From: Yurun Date: Mon, 20 Jun 2022 20:34:44 +0800 Subject: [PATCH 039/440] Replace the use of ZVAL_BOOL() with ZVAL_TRUE() or ZVAL_FALSE() where the value is fixed (#8815) --- build/gen_stub.php | 2 +- ext/dba/dba.c | 2 +- ext/dom/php_dom_arginfo.h | 2 +- ext/oci8/oci8_statement.c | 4 ++-- ext/soap/soap_arginfo.h | 8 ++++---- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 18763844280fa..e142a47e5bacc 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1649,7 +1649,7 @@ public function initializeZval(string $zvalName, iterable $allConstInfos): strin if ($this->type->isNull()) { $code .= "\tZVAL_NULL(&$zvalName);\n"; } elseif ($this->type->isBool()) { - $code .= "\tZVAL_BOOL(&$zvalName, " . ($cConstValue ?: ($this->value ? "true" : "false")) . ");\n"; + $code .= "\t" . ($this->value ? 'ZVAL_TRUE' : 'ZVAL_FALSE') . "(&$zvalName);\n"; } elseif ($this->type->isInt()) { $code .= "\tZVAL_LONG(&$zvalName, " . ($cConstValue ?: $this->value) . ");\n"; } elseif ($this->type->isFloat()) { diff --git a/ext/dba/dba.c b/ext/dba/dba.c index 842f85d73dcdb..c8dec94501542 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -1000,7 +1000,7 @@ PHP_FUNCTION(dba_key_split) } if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &zkey) == SUCCESS) { if (Z_TYPE_P(zkey) == IS_NULL || (Z_TYPE_P(zkey) == IS_FALSE)) { - RETURN_BOOL(0); + RETURN_FALSE; } } if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &key, &key_len) == FAILURE) { diff --git a/ext/dom/php_dom_arginfo.h b/ext/dom/php_dom_arginfo.h index 3842c59fea8da..f1af18e8f6050 100644 --- a/ext/dom/php_dom_arginfo.h +++ b/ext/dom/php_dom_arginfo.h @@ -1312,7 +1312,7 @@ static zend_class_entry *register_class_DOMAttr(zend_class_entry *class_entry_DO zend_string_release(property_name_name); zval property_specified_default_value; - ZVAL_BOOL(&property_specified_default_value, true); + ZVAL_TRUE(&property_specified_default_value); zend_string *property_specified_name = zend_string_init("specified", sizeof("specified") - 1, 1); zend_declare_typed_property(class_entry, property_specified_name, &property_specified_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property_specified_name); diff --git a/ext/oci8/oci8_statement.c b/ext/oci8/oci8_statement.c index ca7ef1c8cd50f..91bba23127b12 100644 --- a/ext/oci8/oci8_statement.c +++ b/ext/oci8/oci8_statement.c @@ -1105,9 +1105,9 @@ int php_oci_bind_post_exec(zval *data) } else if ((Z_TYPE_P(zv) == IS_TRUE) || (Z_TYPE_P(zv) == IS_FALSE)) { /* This convetrsion is done on purpose (ext/oci8 uses LVAL as a temporary value) */ if (Z_LVAL_P(zv) == 0) - ZVAL_BOOL(zv, FALSE); + ZVAL_FALSE(zv); else if (Z_LVAL_P(zv) == 1) - ZVAL_BOOL(zv, TRUE); + ZVAL_TRUE(zv); } return 0; diff --git a/ext/soap/soap_arginfo.h b/ext/soap/soap_arginfo.h index d5ebdcfeac1de..eed9247072cd5 100644 --- a/ext/soap/soap_arginfo.h +++ b/ext/soap/soap_arginfo.h @@ -442,7 +442,7 @@ static zend_class_entry *register_class_SoapClient(void) zend_string_release(property_location_name); zval property_trace_default_value; - ZVAL_BOOL(&property_trace_default_value, false); + ZVAL_FALSE(&property_trace_default_value); zend_string *property_trace_name = zend_string_init("trace", sizeof("trace") - 1, 1); zend_declare_typed_property(class_entry, property_trace_name, &property_trace_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property_trace_name); @@ -490,7 +490,7 @@ static zend_class_entry *register_class_SoapClient(void) zend_string_release(property__password_name); zval property__use_digest_default_value; - ZVAL_BOOL(&property__use_digest_default_value, false); + ZVAL_FALSE(&property__use_digest_default_value); zend_string *property__use_digest_name = zend_string_init("_use_digest", sizeof("_use_digest") - 1, 1); zend_declare_typed_property(class_entry, property__use_digest_name, &property__use_digest_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property__use_digest_name); @@ -526,7 +526,7 @@ static zend_class_entry *register_class_SoapClient(void) zend_string_release(property__proxy_password_name); zval property__exceptions_default_value; - ZVAL_BOOL(&property__exceptions_default_value, true); + ZVAL_TRUE(&property__exceptions_default_value); zend_string *property__exceptions_name = zend_string_init("_exceptions", sizeof("_exceptions") - 1, 1); zend_declare_typed_property(class_entry, property__exceptions_name, &property__exceptions_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property__exceptions_name); @@ -568,7 +568,7 @@ static zend_class_entry *register_class_SoapClient(void) zend_string_release(property__user_agent_name); zval property__keep_alive_default_value; - ZVAL_BOOL(&property__keep_alive_default_value, true); + ZVAL_TRUE(&property__keep_alive_default_value); zend_string *property__keep_alive_name = zend_string_init("_keep_alive", sizeof("_keep_alive") - 1, 1); zend_declare_typed_property(class_entry, property__keep_alive_name, &property__keep_alive_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property__keep_alive_name); From 6bd01751737690e2f9d2812356065012a34578c5 Mon Sep 17 00:00:00 2001 From: cmp Date: Mon, 20 Jun 2022 07:37:59 -0500 Subject: [PATCH 040/440] Prevent fclose on underlying SplFileObject file stream. (#7920) --- ext/spl/spl_directory.c | 3 +++ ext/spl/tests/bug81691.phpt | 15 +++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 ext/spl/tests/bug81691.phpt diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index d0fe202fdb638..4a5f5b132f22c 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -334,6 +334,9 @@ static zend_result spl_filesystem_file_open(spl_filesystem_object *intern, bool return FAILURE; } + /* prevent closing the stream outside of SplFileObject */ + intern->u.file.stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; + /* if (intern->u.file.zcontext) { //zend_list_addref(Z_RES_VAL(intern->u.file.zcontext)); diff --git a/ext/spl/tests/bug81691.phpt b/ext/spl/tests/bug81691.phpt new file mode 100644 index 0000000000000..597e37a9c8218 --- /dev/null +++ b/ext/spl/tests/bug81691.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #81691 fclose on SplFileObject stream +--FILE-- +fgets()); + +?> +--EXPECTF-- +Warning: fclose(): %d is not a valid stream resource in %s on line %d +string(6) " Date: Mon, 13 Jun 2022 17:32:02 +0200 Subject: [PATCH 041/440] Escape problematic characters in CREDITS files On Windows, the contents of the CREDITS files are passed to rc.exe via the command line. To avoid undesired behavior, we need to escape some characters, most notably `<` (which is sometimes used in CREDITS to enclose mail addresses), which otherwise is interpreted as redirection operator, resulting in the hard to understand "The system cannot find the file specified." Even more dangerous is not properly escaping percent signs, which makes it possible for a malicious CREDITS file to inject the values of environment variables of the build system into the generated binaries. This is particularly bad, because as of Windows Vista, the comments can no longer be inspected via explorer.exe, although the binaries still contain these comments. We also cater to double-quotes, which need to be escaped as `\"\"` in this context. Closes GH-8767. --- win32/build/confutils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win32/build/confutils.js b/win32/build/confutils.js index 6dbc6a86ba225..c7489924554cb 100644 --- a/win32/build/confutils.js +++ b/win32/build/confutils.js @@ -1093,7 +1093,7 @@ function generate_version_info_resource(makefiletarget, basename, creditspath, s if (thanks == null) { thanks = ""; } else { - thanks = "Thanks to " + thanks; + thanks = "Thanks to " + thanks.replace(/([<>&|%])/g, "^$1").replace(/"/g, '\\"\\"'); } credits.Close(); } From bfe6f9e66a65d7c40fd486249097f932e2b237c3 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 20 Sep 2019 16:42:47 +0100 Subject: [PATCH 042/440] Introduction of timing attack safe bcmp implementation. Nothing new but to refactor usage b/w hash and password extensions but using volatile pointers to be a bit safer, allowing to expand its usage eventually. --- configure.ac | 2 +- ext/hash/hash.c | 13 +------------ ext/standard/password.c | 7 ++----- main/php.h | 4 ++++ main/safe_bcmp.c | 43 +++++++++++++++++++++++++++++++++++++++++ win32/build/config.w32 | 2 +- 6 files changed, 52 insertions(+), 19 deletions(-) create mode 100644 main/safe_bcmp.c diff --git a/configure.ac b/configure.ac index 73c7edeae3db1..2dfb06dd023e0 100644 --- a/configure.ac +++ b/configure.ac @@ -1616,7 +1616,7 @@ PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c \ php_ini_builder.c \ php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ strlcat.c explicit_bzero.c reentrancy.c php_variables.c php_ticks.c \ - network.c php_open_temporary_file.c php_odbc_utils.c \ + network.c php_open_temporary_file.c php_odbc_utils.c safe_bcmp.c \ output.c getopt.c php_syslog.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_ADD_SOURCES_X(main, fastcgi.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, PHP_FASTCGI_OBJS, no) diff --git a/ext/hash/hash.c b/ext/hash/hash.c index c8b93313d594c..ce665a57443f1 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -1111,9 +1111,7 @@ PHP_FUNCTION(hash_pbkdf2) PHP_FUNCTION(hash_equals) { zval *known_zval, *user_zval; - char *known_str, *user_str; int result = 0; - size_t j; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &known_zval, &user_zval) == FAILURE) { RETURN_THROWS(); @@ -1130,17 +1128,8 @@ PHP_FUNCTION(hash_equals) RETURN_THROWS(); } - if (Z_STRLEN_P(known_zval) != Z_STRLEN_P(user_zval)) { - RETURN_FALSE; - } - - known_str = Z_STRVAL_P(known_zval); - user_str = Z_STRVAL_P(user_zval); - /* This is security sensitive code. Do not optimize this for speed. */ - for (j = 0; j < Z_STRLEN_P(known_zval); j++) { - result |= known_str[j] ^ user_str[j]; - } + result = php_safe_bcmp(Z_STR_P(known_zval), Z_STR_P(user_zval)); RETURN_BOOL(0 == result); } diff --git a/ext/standard/password.c b/ext/standard/password.c index 96b74aa39554f..374b026562842 100644 --- a/ext/standard/password.c +++ b/ext/standard/password.c @@ -152,7 +152,6 @@ static bool php_password_bcrypt_needs_rehash(const zend_string *hash, zend_array } static bool php_password_bcrypt_verify(const zend_string *password, const zend_string *hash) { - size_t i; int status = 0; zend_string *ret = php_crypt(ZSTR_VAL(password), (int)ZSTR_LEN(password), ZSTR_VAL(hash), (int)ZSTR_LEN(hash), 1); @@ -160,7 +159,7 @@ static bool php_password_bcrypt_verify(const zend_string *password, const zend_s return 0; } - if (ZSTR_LEN(ret) != ZSTR_LEN(hash) || ZSTR_LEN(hash) < 13) { + if (ZSTR_LEN(hash) < 13) { zend_string_free(ret); return 0; } @@ -169,9 +168,7 @@ static bool php_password_bcrypt_verify(const zend_string *password, const zend_s * resistance towards timing attacks. This is a constant time * equality check that will always check every byte of both * values. */ - for (i = 0; i < ZSTR_LEN(hash); i++) { - status |= (ZSTR_VAL(ret)[i] ^ ZSTR_VAL(hash)[i]); - } + status = php_safe_bcmp(ret, hash); zend_string_free(ret); return status == 0; diff --git a/main/php.h b/main/php.h index c8ef2d058189f..9009ba032d3bd 100644 --- a/main/php.h +++ b/main/php.h @@ -179,6 +179,10 @@ END_EXTERN_C() #define explicit_bzero php_explicit_bzero #endif +BEGIN_EXTERN_C() +PHPAPI int php_safe_bcmp(const zend_string *a, const zend_string *b); +END_EXTERN_C() + #ifndef HAVE_STRTOK_R BEGIN_EXTERN_C() char *strtok_r(char *s, const char *delim, char **last); diff --git a/main/safe_bcmp.c b/main/safe_bcmp.c new file mode 100644 index 0000000000000..27a1756d79b46 --- /dev/null +++ b/main/safe_bcmp.c @@ -0,0 +1,43 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: David Carlier | + +----------------------------------------------------------------------+ +*/ + +#include "php.h" + +#include + +/* + * Returns 0 if both inputs match, 1 if they don't. + * Returns -1 early if inputs do not have the same lengths. + * + */ +PHPAPI int php_safe_bcmp(const zend_string *a, const zend_string *b) +{ + const volatile unsigned char *ua = (const volatile unsigned char *)ZSTR_VAL(a); + const volatile unsigned char *ub = (const volatile unsigned char *)ZSTR_VAL(b); + size_t i = 0; + int r = 0; + + if (ZSTR_LEN(a) != ZSTR_LEN(b)) { + return -1; + } + + while (i < ZSTR_LEN(a)) { + r |= ua[i] ^ ub[i]; + ++i; + } + + return r; +} diff --git a/win32/build/config.w32 b/win32/build/config.w32 index c174ebe85411c..c66f1e39af6a6 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -265,7 +265,7 @@ ADD_SOURCES("main", "main.c snprintf.c spprintf.c getopt.c fopen_wrappers.c \ php_scandir.c php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ strlcat.c reentrancy.c php_variables.c php_ticks.c network.c \ php_open_temporary_file.c output.c internal_functions.c \ - php_syslog.c php_odbc_utils.c"); + php_syslog.c php_odbc_utils.c safe_bcmp.c"); ADD_FLAG("CFLAGS_BD_MAIN", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); if (VS_TOOLSET && VCVERS >= 1914) { ADD_FLAG("CFLAGS_BD_MAIN", "/d2FuncCache1"); From a8437d08a8a7122af17532e21c7ac3e02838809a Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 20 Jun 2022 17:59:49 +0200 Subject: [PATCH 043/440] Fix GH-8827: Intentionally closing std handles no longer possible We revert the commits which caused this regression from the PHP-8.0 and PHP-8.1 branches for now. We keep it in "master" because of PR #8833 which may offer a proper fix without BC break. --- NEWS | 3 +++ ext/zend_test/test.c | 6 ------ ext/zend_test/tests/gh8575.phpt | 14 -------------- sapi/cli/php_cli.c | 14 ++++++-------- 4 files changed, 9 insertions(+), 28 deletions(-) delete mode 100644 ext/zend_test/tests/gh8575.phpt diff --git a/NEWS b/NEWS index 5c9f640dadba1..b55ee0cefd341 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ PHP NEWS - Core: . Fixed potential use after free in php_binary_init(). (Heiko Weber) +- CLI: + . Fixed GH-8827 (Intentionally closing std handles no longer possible). (cmb) + - COM: . Fixed bug GH-8778 (Integer arithmethic with large number variants fails). (cmb) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index f4004a505b772..69578e0ad1a55 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -42,7 +42,6 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test) int observer_show_opcode; int observer_nesting_depth; int replace_zend_execute_ex; - zend_bool print_stderr_mshutdown; HashTable global_weakmap; ZEND_END_MODULE_GLOBALS(zend_test) @@ -408,7 +407,6 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zend_test.observer.show_init_backtrace", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_init_backtrace, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.observer.show_opcode", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_opcode, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals) - STD_PHP_INI_BOOLEAN("zend_test.print_stderr_mshutdown", "0", PHP_INI_SYSTEM, OnUpdateBool, print_stderr_mshutdown, zend_zend_test_globals, zend_test_globals) PHP_INI_END() static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execute_data); @@ -528,10 +526,6 @@ PHP_MSHUTDOWN_FUNCTION(zend_test) UNREGISTER_INI_ENTRIES(); } - if (ZT_G(print_stderr_mshutdown)) { - fprintf(stderr, "[zend-test] MSHUTDOWN\n"); - } - return SUCCESS; } diff --git a/ext/zend_test/tests/gh8575.phpt b/ext/zend_test/tests/gh8575.phpt deleted file mode 100644 index 8cf1d68dcab39..0000000000000 --- a/ext/zend_test/tests/gh8575.phpt +++ /dev/null @@ -1,14 +0,0 @@ ---TEST-- -CLI: stderr is available in mshutdown ---SKIPIF-- - ---INI-- -zend_test.print_stderr_mshutdown=1 ---FILE-- -==DONE== ---EXPECTF-- -==DONE== -[zend-test] MSHUTDOWN diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 545ac19e84d3d..62bc619db63d1 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -539,14 +539,6 @@ static void cli_register_file_handles(void) /* {{{ */ s_out = php_stream_open_wrapper_ex("php://stdout", "wb", 0, NULL, sc_out); s_err = php_stream_open_wrapper_ex("php://stderr", "wb", 0, NULL, sc_err); - /* Release stream resources, but don't free the underlying handles. Othewrise, - * extensions which write to stderr or company during mshutdown/gshutdown - * won't have the expected functionality. - */ - if (s_in) s_in->flags |= PHP_STREAM_FLAG_NO_CLOSE; - if (s_out) s_out->flags |= PHP_STREAM_FLAG_NO_CLOSE; - if (s_err) s_err->flags |= PHP_STREAM_FLAG_NO_CLOSE; - if (s_in==NULL || s_out==NULL || s_err==NULL) { if (s_in) php_stream_close(s_in); if (s_out) php_stream_close(s_out); @@ -554,6 +546,12 @@ static void cli_register_file_handles(void) /* {{{ */ return; } +#if PHP_DEBUG + /* do not close stdout and stderr */ + s_out->flags |= PHP_STREAM_FLAG_NO_CLOSE; + s_err->flags |= PHP_STREAM_FLAG_NO_CLOSE; +#endif + s_in_process = s_in; php_stream_to_zval(s_in, &ic.value); From a493c94471bcfe9a37c79bc02b40cffe0b62c463 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 27 May 2022 10:26:15 +0100 Subject: [PATCH 044/440] Use bool for silent parameter in SPL directory.c --- ext/spl/spl_directory.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 4a5f5b132f22c..c5c651382b5dc 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1944,7 +1944,7 @@ static zend_result spl_filesystem_file_read_csv(spl_filesystem_object *intern, c } /* }}} */ -static zend_result spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_object *intern, int silent) /* {{{ */ +static zend_result spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_object *intern, bool silent) /* {{{ */ { zval retval; @@ -2026,7 +2026,7 @@ static bool spl_filesystem_file_is_empty_line(spl_filesystem_object *intern) /* } /* }}} */ -static zend_result spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, int silent) /* {{{ */ +static zend_result spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, bool silent) /* {{{ */ { zend_result ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent); @@ -2052,7 +2052,7 @@ static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *i intern->u.file.current_line_num = 0; } if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) { - spl_filesystem_file_read_line(this_ptr, intern, 1); + spl_filesystem_file_read_line(this_ptr, intern, /* silent */ true); } } /* }}} */ @@ -2206,7 +2206,7 @@ PHP_METHOD(SplFileObject, current) CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) { - spl_filesystem_file_read_line(ZEND_THIS, intern, 1); + spl_filesystem_file_read_line(ZEND_THIS, intern, /* silent */ true); } if (intern->u.file.current_line && (!SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || Z_ISUNDEF(intern->u.file.current_zval))) { RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len); @@ -2228,7 +2228,7 @@ PHP_METHOD(SplFileObject, key) /* Do not read the next line to support correct counting with fgetc() if (!intern->u.file.current_line) { - spl_filesystem_file_read_line(ZEND_THIS, intern, 1); + spl_filesystem_file_read_line(ZEND_THIS, intern, silent true); } */ RETURN_LONG(intern->u.file.current_line_num); } /* }}} */ @@ -2244,7 +2244,7 @@ PHP_METHOD(SplFileObject, next) spl_filesystem_file_free_line(intern); if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) { - spl_filesystem_file_read_line(ZEND_THIS, intern, 1); + spl_filesystem_file_read_line(ZEND_THIS, intern, /* silent */ true); } intern->u.file.current_line_num++; } /* }}} */ @@ -2743,7 +2743,7 @@ PHP_METHOD(SplFileObject, seek) spl_filesystem_file_rewind(ZEND_THIS, intern); for (i = 0; i < line_pos; i++) { - if (spl_filesystem_file_read_line(ZEND_THIS, intern, 1) == FAILURE) { + if (spl_filesystem_file_read_line(ZEND_THIS, intern, /* silent */ true) == FAILURE) { return; } } From d5d0b07b4e7f57cc1c074caf8bb8229c2f489f06 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 20 Jun 2022 17:26:40 +0100 Subject: [PATCH 045/440] Early return in spl_filesystem_file_rewind() --- ext/spl/spl_directory.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index c5c651382b5dc..cc1a660823330 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -2047,10 +2047,12 @@ static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *i } if (-1 == php_stream_rewind(intern->u.file.stream)) { zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot rewind file %s", ZSTR_VAL(intern->file_name)); - } else { - spl_filesystem_file_free_line(intern); - intern->u.file.current_line_num = 0; + return; } + + spl_filesystem_file_free_line(intern); + intern->u.file.current_line_num = 0; + if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) { spl_filesystem_file_read_line(this_ptr, intern, /* silent */ true); } From 84e4d2a0e88d9e99ba42d33926f82f37694a8421 Mon Sep 17 00:00:00 2001 From: Heiko Weber Date: Mon, 20 Jun 2022 18:32:13 +0200 Subject: [PATCH 046/440] Refactor sapi_getenv() (#8786) --- main/SAPI.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/main/SAPI.c b/main/SAPI.c index d1bd3134b6dee..70ed6a2b9c835 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -1007,29 +1007,30 @@ SAPI_API zend_stat_t *sapi_get_stat(void) SAPI_API char *sapi_getenv(const char *name, size_t name_len) { + char *value, *tmp; + + if (!sapi_module.getenv) { + return NULL; + } if (!strncasecmp(name, "HTTP_PROXY", name_len)) { /* Ugly fix for HTTP_PROXY issue, see bug #72573 */ return NULL; } - if (sapi_module.getenv) { - char *value, *tmp = sapi_module.getenv(name, name_len); - if (tmp) { - value = estrdup(tmp); + tmp = sapi_module.getenv(name, name_len); + if (!tmp) { + return NULL; + } + value = estrdup(tmp); #ifdef PHP_WIN32 - if (strlen(sapi_module.name) == sizeof("cgi-fcgi") - 1 && !strcmp(sapi_module.name, "cgi-fcgi")) { - /* XXX more modules to go, if needed. */ - free(tmp); - } + if (strlen(sapi_module.name) == sizeof("cgi-fcgi") - 1 && !strcmp(sapi_module.name, "cgi-fcgi")) { + /* XXX more modules to go, if needed. */ + free(tmp); + } #endif - } else { - return NULL; - } - if (sapi_module.input_filter) { - sapi_module.input_filter(PARSE_STRING, name, &value, strlen(value), NULL); - } - return value; + if (sapi_module.input_filter) { + sapi_module.input_filter(PARSE_STRING, name, &value, strlen(value), NULL); } - return NULL; + return value; } SAPI_API int sapi_get_fd(int *fd) From 7e8ad578ab374f81cbf53090b12d744eb759ecf0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 20 Jun 2022 18:43:16 +0200 Subject: [PATCH 047/440] Fix bad merge (b8dee9b3fc0f8f6371313cc54c642a5c9fc8bcd9) --- ext/zend_test/test.c | 5 ----- ext/zend_test/tests/gh8575.phpt | 14 -------------- 2 files changed, 19 deletions(-) delete mode 100644 ext/zend_test/tests/gh8575.phpt diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 617d81fa25d6a..6c5bc119ab31b 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -480,7 +480,6 @@ static ZEND_METHOD(ZendTestChildClassWithMethodWithParameterAttribute, override) PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals) - STD_PHP_INI_BOOLEAN("zend_test.print_stderr_mshutdown", "0", PHP_INI_SYSTEM, OnUpdateBool, print_stderr_mshutdown, zend_zend_test_globals, zend_test_globals) PHP_INI_END() void (*old_zend_execute_ex)(zend_execute_data *execute_data); @@ -606,10 +605,6 @@ PHP_MSHUTDOWN_FUNCTION(zend_test) zend_test_observer_shutdown(SHUTDOWN_FUNC_ARGS_PASSTHRU); - if (ZT_G(print_stderr_mshutdown)) { - fprintf(stderr, "[zend-test] MSHUTDOWN\n"); - } - return SUCCESS; } diff --git a/ext/zend_test/tests/gh8575.phpt b/ext/zend_test/tests/gh8575.phpt deleted file mode 100644 index 8cf1d68dcab39..0000000000000 --- a/ext/zend_test/tests/gh8575.phpt +++ /dev/null @@ -1,14 +0,0 @@ ---TEST-- -CLI: stderr is available in mshutdown ---SKIPIF-- - ---INI-- -zend_test.print_stderr_mshutdown=1 ---FILE-- -==DONE== ---EXPECTF-- -==DONE== -[zend-test] MSHUTDOWN From ff472ce6fc462bfeb6d88a651eec3779c0923dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 21 Jun 2022 09:28:57 +0200 Subject: [PATCH 048/440] Support the `#[\AllowDynamicProperties]` attribute in stubs (#8776) * Support the `#[\AllowDynamicProperties]` attribute in stubs * Use `#[\AllowDynamicProperties]` attribute in stubs * Disallow applying both `@strict-properties` and `#[\AllowDynamicProperties]` --- Zend/zend_builtin_functions.c | 2 -- Zend/zend_builtin_functions.stub.php | 1 + Zend/zend_builtin_functions_arginfo.h | 4 +++- build/gen_stub.php | 30 +++++++++++++++++++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 963332e0f7ed8..8813fa9788a97 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -38,8 +38,6 @@ ZEND_MINIT_FUNCTION(core) { /* {{{ */ zend_register_default_classes(); zend_standard_class_def = register_class_stdClass(); - zend_add_class_attribute(zend_standard_class_def, zend_ce_allow_dynamic_properties->name, 0); - zend_standard_class_def->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; return SUCCESS; } diff --git a/Zend/zend_builtin_functions.stub.php b/Zend/zend_builtin_functions.stub.php index bf6b8242c5a81..ca04719742c54 100644 --- a/Zend/zend_builtin_functions.stub.php +++ b/Zend/zend_builtin_functions.stub.php @@ -2,6 +2,7 @@ /** @generate-class-entries */ +#[\AllowDynamicProperties] class stdClass { } diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h index c4bfc3c48b036..1dbc4255945a6 100644 --- a/Zend/zend_builtin_functions_arginfo.h +++ b/Zend/zend_builtin_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 33a976db268b72cee985011198125f652bc6c86d */ + * Stub hash: 80355bb52d643177e3a661a515d9ea915bd1e2fc */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_version, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -353,6 +353,8 @@ static zend_class_entry *register_class_stdClass(void) INIT_CLASS_ENTRY(ce, "stdClass", class_stdClass_methods); class_entry = zend_register_internal_class_ex(&ce, NULL); + class_entry->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; + zend_add_class_attribute(class_entry, zend_ce_allow_dynamic_properties->name, 0); return class_entry; } diff --git a/build/gen_stub.php b/build/gen_stub.php index e142a47e5bacc..202ab1fdc6ed4 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2273,6 +2273,8 @@ class ClassInfo { /** @var bool */ public $isStrictProperties; /** @var bool */ + public $allowsDynamicProperties; + /** @var bool */ public $isNotSerializable; /** @var Name[] */ public $extends; @@ -2305,6 +2307,7 @@ public function __construct( ?SimpleType $enumBackingType, bool $isDeprecated, bool $isStrictProperties, + bool $allowsDynamicProperties, bool $isNotSerializable, array $extends, array $implements, @@ -2321,6 +2324,7 @@ public function __construct( $this->enumBackingType = $enumBackingType; $this->isDeprecated = $isDeprecated; $this->isStrictProperties = $isStrictProperties; + $this->allowsDynamicProperties = $allowsDynamicProperties; $this->isNotSerializable = $isNotSerializable; $this->extends = $extends; $this->implements = $implements; @@ -2409,6 +2413,10 @@ function (Name $item) { $code .= $property->getDeclaration($allConstInfos); } + if ($this->allowsDynamicProperties) { + $code .= "\tzend_add_class_attribute(class_entry, zend_ce_allow_dynamic_properties->name, 0);\n"; + } + if ($attributeInitializationCode = generateAttributeInitialization($this->funcInfos, $this->cond)) { $code .= "\n" . $attributeInitializationCode; } @@ -2452,6 +2460,10 @@ private function getFlagsAsString(): string $flags[] = "ZEND_ACC_NO_DYNAMIC_PROPERTIES"; } + if ($this->allowsDynamicProperties) { + $flags[] = "ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES"; + } + if ($this->isNotSerializable) { $flags[] = "ZEND_ACC_NOT_SERIALIZABLE"; } @@ -3273,6 +3285,7 @@ function parseClass( $isDeprecated = false; $isStrictProperties = false; $isNotSerializable = false; + $allowsDynamicProperties = false; if ($comment) { $tags = parseDocComment($comment); @@ -3289,6 +3302,22 @@ function parseClass( } } + foreach ($class->attrGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attr) { + switch ($attr->name->toCodeString()) { + case '\\AllowDynamicProperties': + $allowsDynamicProperties = true; + break; + default: + throw new Exception("Unhandled attribute {$attr->name->toCodeString()}."); + } + } + } + + if ($isStrictProperties && $allowsDynamicProperties) { + throw new Exception("A class may not have '@strict-properties' and '#[\\AllowDynamicProperties]' at the same time."); + } + $extends = []; $implements = []; @@ -3319,6 +3348,7 @@ function parseClass( ? SimpleType::fromNode($class->scalarType) : null, $isDeprecated, $isStrictProperties, + $allowsDynamicProperties, $isNotSerializable, $extends, $implements, From fcd69a4e2bf88645b926bf84b9cb9325a6e13e50 Mon Sep 17 00:00:00 2001 From: Gabriel Caruso Date: Tue, 21 Jun 2022 11:33:20 +0200 Subject: [PATCH 049/440] Prepare for 8.0.22 --- NEWS | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index b55ee0cefd341..c25a387d4fbf8 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? 2022, PHP 8.0.21 +?? ??? 2022, PHP 8.0.22 + + +07 Jul 2022, PHP 8.0.21 - Core: . Fixed potential use after free in php_binary_init(). (Heiko Weber) From a1b05a3a409100068d1ed41e38aacbd68b3a7299 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 20 Jun 2022 12:50:51 +0200 Subject: [PATCH 050/440] Tweak $count range check of array_fill() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We fix the `UNEXPECTED(EXPECTED(…))`, which does not make sense, and replace the magic number with the respective macro. We also add a test case to verify the expected behavior for an `array_fill()` edge case. Closes GH-8804. --- ext/standard/array.c | 2 +- .../tests/array/array_fill_variation6.phpt | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/array/array_fill_variation6.phpt diff --git a/ext/standard/array.c b/ext/standard/array.c index a3ce0d6c80cf7..2514beee62bde 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2598,7 +2598,7 @@ PHP_FUNCTION(array_fill) ZEND_PARSE_PARAMETERS_END(); if (EXPECTED(num > 0)) { - if (sizeof(num) > 4 && UNEXPECTED(EXPECTED(num > 0x7fffffff))) { + if (sizeof(num) > 4 && UNEXPECTED(num >INT_MAX)) { zend_argument_value_error(2, "is too large"); RETURN_THROWS(); } else if (UNEXPECTED(start_key > ZEND_LONG_MAX - num + 1)) { diff --git a/ext/standard/tests/array/array_fill_variation6.phpt b/ext/standard/tests/array/array_fill_variation6.phpt new file mode 100644 index 0000000000000..60dcec7e231ea --- /dev/null +++ b/ext/standard/tests/array/array_fill_variation6.phpt @@ -0,0 +1,19 @@ +--TEST-- +array_fill(): last element +--FILE-- +getMessage(), PHP_EOL; +} +?> +--EXPECT-- +int(1) +bool(true) +Cannot add element to the array as the next element is already occupied From cd363a9b1b281496b747781c3cba5d8422a94e8d Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 21 Jun 2022 13:37:38 +0200 Subject: [PATCH 051/440] Specify unit in out of memory error (#8820) Closes GH-8808 --- Zend/zend_alloc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index f25b10360e59a..c7895a6624c60 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -992,9 +992,9 @@ static void *zend_mm_alloc_pages(zend_mm_heap *heap, uint32_t pages_count ZEND_F #if !ZEND_MM_LIMIT zend_mm_safe_error(heap, "Out of memory"); #elif ZEND_DEBUG - zend_mm_safe_error(heap, "Out of memory (allocated %zu) at %s:%d (tried to allocate %zu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); + zend_mm_safe_error(heap, "Out of memory (allocated %zu bytes) at %s:%d (tried to allocate %zu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); #else - zend_mm_safe_error(heap, "Out of memory (allocated %zu) (tried to allocate %zu bytes)", heap->real_size, ZEND_MM_PAGE_SIZE * pages_count); + zend_mm_safe_error(heap, "Out of memory (allocated %zu bytes) (tried to allocate %zu bytes)", heap->real_size, ZEND_MM_PAGE_SIZE * pages_count); #endif return NULL; } @@ -1810,9 +1810,9 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D #if !ZEND_MM_LIMIT zend_mm_safe_error(heap, "Out of memory"); #elif ZEND_DEBUG - zend_mm_safe_error(heap, "Out of memory (allocated %zu) at %s:%d (tried to allocate %zu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); + zend_mm_safe_error(heap, "Out of memory (allocated %zu bytes) at %s:%d (tried to allocate %zu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); #else - zend_mm_safe_error(heap, "Out of memory (allocated %zu) (tried to allocate %zu bytes)", heap->real_size, size); + zend_mm_safe_error(heap, "Out of memory (allocated %zu bytes) (tried to allocate %zu bytes)", heap->real_size, size); #endif return NULL; } From 1a3d836fa1e4488387bc3149b98a08ff34df5a42 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 21 Jun 2022 13:42:52 +0200 Subject: [PATCH 052/440] Fix CS (missing space) --- ext/standard/array.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 2514beee62bde..d9cbc3b3e253b 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2598,7 +2598,7 @@ PHP_FUNCTION(array_fill) ZEND_PARSE_PARAMETERS_END(); if (EXPECTED(num > 0)) { - if (sizeof(num) > 4 && UNEXPECTED(num >INT_MAX)) { + if (sizeof(num) > 4 && UNEXPECTED(num > INT_MAX)) { zend_argument_value_error(2, "is too large"); RETURN_THROWS(); } else if (UNEXPECTED(start_key > ZEND_LONG_MAX - num + 1)) { From 804c7080235ceba1f9a62dac15f361b6bbeabc28 Mon Sep 17 00:00:00 2001 From: jcm Date: Tue, 21 Jun 2022 12:36:03 +0200 Subject: [PATCH 053/440] Add test for iconv_strpos() internal encoding error Co-authored-by: Christoph M. Becker Closes GH-8816. --- ext/iconv/tests/iconv_strpos_error_001.phpt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 ext/iconv/tests/iconv_strpos_error_001.phpt diff --git a/ext/iconv/tests/iconv_strpos_error_001.phpt b/ext/iconv/tests/iconv_strpos_error_001.phpt new file mode 100644 index 0000000000000..3387cfd024189 --- /dev/null +++ b/ext/iconv/tests/iconv_strpos_error_001.phpt @@ -0,0 +1,13 @@ +--TEST-- +iconv_strpos() - test against PHP's default internal encoding +--EXTENSIONS-- +iconv +--FILE-- + +--EXPECTF-- +%AWarning: iconv_strpos(): Wrong encoding, conversion from %s +bool(false) From 280b3db054ab68a0185d4978b5044368fc14e87b Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 21 Jun 2022 15:19:23 +0100 Subject: [PATCH 054/440] Use same type error wording for alias iterable in ZPP (#8838) Follow-up from #7309 as I didn't change the ZPP TypeError wording. --- Zend/tests/iterable_or_null.phpt | 8 ++++---- Zend/zend_API.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Zend/tests/iterable_or_null.phpt b/Zend/tests/iterable_or_null.phpt index 3585e449caee2..a44e858bce92e 100644 --- a/Zend/tests/iterable_or_null.phpt +++ b/Zend/tests/iterable_or_null.phpt @@ -40,8 +40,8 @@ try { ?> --EXPECT-- -zend_iterable(): Argument #1 ($arg1) must be of type iterable, string given -zend_iterable(): Argument #1 ($arg1) must be of type iterable, int given -zend_iterable(): Argument #1 ($arg1) must be of type iterable, null given -zend_iterable(): Argument #2 ($arg2) must be of type ?iterable, string given +zend_iterable(): Argument #1 ($arg1) must be of type Traversable|array, string given +zend_iterable(): Argument #1 ($arg1) must be of type Traversable|array, int given +zend_iterable(): Argument #1 ($arg1) must be of type Traversable|array, null given +zend_iterable(): Argument #2 ($arg2) must be of type Traversable|array|null, string given diff --git a/Zend/zend_API.h b/Zend/zend_API.h index b21228840c0ce..2dbd9bd15d090 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -1319,8 +1319,8 @@ static zend_always_inline zval *zend_try_array_init(zval *zv) _(Z_EXPECTED_ARRAY_OR_NULL, "of type ?array") \ _(Z_EXPECTED_ARRAY_OR_LONG, "of type array|int") \ _(Z_EXPECTED_ARRAY_OR_LONG_OR_NULL, "of type array|int|null") \ - _(Z_EXPECTED_ITERABLE, "of type iterable") \ - _(Z_EXPECTED_ITERABLE_OR_NULL, "of type ?iterable") \ + _(Z_EXPECTED_ITERABLE, "of type Traversable|array") \ + _(Z_EXPECTED_ITERABLE_OR_NULL, "of type Traversable|array|null") \ _(Z_EXPECTED_FUNC, "a valid callback") \ _(Z_EXPECTED_FUNC_OR_NULL, "a valid callback or null") \ _(Z_EXPECTED_RESOURCE, "of type resource") \ From dc322821a4521a41a900cf60274c31d1fa6ca8b3 Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Tue, 21 Jun 2022 11:22:34 -0400 Subject: [PATCH 055/440] Update NEWS for PHP 8.2.0 alpha3 --- NEWS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 70e494dc06e51..b0fd93fb213f6 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.0alpha2 +?? ??? ????, PHP 8.2.0alpha3 + +23 Jun 2022, PHP 8.2.0alpha2 - Core: . Fixed bug GH-8655 (Casting an object to array does not unwrap refcount=1 From f3b45e74f5dd00e2bb173a13b21d6e83770e2d1e Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 21 Jun 2022 11:03:50 -0500 Subject: [PATCH 056/440] PHP-8.1 is now for PHP 8.1.9-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 e54603c47ab73..84e9be6b44356 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.8 +?? ??? ????, PHP 8.1.9 + + + +07 Jul 2022, PHP 8.1.8 - Core: . Fixed bug GH-8338 (Intel CET is disabled unintentionally). (Chen, Hu) diff --git a/Zend/zend.h b/Zend/zend.h index 902d340427a03..0651ce80dd31a 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.8-dev" +#define ZEND_VERSION "4.1.9-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index b95e3232aef0d..0b7cc577e0b75 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.1.8-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.9-dev],[https://bugs.php.net],[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 43d5eb5b19321..74b4efee14ed0 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 1 -#define PHP_RELEASE_VERSION 8 +#define PHP_RELEASE_VERSION 9 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.8-dev" -#define PHP_VERSION_ID 80108 +#define PHP_VERSION "8.1.9-dev" +#define PHP_VERSION_ID 80109 From c8f9555a058aaacc798829039fd1c9ebf8f807e9 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 21 Jun 2022 11:26:23 -0500 Subject: [PATCH 057/440] [ci skip] fix gen_verify_stub example command --- docs/release-process.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/release-process.md b/docs/release-process.md index d55e881e9daa2..6821ab87962d0 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -296,7 +296,7 @@ slightly different steps. We'll call attention where the steps differ. upload to GitHub and include in the announcement emails. ```shell - ./scripts/dev/gen_verify_stub php-X.Y.ZRCn YOURKEYID > php-X.Y.ZRCn.manifest + ./scripts/dev/gen_verify_stub X.Y.ZRCn YOURKEYID > php-X.Y.ZRCn.manifest ``` 13. If you have the [GitHub command line tool][] installed, run the following to @@ -569,7 +569,7 @@ slightly different steps. We'll call attention where the steps differ. upload to GitHub and include in the announcement emails. ```shell - ./scripts/dev/gen_verify_stub php-X.Y.Z YOURKEYID > php-X.Y.Z.manifest + ./scripts/dev/gen_verify_stub X.Y.Z YOURKEYID > php-X.Y.Z.manifest ``` 12. If you have the [GitHub command line tool][] installed, run the following to From 6b6e5f3748078c6d2a5f72d9080744d6694f4d7e Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Tue, 21 Jun 2022 17:52:25 -0400 Subject: [PATCH 058/440] Add AllowDynamicProperties on OCILob and OCICollection Fix GH-8756 : oci_new_descriptor() triggers dynamic property deprecation. This fix should be temporary. At some point we should either define those properties or just hide them since they should probably not be used. Better fix is here : https://github.com/php/php-src/pull/8758 but waiting feedback from Oracle team before going ahead. --- ext/oci8/oci8.stub.php | 2 ++ ext/oci8/oci8_arginfo.h | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ext/oci8/oci8.stub.php b/ext/oci8/oci8.stub.php index 1cdb076988e9f..aaa6585d00f11 100644 --- a/ext/oci8/oci8.stub.php +++ b/ext/oci8/oci8.stub.php @@ -560,6 +560,7 @@ function oci_register_taf_callback($connection, ?callable $callback): bool {} /** @param resource $connection */ function oci_unregister_taf_callback($connection): bool {} +#[\AllowDynamicProperties] class OCILob { /** * @alias oci_lob_save @@ -688,6 +689,7 @@ public function close(): bool {} public function free(): bool {} } +#[\AllowDynamicProperties] class OCICollection { /** * @alias oci_free_collection diff --git a/ext/oci8/oci8_arginfo.h b/ext/oci8/oci8_arginfo.h index 5ba7cfa5579f4..eff5d7c0eee3b 100644 --- a/ext/oci8/oci8_arginfo.h +++ b/ext/oci8/oci8_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: db170b61403c53d4d420d0095031944f3d036508 */ + * Stub hash: 592fbc9718ff272e1cb182025963683541a7a646 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_oci_define_by_name, 0, 3, _IS_BOOL, 0) ZEND_ARG_INFO(0, statement) @@ -815,6 +815,8 @@ static zend_class_entry *register_class_OCILob(void) INIT_CLASS_ENTRY(ce, "OCILob", class_OCILob_methods); class_entry = zend_register_internal_class_ex(&ce, NULL); + class_entry->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; + zend_add_class_attribute(class_entry, zend_ce_allow_dynamic_properties->name, 0); return class_entry; } @@ -825,6 +827,8 @@ static zend_class_entry *register_class_OCICollection(void) INIT_CLASS_ENTRY(ce, "OCICollection", class_OCICollection_methods); class_entry = zend_register_internal_class_ex(&ce, NULL); + class_entry->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; + zend_add_class_attribute(class_entry, zend_ce_allow_dynamic_properties->name, 0); return class_entry; } From 5bfc160817a3b707718cc764661321daffadd402 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Wed, 22 Jun 2022 09:34:23 +0100 Subject: [PATCH 059/440] Don't shortcut empty oparray executions if zend_execute_ex has been overridden --- Zend/zend_vm_def.h | 3 ++- Zend/zend_vm_execute.h | 12 ++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 54cc5dfe3a923..9043cde725bac 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -6281,7 +6281,8 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL, SPEC(OBSER } } else if (new_op_array->last == 1 && new_op_array->opcodes[0].opcode == ZEND_RETURN - && new_op_array->opcodes[0].op1_type == IS_CONST) { + && new_op_array->opcodes[0].op1_type == IS_CONST + && EXPECTED(zend_execute_ex == execute_ex)) { if (RETURN_VALUE_USED(opline)) { const zend_op *op = new_op_array->opcodes; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 76e4aace61471..39005c9184946 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4843,7 +4843,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN } } else if (new_op_array->last == 1 && new_op_array->opcodes[0].opcode == ZEND_RETURN - && new_op_array->opcodes[0].op1_type == IS_CONST) { + && new_op_array->opcodes[0].op1_type == IS_CONST + && EXPECTED(zend_execute_ex == execute_ex)) { if (RETURN_VALUE_USED(opline)) { const zend_op *op = new_op_array->opcodes; @@ -4925,7 +4926,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_ } } else if (new_op_array->last == 1 && new_op_array->opcodes[0].opcode == ZEND_RETURN - && new_op_array->opcodes[0].op1_type == IS_CONST) { + && new_op_array->opcodes[0].op1_type == IS_CONST + && EXPECTED(zend_execute_ex == execute_ex)) { if (RETURN_VALUE_USED(opline)) { const zend_op *op = new_op_array->opcodes; @@ -14445,7 +14447,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA } } else if (new_op_array->last == 1 && new_op_array->opcodes[0].opcode == ZEND_RETURN - && new_op_array->opcodes[0].op1_type == IS_CONST) { + && new_op_array->opcodes[0].op1_type == IS_CONST + && EXPECTED(zend_execute_ex == execute_ex)) { if (RETURN_VALUE_USED(opline)) { const zend_op *op = new_op_array->opcodes; @@ -38830,7 +38833,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE } } else if (new_op_array->last == 1 && new_op_array->opcodes[0].opcode == ZEND_RETURN - && new_op_array->opcodes[0].op1_type == IS_CONST) { + && new_op_array->opcodes[0].op1_type == IS_CONST + && EXPECTED(zend_execute_ex == execute_ex)) { if (RETURN_VALUE_USED(opline)) { const zend_op *op = new_op_array->opcodes; From 1380b65d261d1ab2e2e920173b836cd95325c8a0 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 19 Jun 2022 23:46:57 +0200 Subject: [PATCH 060/440] Remove reundant address comparison in accel_remap_huge_pages Closes GH-8830 MAP_FIXED guarantees mmap will return that exact address or fail so the address comparison is redundant. The return value of this function is unused but I kept it because it improves readability. --- ext/opcache/ZendAccelerator.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index bf62383b6c274..3affc20c3ea32 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2984,19 +2984,19 @@ static int accel_remap_huge_pages(void *start, size_t size, size_t real_size, co zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " huge_code_pages: mmap(HUGETLB) failed: %s (%d)", strerror(errno), errno); - return -1; + return FAILURE; # endif } + // Given the MAP_FIXED flag the address can never diverge + ZEND_ASSERT(ret == start); zend_mmap_set_name(start, size, "zend_huge_code_pages"); + memcpy(start, mem, real_size); + mprotect(start, size, PROT_READ | PROT_EXEC); - if (ret == start) { - memcpy(start, mem, real_size); - mprotect(start, size, PROT_READ | PROT_EXEC); - } munmap(mem, size); - return (ret == start) ? 0 : -1; + return SUCCESS; } static void accel_move_code_to_huge_pages(void) From 0429159775658f9b9f81d67e4206cf449da01679 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 22 Jun 2022 18:10:05 +0200 Subject: [PATCH 061/440] Fully convert accel_remap_huge_pages to use zend_result Changes were lost during rebase... --- ext/opcache/ZendAccelerator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 3affc20c3ea32..9620c858cc26f 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2937,7 +2937,7 @@ static void accel_globals_ctor(zend_accel_globals *accel_globals) # endif # if defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE) -static int accel_remap_huge_pages(void *start, size_t size, size_t real_size, const char *name, size_t offset) +static zend_result accel_remap_huge_pages(void *start, size_t size, size_t real_size, const char *name, size_t offset) { void *ret = MAP_FAILED; void *mem; @@ -2950,7 +2950,7 @@ static int accel_remap_huge_pages(void *start, size_t size, size_t real_size, co zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " huge_code_pages: mmap failed: %s (%d)", strerror(errno), errno); - return -1; + return FAILURE; } memcpy(mem, start, real_size); @@ -2975,7 +2975,7 @@ static int accel_remap_huge_pages(void *start, size_t size, size_t real_size, co zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " huge_code_pages: madvise(HUGEPAGE) failed: %s (%d)", strerror(errno), errno); - return -1; + return FAILURE; } # else memcpy(start, mem, real_size); From 9405f43ba927376e02f4023cbfdc0f9bf412396d Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 23 Jun 2022 13:23:27 +0200 Subject: [PATCH 062/440] Fix GH-8848: imagecopyresized() error refers to the wrong argument Closes GH-8849. --- NEWS | 3 +++ ext/gd/gd.c | 8 ++++---- ext/gd/tests/gh8848.phpt | 31 +++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 ext/gd/tests/gh8848.phpt diff --git a/NEWS b/NEWS index c25a387d4fbf8..3474bfa63812f 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2022, PHP 8.0.22 +- GD: + . Fixed bug GH-8848 (imagecopyresized() error refers to the wrong argument). + (cmb) 07 Jul 2022, PHP 8.0.21 diff --git a/ext/gd/gd.c b/ext/gd/gd.c index bed7e53ac53a3..336ddef9c6b4f 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3013,22 +3013,22 @@ PHP_FUNCTION(imagecopyresized) dstW = DW; if (dstW <= 0) { - zend_argument_value_error(3, "must be greater than 0"); + zend_argument_value_error(7, "must be greater than 0"); RETURN_THROWS(); } if (dstH <= 0) { - zend_argument_value_error(4, "must be greater than 0"); + zend_argument_value_error(8, "must be greater than 0"); RETURN_THROWS(); } if (srcW <= 0) { - zend_argument_value_error(5, "must be greater than 0"); + zend_argument_value_error(9, "must be greater than 0"); RETURN_THROWS(); } if (srcH <= 0) { - zend_argument_value_error(6, "must be greater than 0"); + zend_argument_value_error(10, "must be greater than 0"); RETURN_THROWS(); } diff --git a/ext/gd/tests/gh8848.phpt b/ext/gd/tests/gh8848.phpt new file mode 100644 index 0000000000000..bd89d0b075749 --- /dev/null +++ b/ext/gd/tests/gh8848.phpt @@ -0,0 +1,31 @@ +--TEST-- +GH-8848 (imagecopyresized() error refers to the wrong argument) +--SKIPIF-- + +--FILE-- +getMessage(), PHP_EOL; + } +} +?> +--EXPECT-- +imagecopyresized(): Argument #7 ($dst_width) must be greater than 0 +imagecopyresized(): Argument #8 ($dst_height) must be greater than 0 +imagecopyresized(): Argument #9 ($src_width) must be greater than 0 +imagecopyresized(): Argument #10 ($src_height) must be greater than 0 From 4d43241e96c570addf14a40ab90361a56d5201ee Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 20 Jun 2022 18:24:04 +0100 Subject: [PATCH 063/440] Move some private SPL Directory elements out of the header --- ext/spl/spl_directory.c | 29 +++++++++++++++++++++++++++++ ext/spl/spl_directory.h | 40 ++++++---------------------------------- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index cc1a660823330..947b05fde5753 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -52,6 +52,35 @@ PHPAPI zend_class_entry *spl_ce_GlobIterator; PHPAPI zend_class_entry *spl_ce_SplFileObject; PHPAPI zend_class_entry *spl_ce_SplTempFileObject; +/* Object helper */ +static inline spl_filesystem_object *spl_filesystem_from_obj(zend_object *obj) /* {{{ */ { + return (spl_filesystem_object*)((char*)(obj) - XtOffsetOf(spl_filesystem_object, std)); +} +/* }}} */ +#define Z_SPLFILESYSTEM_P(zv) spl_filesystem_from_obj(Z_OBJ_P((zv))) + +/* define an overloaded iterator structure */ +typedef struct { + zend_object_iterator intern; + zval current; + void *object; +} spl_filesystem_iterator; + +static inline spl_filesystem_iterator* spl_filesystem_object_to_iterator(spl_filesystem_object *obj) +{ + spl_filesystem_iterator *it; + + it = ecalloc(1, sizeof(spl_filesystem_iterator)); + it->object = (void *)obj; + zend_iterator_init(&it->intern); + return it; +} + +static inline spl_filesystem_object* spl_filesystem_iterator_to_object(spl_filesystem_iterator *it) +{ + return (spl_filesystem_object*)it->object; +} + #define CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(spl_filesystem_object_pointer) \ if (!(spl_filesystem_object_pointer)->u.file.stream) { \ zend_throw_error(NULL, "Object not initialized"); \ diff --git a/ext/spl/spl_directory.h b/ext/spl/spl_directory.h index 0a99a0778be1e..bb300f0e93ce8 100644 --- a/ext/spl/spl_directory.h +++ b/ext/spl/spl_directory.h @@ -30,12 +30,7 @@ extern PHPAPI zend_class_entry *spl_ce_SplTempFileObject; PHP_MINIT_FUNCTION(spl_directory); -typedef enum { - SPL_FS_INFO, /* must be 0 */ - SPL_FS_DIR, - SPL_FS_FILE -} SPL_FS_OBJ_TYPE; - +/* Internal objecte structure and helpers for Directory and File SPL objects */ typedef struct _spl_filesystem_object spl_filesystem_object; typedef void (*spl_foreign_dtor_t)(spl_filesystem_object *object); @@ -48,12 +43,11 @@ typedef struct _spl_other_handler { spl_foreign_clone_t clone; } spl_other_handler; -/* define an overloaded iterator structure */ -typedef struct { - zend_object_iterator intern; - zval current; - void *object; -} spl_filesystem_iterator; +typedef enum { + SPL_FS_INFO, /* must be 0 */ + SPL_FS_DIR, + SPL_FS_FILE +} SPL_FS_OBJ_TYPE; struct _spl_filesystem_object { void *oth; @@ -96,28 +90,6 @@ struct _spl_filesystem_object { zend_object std; }; -static inline spl_filesystem_object *spl_filesystem_from_obj(zend_object *obj) /* {{{ */ { - return (spl_filesystem_object*)((char*)(obj) - XtOffsetOf(spl_filesystem_object, std)); -} -/* }}} */ - -#define Z_SPLFILESYSTEM_P(zv) spl_filesystem_from_obj(Z_OBJ_P((zv))) - -static inline spl_filesystem_iterator* spl_filesystem_object_to_iterator(spl_filesystem_object *obj) -{ - spl_filesystem_iterator *it; - - it = ecalloc(1, sizeof(spl_filesystem_iterator)); - it->object = (void *)obj; - zend_iterator_init(&it->intern); - return it; -} - -static inline spl_filesystem_object* spl_filesystem_iterator_to_object(spl_filesystem_iterator *it) -{ - return (spl_filesystem_object*)it->object; -} - #define SPL_FILE_OBJECT_DROP_NEW_LINE 0x00000001 /* drop new lines */ #define SPL_FILE_OBJECT_READ_AHEAD 0x00000002 /* read on rewind/next */ #define SPL_FILE_OBJECT_SKIP_EMPTY 0x00000004 /* skip empty lines */ From 623fbfe74846b6e02bd9f9e9671251daca967433 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 20 Jun 2022 18:28:20 +0100 Subject: [PATCH 064/440] Remove Z_SPLFILESYSTEM_P macro Remove one level of macro expansion hell --- ext/spl/spl_directory.c | 135 ++++++++++++++++++++-------------------- 1 file changed, 67 insertions(+), 68 deletions(-) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 947b05fde5753..05cdc7caa5f43 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -57,7 +57,6 @@ static inline spl_filesystem_object *spl_filesystem_from_obj(zend_object *obj) / return (spl_filesystem_object*)((char*)(obj) - XtOffsetOf(spl_filesystem_object, std)); } /* }}} */ -#define Z_SPLFILESYSTEM_P(zv) spl_filesystem_from_obj(Z_OBJ_P((zv))) /* define an overloaded iterator structure */ typedef struct { @@ -760,7 +759,7 @@ void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, zend_long cto RETURN_THROWS(); } - intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (intern->path) { /* object is already initialized */ zend_throw_error(NULL, "Directory object is already initialized"); @@ -797,7 +796,7 @@ PHP_METHOD(DirectoryIterator, __construct) /* {{{ Rewind dir back to the start */ PHP_METHOD(DirectoryIterator, rewind) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -813,7 +812,7 @@ PHP_METHOD(DirectoryIterator, rewind) /* {{{ Return current dir entry */ PHP_METHOD(DirectoryIterator, key) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -831,7 +830,7 @@ PHP_METHOD(DirectoryIterator, current) RETURN_THROWS(); } - CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(Z_SPLFILESYSTEM_P(ZEND_THIS)); + CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS))); RETURN_OBJ_COPY(Z_OBJ_P(ZEND_THIS)); } /* }}} */ @@ -839,7 +838,7 @@ PHP_METHOD(DirectoryIterator, current) /* {{{ Move to next entry */ PHP_METHOD(DirectoryIterator, next) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); bool skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS); if (zend_parse_parameters_none() == FAILURE) { @@ -861,7 +860,7 @@ PHP_METHOD(DirectoryIterator, next) /* {{{ Seek to the given position */ PHP_METHOD(DirectoryIterator, seek) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zval retval; zend_long pos; @@ -891,7 +890,7 @@ PHP_METHOD(DirectoryIterator, seek) /* {{{ Check whether dir contains more entries */ PHP_METHOD(DirectoryIterator, valid) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -905,7 +904,7 @@ PHP_METHOD(DirectoryIterator, valid) /* {{{ Return the path */ PHP_METHOD(SplFileInfo, getPath) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char *path; size_t path_len; @@ -925,7 +924,7 @@ PHP_METHOD(SplFileInfo, getPath) /* {{{ Return filename only */ PHP_METHOD(SplFileInfo, getFilename) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); size_t path_len; if (zend_parse_parameters_none() == FAILURE) { @@ -950,7 +949,7 @@ PHP_METHOD(SplFileInfo, getFilename) /* {{{ Return filename of current dir entry */ PHP_METHOD(DirectoryIterator, getFilename) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -964,7 +963,7 @@ PHP_METHOD(DirectoryIterator, getFilename) /* {{{ Returns file extension component of path */ PHP_METHOD(SplFileInfo, getExtension) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char *fname = NULL; const char *p; size_t flen; @@ -1009,7 +1008,7 @@ PHP_METHOD(SplFileInfo, getExtension) /* {{{ Returns the file extension component of path */ PHP_METHOD(DirectoryIterator, getExtension) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); const char *p; size_t idx; zend_string *fname; @@ -1036,7 +1035,7 @@ PHP_METHOD(DirectoryIterator, getExtension) /* {{{ Returns filename component of path */ PHP_METHOD(SplFileInfo, getBasename) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char *fname, *suffix = 0; size_t flen; size_t slen = 0, path_len; @@ -1067,7 +1066,7 @@ PHP_METHOD(SplFileInfo, getBasename) /* {{{ Returns filename component of current dir entry */ PHP_METHOD(DirectoryIterator, getBasename) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char *suffix = 0; size_t slen = 0; zend_string *fname; @@ -1086,7 +1085,7 @@ PHP_METHOD(DirectoryIterator, getBasename) /* {{{ Return path and filename */ PHP_METHOD(SplFileInfo, getPathname) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_string *path; if (zend_parse_parameters_none() == FAILURE) { @@ -1104,7 +1103,7 @@ PHP_METHOD(SplFileInfo, getPathname) /* {{{ Return getPathname() or getFilename() depending on flags */ PHP_METHOD(FilesystemIterator, key) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -1124,7 +1123,7 @@ PHP_METHOD(FilesystemIterator, key) /* {{{ Return getFilename(), getFileInfo() or $this depending on flags */ PHP_METHOD(FilesystemIterator, current) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -1149,7 +1148,7 @@ PHP_METHOD(FilesystemIterator, current) /* {{{ Returns true if current entry is '.' or '..' */ PHP_METHOD(DirectoryIterator, isDot) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -1173,7 +1172,7 @@ PHP_METHOD(SplFileInfo, __construct) RETURN_THROWS(); } - intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); spl_filesystem_info_set_filename(intern, path); @@ -1185,7 +1184,7 @@ PHP_METHOD(SplFileInfo, __construct) #define FileInfoFunction(func_name, func_num) \ PHP_METHOD(SplFileInfo, func_name) \ { \ - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); \ + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); \ zend_error_handling error_handling; \ if (zend_parse_parameters_none() == FAILURE) { \ RETURN_THROWS(); \ @@ -1262,7 +1261,7 @@ FileInfoFunction(isLink, FS_IS_LINK) /* {{{ Return the target of a symbolic link */ PHP_METHOD(SplFileInfo, getLinkTarget) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); ssize_t ret; char buff[MAXPATHLEN]; @@ -1309,7 +1308,7 @@ PHP_METHOD(SplFileInfo, getLinkTarget) /* {{{ Return the resolved path */ PHP_METHOD(SplFileInfo, getRealPath) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char buff[MAXPATHLEN]; char *filename; @@ -1346,7 +1345,7 @@ PHP_METHOD(SplFileInfo, getRealPath) /* {{{ Open the current file */ PHP_METHOD(SplFileInfo, openFile) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_FILE, NULL, return_value); } @@ -1355,7 +1354,7 @@ PHP_METHOD(SplFileInfo, openFile) /* {{{ Class to use in openFile() */ PHP_METHOD(SplFileInfo, setFileClass) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_class_entry *ce = spl_ce_SplFileObject; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == FAILURE) { @@ -1369,7 +1368,7 @@ PHP_METHOD(SplFileInfo, setFileClass) /* {{{ Class to use in getFileInfo(), getPathInfo() */ PHP_METHOD(SplFileInfo, setInfoClass) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_class_entry *ce = spl_ce_SplFileInfo; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == FAILURE) { @@ -1383,7 +1382,7 @@ PHP_METHOD(SplFileInfo, setInfoClass) /* {{{ Get/copy file info */ PHP_METHOD(SplFileInfo, getFileInfo) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_class_entry *ce = intern->info_class; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C!", &ce) == FAILURE) { @@ -1397,7 +1396,7 @@ PHP_METHOD(SplFileInfo, getFileInfo) /* {{{ Get/copy file info */ PHP_METHOD(SplFileInfo, getPathInfo) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_class_entry *ce = intern->info_class; zend_string *path; @@ -1446,7 +1445,7 @@ PHP_METHOD(FilesystemIterator, __construct) /* {{{ Rewind dir back to the start */ PHP_METHOD(FilesystemIterator, rewind) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); bool skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS); if (zend_parse_parameters_none() == FAILURE) { @@ -1466,7 +1465,7 @@ PHP_METHOD(FilesystemIterator, rewind) /* {{{ Get handling flags */ PHP_METHOD(FilesystemIterator, getFlags) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -1478,7 +1477,7 @@ PHP_METHOD(FilesystemIterator, getFlags) /* {{{ Set handling flags */ PHP_METHOD(FilesystemIterator, setFlags) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_long flags; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &flags) == FAILURE) { @@ -1493,7 +1492,7 @@ PHP_METHOD(FilesystemIterator, setFlags) PHP_METHOD(RecursiveDirectoryIterator, hasChildren) { bool allow_links = 0; - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL @@ -1526,7 +1525,7 @@ PHP_METHOD(RecursiveDirectoryIterator, hasChildren) PHP_METHOD(RecursiveDirectoryIterator, getChildren) { zval zpath, zflags; - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); spl_filesystem_object *subdir; char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH; @@ -1543,7 +1542,7 @@ PHP_METHOD(RecursiveDirectoryIterator, getChildren) spl_instantiate_arg_ex2(Z_OBJCE_P(ZEND_THIS), return_value, &zpath, &zflags); zval_ptr_dtor(&zpath); - subdir = Z_SPLFILESYSTEM_P(return_value); + subdir = spl_filesystem_from_obj(Z_OBJ_P(return_value)); if (subdir) { size_t name_len = strlen(intern->u.dir.entry.d_name); if (intern->u.dir.sub_path && ZSTR_LEN(intern->u.dir.sub_path)) { @@ -1566,7 +1565,7 @@ PHP_METHOD(RecursiveDirectoryIterator, getChildren) /* {{{ Get sub path */ PHP_METHOD(RecursiveDirectoryIterator, getSubPath) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -1583,7 +1582,7 @@ PHP_METHOD(RecursiveDirectoryIterator, getSubPath) /* {{{ Get sub path and file name */ PHP_METHOD(RecursiveDirectoryIterator, getSubPathname) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH; if (zend_parse_parameters_none() == FAILURE) { @@ -1616,7 +1615,7 @@ PHP_METHOD(GlobIterator, __construct) /* {{{ Return the number of directories and files found by globbing */ PHP_METHOD(GlobIterator, count) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -1664,7 +1663,7 @@ zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval zend_throw_error(NULL, "An iterator cannot be used with foreach by reference"); return NULL; } - dir_object = Z_SPLFILESYSTEM_P(object); + dir_object = spl_filesystem_from_obj(Z_OBJ_P(object)); iterator = spl_filesystem_object_to_iterator(dir_object); ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object)); iterator->intern.funcs = &spl_filesystem_dir_it_funcs; @@ -1857,7 +1856,7 @@ zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zva zend_throw_error(NULL, "An iterator cannot be used with foreach by reference"); return NULL; } - dir_object = Z_SPLFILESYSTEM_P(object); + dir_object = spl_filesystem_from_obj(Z_OBJ_P(object)); iterator = spl_filesystem_object_to_iterator(dir_object); ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object)); @@ -2090,7 +2089,7 @@ static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *i /* {{{ Construct a new file object */ PHP_METHOD(SplFileObject, __construct) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_string *open_mode = ZSTR_CHAR('r'); bool use_include_path = 0; size_t path_len; @@ -2138,7 +2137,7 @@ PHP_METHOD(SplTempFileObject, __construct) { zend_string *file_name; zend_long max_memory = PHP_STREAM_MAX_MEM; - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_error_handling error_handling; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &max_memory) == FAILURE) { @@ -2167,7 +2166,7 @@ PHP_METHOD(SplTempFileObject, __construct) /* {{{ Rewind the file and read the first line */ PHP_METHOD(SplFileObject, rewind) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -2179,7 +2178,7 @@ PHP_METHOD(SplFileObject, rewind) /* {{{ Return whether end of file is reached */ PHP_METHOD(SplFileObject, eof) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -2193,7 +2192,7 @@ PHP_METHOD(SplFileObject, eof) /* {{{ Return !eof() */ PHP_METHOD(SplFileObject, valid) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -2211,7 +2210,7 @@ PHP_METHOD(SplFileObject, valid) /* {{{ Return next line from file */ PHP_METHOD(SplFileObject, fgets) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -2228,7 +2227,7 @@ PHP_METHOD(SplFileObject, fgets) /* {{{ Return current line from file */ PHP_METHOD(SplFileObject, current) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -2251,7 +2250,7 @@ PHP_METHOD(SplFileObject, current) /* {{{ Return line number */ PHP_METHOD(SplFileObject, key) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -2267,7 +2266,7 @@ PHP_METHOD(SplFileObject, key) /* {{{ Read next line */ PHP_METHOD(SplFileObject, next) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -2283,7 +2282,7 @@ PHP_METHOD(SplFileObject, next) /* {{{ Set file handling flags */ PHP_METHOD(SplFileObject, setFlags) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &intern->flags) == FAILURE) { RETURN_THROWS(); @@ -2293,7 +2292,7 @@ PHP_METHOD(SplFileObject, setFlags) /* {{{ Get file handling flags */ PHP_METHOD(SplFileObject, getFlags) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -2307,7 +2306,7 @@ PHP_METHOD(SplFileObject, setMaxLineLen) { zend_long max_len; - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &max_len) == FAILURE) { RETURN_THROWS(); @@ -2324,7 +2323,7 @@ PHP_METHOD(SplFileObject, setMaxLineLen) /* {{{ Get maximum line length */ PHP_METHOD(SplFileObject, getMaxLineLen) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -2355,7 +2354,7 @@ PHP_METHOD(SplFileObject, getChildren) /* {{{ Return current line as CSV */ PHP_METHOD(SplFileObject, fgetcsv) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure; int escape = intern->u.file.escape; char *delim = NULL, *enclo = NULL, *esc = NULL; @@ -2402,7 +2401,7 @@ PHP_METHOD(SplFileObject, fgetcsv) /* {{{ Output a field array as a CSV line */ PHP_METHOD(SplFileObject, fputcsv) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure; int escape = intern->u.file.escape; char *delim = NULL, *enclo = NULL, *esc = NULL; @@ -2452,7 +2451,7 @@ PHP_METHOD(SplFileObject, fputcsv) /* {{{ Set the delimiter, enclosure and escape character used in fgetcsv */ PHP_METHOD(SplFileObject, setCsvControl) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char delimiter = ',', enclosure = '"'; int escape = (unsigned char) '\\'; char *delim = NULL, *enclo = NULL, *esc = NULL; @@ -2497,7 +2496,7 @@ PHP_METHOD(SplFileObject, setCsvControl) /* {{{ Get the delimiter, enclosure and escape character used in fgetcsv */ PHP_METHOD(SplFileObject, getCsvControl) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char delimiter[2], enclosure[2], escape[2]; if (zend_parse_parameters_none() == FAILURE) { @@ -2526,7 +2525,7 @@ PHP_METHOD(SplFileObject, getCsvControl) /* {{{ Portable file locking */ PHP_METHOD(SplFileObject, flock) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zval *wouldblock = NULL; zend_long operation = 0; @@ -2543,7 +2542,7 @@ PHP_METHOD(SplFileObject, flock) /* {{{ Flush the file */ PHP_METHOD(SplFileObject, fflush) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -2557,7 +2556,7 @@ PHP_METHOD(SplFileObject, fflush) /* {{{ Return current file position */ PHP_METHOD(SplFileObject, ftell) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_long ret; if (zend_parse_parameters_none() == FAILURE) { @@ -2578,7 +2577,7 @@ PHP_METHOD(SplFileObject, ftell) /* {{{ Seek to a position */ PHP_METHOD(SplFileObject, fseek) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_long pos, whence = SEEK_SET; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &pos, &whence) == FAILURE) { @@ -2594,7 +2593,7 @@ PHP_METHOD(SplFileObject, fseek) /* {{{ Get a character from the file */ PHP_METHOD(SplFileObject, fgetc) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char buf[2]; int result; @@ -2623,7 +2622,7 @@ PHP_METHOD(SplFileObject, fgetc) /* {{{ Output all remaining data from a file pointer */ PHP_METHOD(SplFileObject, fpassthru) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -2640,7 +2639,7 @@ PHP_METHOD(SplFileObject, fscanf) int result, num_varargs = 0; zend_string *format_str; zval *varargs= NULL; - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters(ZEND_NUM_ARGS(), "S*", &format_str, &varargs, &num_varargs) == FAILURE) { RETURN_THROWS(); @@ -2664,7 +2663,7 @@ PHP_METHOD(SplFileObject, fscanf) /* {{{ Binary-safe file write */ PHP_METHOD(SplFileObject, fwrite) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char *str; size_t str_len; zend_long length = 0; @@ -2697,7 +2696,7 @@ PHP_METHOD(SplFileObject, fwrite) PHP_METHOD(SplFileObject, fread) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_long length = 0; zend_string *str; @@ -2722,7 +2721,7 @@ PHP_METHOD(SplFileObject, fread) /* {{{ Stat() on a filehandle */ PHP_METHOD(SplFileObject, fstat) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -2737,7 +2736,7 @@ PHP_METHOD(SplFileObject, fstat) /* {{{ Truncate file to 'size' length */ PHP_METHOD(SplFileObject, ftruncate) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_long size; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &size) == FAILURE) { @@ -2757,7 +2756,7 @@ PHP_METHOD(SplFileObject, ftruncate) /* {{{ Seek to specified line */ PHP_METHOD(SplFileObject, seek) { - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); zend_long line_pos, i; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &line_pos) == FAILURE) { From 7cd8879d777d1374974f452132d6d48ca7da7b59 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 21 Jun 2022 12:29:35 +0100 Subject: [PATCH 065/440] Refactor spl_filesystem_object_get_path() to return zend_string* --- ext/phar/phar_object.c | 8 ++- ext/spl/spl_directory.c | 129 ++++++++++++++++++---------------------- ext/spl/spl_directory.h | 2 +- 3 files changed, 64 insertions(+), 75 deletions(-) diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index a9bad08aa39f9..f8ab30bc969a9 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1448,9 +1448,10 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */ } switch (intern->type) { - case SPL_FS_DIR: - test = spl_filesystem_object_get_path(intern, NULL); - fname_len = spprintf(&fname, 0, "%s%c%s", test, DEFAULT_SLASH, intern->u.dir.entry.d_name); + case SPL_FS_DIR: { + zend_string *test_str = spl_filesystem_object_get_path(intern); + fname_len = spprintf(&fname, 0, "%s%c%s", ZSTR_VAL(test_str), DEFAULT_SLASH, intern->u.dir.entry.d_name); + zend_string_release_ex(test_str, /* persistent */ false); if (php_stream_stat_path(fname, &ssb) == 0 && S_ISDIR(ssb.sb.st_mode)) { /* ignore directories */ efree(fname); @@ -1470,6 +1471,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */ save = fname; goto phar_spl_fileinfo; + } case SPL_FS_INFO: case SPL_FS_FILE: fname = expand_filepath(ZSTR_VAL(intern->file_name), NULL); diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 05cdc7caa5f43..9de3445b7f43d 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -222,19 +222,22 @@ static zend_object *spl_filesystem_object_new_check(zend_class_entry *class_type } /* }}} */ -PHPAPI char* spl_filesystem_object_get_path(spl_filesystem_object *intern, size_t *len) /* {{{ */ +PHPAPI zend_string *spl_filesystem_object_get_path(spl_filesystem_object *intern) /* {{{ */ { #ifdef HAVE_GLOB - if (intern->type == SPL_FS_DIR) { - if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) { - return php_glob_stream_get_path(intern->u.dir.dirp, len); + if (intern->type == SPL_FS_DIR && php_stream_is(intern->u.dir.dirp, &php_glob_stream_ops)) { + size_t len = 0; + char *tmp = php_glob_stream_get_path(intern->u.dir.dirp, &len); + if (len == 0) { + return NULL; } + return zend_string_init(tmp, len, /* persistent */ false); } #endif - if (len) { - *len = intern->path ? ZSTR_LEN(intern->path) : 0; + if (!intern->path) { + return NULL; } - return intern->path ? ZSTR_VAL(intern->path) : NULL; + return zend_string_copy(intern->path); } /* }}} */ static inline zend_result spl_filesystem_object_get_file_name(spl_filesystem_object *intern) /* {{{ */ @@ -249,29 +252,25 @@ static inline zend_result spl_filesystem_object_get_file_name(spl_filesystem_obj case SPL_FS_FILE: zend_throw_error(NULL, "Object not initialized"); return FAILURE; - break; - case SPL_FS_DIR: - { - size_t name_len; - size_t path_len = 0; - char *path; - char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH; - - path = spl_filesystem_object_get_path(intern, &path_len); - /* if there is parent path, amend it, otherwise just use the given path as is */ - name_len = strlen(intern->u.dir.entry.d_name); - if (path_len == 0) { - intern->file_name = zend_string_init(intern->u.dir.entry.d_name, name_len, 0); - } else { - zend_string *file_name = zend_string_alloc(path_len + 1 + name_len, 0); - memcpy(ZSTR_VAL(file_name), path, path_len); - ZSTR_VAL(file_name)[path_len] = slash; - memcpy(ZSTR_VAL(file_name) + path_len + 1, intern->u.dir.entry.d_name, name_len); - ZSTR_VAL(file_name)[path_len + 1 + name_len] = 0; - intern->file_name = file_name; - } + case SPL_FS_DIR: { + size_t name_len; + zend_string *path; + char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH; + + path = spl_filesystem_object_get_path(intern); + /* if there is parent path, amend it, otherwise just use the given path as is */ + name_len = strlen(intern->u.dir.entry.d_name); + if (!path) { + intern->file_name = zend_string_init(intern->u.dir.entry.d_name, name_len, 0); + return SUCCESS; } + + ZEND_ASSERT(ZSTR_LEN(path) != 0); + intern->file_name = zend_string_concat3( + ZSTR_VAL(path), ZSTR_LEN(path), &slash, 1, intern->u.dir.entry.d_name, name_len); + zend_string_release_ex(path, /* persistent */ false); break; + } } return SUCCESS; } /* }}} */ @@ -545,16 +544,8 @@ static spl_filesystem_object *spl_filesystem_object_create_type(int num_args, sp zend_call_method_with_1_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1); zval_ptr_dtor(&arg1); } else { - char *path; - size_t path_len; - intern->file_name = zend_string_copy(source->file_name); - path = spl_filesystem_object_get_path(source, &path_len); - if (source->path && ZSTR_VAL(source->path) == path) { - intern->path = zend_string_copy(source->path); - } else { - intern->path = zend_string_init(path, path_len, 0); - } + intern->path = spl_filesystem_object_get_path(source); } break; case SPL_FS_FILE: @@ -584,17 +575,8 @@ static spl_filesystem_object *spl_filesystem_object_create_type(int num_args, sp zval_ptr_dtor(&arg1); zval_ptr_dtor(&arg2); } else { - char *path; - size_t path_len; - intern->file_name = source->file_name; - path = spl_filesystem_object_get_path(source, &path_len); - if (source->path && ZSTR_VAL(source->path) == path) { - intern->path = zend_string_copy(source->path); - } else { - intern->path = zend_string_init(path, path_len, 0); - } - + intern->path = spl_filesystem_object_get_path(source); intern->u.file.open_mode = zend_string_copy(open_mode); intern->u.file.zcontext = resource; @@ -664,18 +646,19 @@ static inline HashTable *spl_filesystem_object_get_debug_info(zend_object *objec zend_string_release_ex(pnstr, 0); if (intern->file_name) { - size_t path_len; + zend_string *path; pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "fileName", sizeof("fileName")-1); - spl_filesystem_object_get_path(intern, &path_len); + path = spl_filesystem_object_get_path(intern); - if (path_len && path_len < ZSTR_LEN(intern->file_name)) { - ZVAL_STRINGL(&tmp, ZSTR_VAL(intern->file_name) + path_len + 1, ZSTR_LEN(intern->file_name) - (path_len + 1)); + if (ZSTR_LEN(path) && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) { + ZVAL_STRINGL(&tmp, ZSTR_VAL(intern->file_name) + ZSTR_LEN(path) + 1, ZSTR_LEN(intern->file_name) - (ZSTR_LEN(path) + 1)); } else { ZVAL_STR_COPY(&tmp, intern->file_name); } zend_symtable_update(rv, pnstr, &tmp); - zend_string_release_ex(pnstr, 0); + zend_string_release_ex(pnstr, /* persistent */ false); + zend_string_release_ex(path, /* persistent */ false); } if (intern->type == SPL_FS_DIR) { #ifdef HAVE_GLOB @@ -905,16 +888,15 @@ PHP_METHOD(DirectoryIterator, valid) PHP_METHOD(SplFileInfo, getPath) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - char *path; - size_t path_len; + zend_string *path; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } - path = spl_filesystem_object_get_path(intern, &path_len); + path = spl_filesystem_object_get_path(intern); if (path) { - RETURN_STRINGL(path, path_len); + RETURN_STR(path); } else { RETURN_EMPTY_STRING(); } @@ -925,7 +907,7 @@ PHP_METHOD(SplFileInfo, getPath) PHP_METHOD(SplFileInfo, getFilename) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); - size_t path_len; + zend_string *path; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); @@ -936,13 +918,15 @@ PHP_METHOD(SplFileInfo, getFilename) RETURN_THROWS(); } - spl_filesystem_object_get_path(intern, &path_len); + path = spl_filesystem_object_get_path(intern); - if (path_len && path_len < ZSTR_LEN(intern->file_name)) { - RETURN_STRINGL(ZSTR_VAL(intern->file_name) + path_len + 1, ZSTR_LEN(intern->file_name) - (path_len + 1)); + if (path && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) { + size_t path_len = ZSTR_LEN(path); + RETVAL_STRINGL(ZSTR_VAL(intern->file_name) + path_len + 1, ZSTR_LEN(intern->file_name) - (path_len + 1)); } else { - RETURN_STR_COPY(intern->file_name); + RETVAL_STR_COPY(intern->file_name); } + zend_string_release_ex(path, /* persistent */ false); } /* }}} */ @@ -967,7 +951,7 @@ PHP_METHOD(SplFileInfo, getExtension) char *fname = NULL; const char *p; size_t flen; - size_t path_len; + zend_string *path; size_t idx; zend_string *ret; @@ -980,15 +964,16 @@ PHP_METHOD(SplFileInfo, getExtension) RETURN_THROWS(); } - spl_filesystem_object_get_path(intern, &path_len); + path = spl_filesystem_object_get_path(intern); - if (path_len && path_len < ZSTR_LEN(intern->file_name)) { - fname = ZSTR_VAL(intern->file_name) + path_len + 1; - flen = ZSTR_LEN(intern->file_name) - (path_len + 1); + if (ZSTR_LEN(path) && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) { + fname = ZSTR_VAL(intern->file_name) + ZSTR_LEN(path) + 1; + flen = ZSTR_LEN(intern->file_name) - (ZSTR_LEN(path) + 1); } else { fname = ZSTR_VAL(intern->file_name); flen = ZSTR_LEN(intern->file_name); } + zend_string_release_ex(path, /* persistent */ false); ret = php_basename(fname, flen, NULL, 0); @@ -1038,7 +1023,8 @@ PHP_METHOD(SplFileInfo, getBasename) spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); char *fname, *suffix = 0; size_t flen; - size_t slen = 0, path_len; + size_t slen = 0; + zend_string *path; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) { RETURN_THROWS(); @@ -1049,15 +1035,16 @@ PHP_METHOD(SplFileInfo, getBasename) RETURN_THROWS(); } - spl_filesystem_object_get_path(intern, &path_len); + path = spl_filesystem_object_get_path(intern); - if (path_len && path_len < ZSTR_LEN(intern->file_name)) { - fname = ZSTR_VAL(intern->file_name) + path_len + 1; - flen = ZSTR_LEN(intern->file_name) - (path_len + 1); + if (path && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) { + fname = ZSTR_VAL(intern->file_name) + ZSTR_LEN(path) + 1; + flen = ZSTR_LEN(intern->file_name) - (ZSTR_LEN(path) + 1); } else { fname = ZSTR_VAL(intern->file_name); flen = ZSTR_LEN(intern->file_name); } + zend_string_release_ex(path, /* persistent */ false); RETURN_STR(php_basename(fname, flen, suffix, slen)); } diff --git a/ext/spl/spl_directory.h b/ext/spl/spl_directory.h index bb300f0e93ce8..ca0e547865025 100644 --- a/ext/spl/spl_directory.h +++ b/ext/spl/spl_directory.h @@ -36,7 +36,7 @@ typedef struct _spl_filesystem_object spl_filesystem_object; typedef void (*spl_foreign_dtor_t)(spl_filesystem_object *object); typedef void (*spl_foreign_clone_t)(spl_filesystem_object *src, spl_filesystem_object *dst); -PHPAPI char* spl_filesystem_object_get_path(spl_filesystem_object *intern, size_t *len); +PHPAPI zend_string *spl_filesystem_object_get_path(spl_filesystem_object *intern); typedef struct _spl_other_handler { spl_foreign_dtor_t dtor; From 44cd74b6245b09be57e900e18556a7820df2c91a Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 17 Jun 2022 16:20:28 +0200 Subject: [PATCH 066/440] Fix lineno in backtrace of multi-line function calls Closes GH-8810 Closes GH-8818 --- NEWS | 2 ++ Zend/tests/gh8810_1.phpt | 22 +++++++++++++ Zend/tests/gh8810_2.phpt | 23 +++++++++++++ Zend/tests/gh8810_3.phpt | 19 +++++++++++ Zend/tests/gh8810_4.phpt | 19 +++++++++++ Zend/tests/gh8810_5.phpt | 16 +++++++++ Zend/tests/gh8810_6.phpt | 23 +++++++++++++ Zend/tests/gh8810_7.phpt | 22 +++++++++++++ Zend/zend_compile.c | 33 ++++++++++--------- Zend/zend_language_parser.y | 6 ++-- .../tests/dateformat_calendars_variant3.phpt | 2 +- 11 files changed, 168 insertions(+), 19 deletions(-) create mode 100644 Zend/tests/gh8810_1.phpt create mode 100644 Zend/tests/gh8810_2.phpt create mode 100644 Zend/tests/gh8810_3.phpt create mode 100644 Zend/tests/gh8810_4.phpt create mode 100644 Zend/tests/gh8810_5.phpt create mode 100644 Zend/tests/gh8810_6.phpt create mode 100644 Zend/tests/gh8810_7.phpt diff --git a/NEWS b/NEWS index b0fd93fb213f6..e0bb5b24cc57c 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ PHP NEWS warning). (ilutov) . Fixed bug GH-7821 and GH-8418 (Allow arbitrary const expressions in backed enums). (ilutov) + . Fixed bug GH-8810 (Incorrect lineno in backtrace of multi-line function + calls). (ilutov) - Curl: . Added new constants from cURL 7.62 to 7.80. (Pierrick) diff --git a/Zend/tests/gh8810_1.phpt b/Zend/tests/gh8810_1.phpt new file mode 100644 index 0000000000000..ec48d4df0da4a --- /dev/null +++ b/Zend/tests/gh8810_1.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line function call +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:4 +Stack trace: +#0 %s(7): foo('bar', 'baz') +#1 {main} + thrown in %s on line 4 diff --git a/Zend/tests/gh8810_2.phpt b/Zend/tests/gh8810_2.phpt new file mode 100644 index 0000000000000..df37057c7a7c3 --- /dev/null +++ b/Zend/tests/gh8810_2.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line method call +--FILE-- + + b + (); + +?> +--EXPECTF-- +Fatal error: Uncaught Exception in %s:5 +Stack trace: +#0 %s(11): A->b() +#1 {main} + thrown in %s on line 5 diff --git a/Zend/tests/gh8810_3.phpt b/Zend/tests/gh8810_3.phpt new file mode 100644 index 0000000000000..99fb449ce2fc0 --- /dev/null +++ b/Zend/tests/gh8810_3.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line closure call +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:4 +Stack trace: +#0 %s(6): {closure}('foo') +#1 {main} + thrown in %s on line 4 diff --git a/Zend/tests/gh8810_4.phpt b/Zend/tests/gh8810_4.phpt new file mode 100644 index 0000000000000..9abb317fbd10c --- /dev/null +++ b/Zend/tests/gh8810_4.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line dynamic call +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:4 +Stack trace: +#0 %s(8): foo() +#1 {main} + thrown in %s on line 4 diff --git a/Zend/tests/gh8810_5.phpt b/Zend/tests/gh8810_5.phpt new file mode 100644 index 0000000000000..1b3a983181c9a --- /dev/null +++ b/Zend/tests/gh8810_5.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line assert call +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught AssertionError: assert(false) in %s:3 +Stack trace: +#0 %s(3): assert(false, 'assert(false)') +#1 {main} + thrown in %s on line 3 diff --git a/Zend/tests/gh8810_6.phpt b/Zend/tests/gh8810_6.phpt new file mode 100644 index 0000000000000..452a859db5530 --- /dev/null +++ b/Zend/tests/gh8810_6.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line static call +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:5 +Stack trace: +#0 %s(11): A::b() +#1 {main} + thrown in %s on line 5 diff --git a/Zend/tests/gh8810_7.phpt b/Zend/tests/gh8810_7.phpt new file mode 100644 index 0000000000000..b435b25d483a4 --- /dev/null +++ b/Zend/tests/gh8810_7.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-8810: Fix reported line number of multi-line new call +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:5 +Stack trace: +#0 %s(10): A->__construct() +#1 {main} + thrown in %s on line 5 diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 728feded60896..c18c6db7e67da 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3623,7 +3623,7 @@ ZEND_API zend_uchar zend_get_call_op(const zend_op *init_op, zend_function *fbc) } /* }}} */ -static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc) /* {{{ */ +static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc, uint32_t lineno) /* {{{ */ { zend_op *opline; uint32_t opnum_init = get_next_op_number() - 1; @@ -3660,6 +3660,7 @@ static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_fun if (may_have_extra_named_args) { opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS; } + opline->lineno = lineno; zend_do_extended_fcall_end(); return false; } @@ -3678,7 +3679,7 @@ static bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /* } /* }}} */ -static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */ +static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno) /* {{{ */ { zend_op *opline = get_next_op(); opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME; @@ -3687,11 +3688,11 @@ static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args Z_STR(name_node->u.constant)); opline->result.num = zend_alloc_cache_slot(); - zend_compile_call_common(result, args_ast, NULL); + zend_compile_call_common(result, args_ast, NULL, lineno); } /* }}} */ -static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */ +static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno) /* {{{ */ { if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) { const char *colon; @@ -3721,7 +3722,7 @@ static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, name_node); } - zend_compile_call_common(result, args_ast, NULL); + zend_compile_call_common(result, args_ast, NULL, lineno); } /* }}} */ @@ -4015,7 +4016,7 @@ static zend_result zend_compile_func_cuf(znode *result, zend_ast_list *args, zen } /* }}} */ -static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, zend_function *fbc) /* {{{ */ +static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, zend_function *fbc, uint32_t lineno) /* {{{ */ { if (EG(assertions) >= 0) { znode name_node; @@ -4050,7 +4051,7 @@ static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string zend_ast_list_add((zend_ast *) args, arg); } - zend_compile_call_common(result, (zend_ast*)args, fbc); + zend_compile_call_common(result, (zend_ast*)args, fbc, lineno); opline = &CG(active_op_array)->opcodes[check_op_number]; opline->op2.opline_num = get_next_op_number(); @@ -4377,7 +4378,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) { zend_compile_expr(&name_node, name_ast); - zend_compile_dynamic_call(result, &name_node, args_ast); + zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno); return; } @@ -4386,9 +4387,9 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ if (runtime_resolution) { if (zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "assert") && !is_callable_convert) { - zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL); + zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL, ast->lineno); } else { - zend_compile_ns_call(result, &name_node, args_ast); + zend_compile_ns_call(result, &name_node, args_ast, ast->lineno); } return; } @@ -4405,7 +4406,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ /* Special assert() handling should apply independently of compiler flags. */ if (fbc && zend_string_equals_literal(lcname, "assert") && !is_callable_convert) { - zend_compile_assert(result, zend_ast_get_list(args_ast), lcname, fbc); + zend_compile_assert(result, zend_ast_get_list(args_ast), lcname, fbc, ast->lineno); zend_string_release(lcname); zval_ptr_dtor(&name_node.u.constant); return; @@ -4417,7 +4418,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename) ) { zend_string_release_ex(lcname, 0); - zend_compile_dynamic_call(result, &name_node, args_ast); + zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno); return; } @@ -4436,7 +4437,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node); opline->result.num = zend_alloc_cache_slot(); - zend_compile_call_common(result, args_ast, fbc); + zend_compile_call_common(result, args_ast, fbc, ast->lineno); } } /* }}} */ @@ -4500,7 +4501,7 @@ static void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type } } - if (zend_compile_call_common(result, args_ast, fbc)) { + if (zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast))) { if (short_circuiting_checkpoint != zend_short_circuiting_checkpoint()) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot combine nullsafe operator with Closure creation"); @@ -4597,7 +4598,7 @@ static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type } } - zend_compile_call_common(result, args_ast, fbc); + zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast)); } /* }}} */ @@ -4629,7 +4630,7 @@ static void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */ SET_NODE(opline->op1, &class_node); } - zend_compile_call_common(&ctor_result, args_ast, NULL); + zend_compile_call_common(&ctor_result, args_ast, NULL, ast->lineno); zend_do_free(&ctor_result); } /* }}} */ diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index a333bf52a8dad..9ad5354496924 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -1263,8 +1263,10 @@ function_call: { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); } | variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); } - | callable_expr argument_list - { $$ = zend_ast_create(ZEND_AST_CALL, $1, $2); } + | callable_expr { $$ = CG(zend_lineno); } argument_list { + $$ = zend_ast_create(ZEND_AST_CALL, $1, $3); + $$->lineno = $2; + } ; class_name: diff --git a/ext/intl/tests/dateformat_calendars_variant3.phpt b/ext/intl/tests/dateformat_calendars_variant3.phpt index 0e7f8b0183d71..d189361bcffb6 100644 --- a/ext/intl/tests/dateformat_calendars_variant3.phpt +++ b/ext/intl/tests/dateformat_calendars_variant3.phpt @@ -41,7 +41,7 @@ string(47) "Sunday, January 1, 2012 at 5:12:00 AM GMT+05:12" string(47) "Sunday, January 1, 2012 at 5:12:00 AM GMT+05:12" string(44) "Sunday, 6 Tevet 5772 at 5:12:00 AM GMT+05:12" -Fatal error: Uncaught IntlException: IntlDateFormatter::__construct(): datefmt_create: Invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object in %sdateformat_calendars_variant3.php:27 +Fatal error: Uncaught IntlException: IntlDateFormatter::__construct(): datefmt_create: Invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object in %sdateformat_calendars_variant3.php:%d Stack trace: #0 %sdateformat_calendars_variant3.php(%d): IntlDateFormatter->__construct('en_US@calendar=...', 0, 0, 'GMT+05:12', -1) #1 {main} From 9bfdfcac8f09b344201442c6a8c297450bac0250 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 23 Jun 2022 16:28:42 +0200 Subject: [PATCH 067/440] Replace more hard-coded line numbers --- .../tests/preg_replace_callback_array_error.phpt | 12 ++++++------ .../preg_replace_callback_array_fatal_error.phpt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/pcre/tests/preg_replace_callback_array_error.phpt b/ext/pcre/tests/preg_replace_callback_array_error.phpt index 7a73d5b00c211..6298d081b1f06 100644 --- a/ext/pcre/tests/preg_replace_callback_array_error.phpt +++ b/ext/pcre/tests/preg_replace_callback_array_error.phpt @@ -47,20 +47,20 @@ var_dump(preg_replace_callback_array( ?> --EXPECTF-- -Warning: preg_replace_callback_array(): Empty regular expression in %spreg_replace_callback_array_error.php on line 12 +Warning: preg_replace_callback_array(): Empty regular expression in %spreg_replace_callback_array_error.php on line %d NULL -Warning: preg_replace_callback_array(): Empty regular expression in %spreg_replace_callback_array_error.php on line 17 +Warning: preg_replace_callback_array(): Empty regular expression in %spreg_replace_callback_array_error.php on line %d NULL -Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_callback_array_error.php on line 24 +Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_callback_array_error.php on line %d NULL -Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_callback_array_error.php on line 31 +Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_callback_array_error.php on line %d NULL -Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_callback_array_error.php on line 36 +Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_callback_array_error.php on line %d NULL -Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_callback_array_error.php on line 43 +Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric, backslash, or NUL in %spreg_replace_callback_array_error.php on line %d NULL \ No newline at end of file diff --git a/ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt b/ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt index 0b018627de74a..03d69a6cea9ed 100644 --- a/ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt +++ b/ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt @@ -14,8 +14,8 @@ var_dump(preg_replace_callback_array( "/b/" => 'invalid callable'), 'a')); --EXPECTF-- -Fatal error: Uncaught TypeError: preg_replace_callback_array(): Argument #1 ($pattern) must contain only valid callbacks in %spreg_replace_callback_array_fatal_error.php:11 +Fatal error: Uncaught TypeError: preg_replace_callback_array(): Argument #1 ($pattern) must contain only valid callbacks in %spreg_replace_callback_array_fatal_error.php:%d Stack trace: #0 %spreg_replace_callback_array_fatal_error.php(11): preg_replace_callback_array(Array, 'a') #1 {main} - thrown in %spreg_replace_callback_array_fatal_error.php on line 11 + thrown in %spreg_replace_callback_array_fatal_error.php on line %d From cda7e8f1ecfe7f07875873e5a498ae725840449c Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 23 Jun 2022 16:48:17 +0200 Subject: [PATCH 068/440] Replace another hard-coded line number --- ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt b/ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt index 03d69a6cea9ed..dfbf73f54e96f 100644 --- a/ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt +++ b/ext/pcre/tests/preg_replace_callback_array_fatal_error.phpt @@ -16,6 +16,6 @@ var_dump(preg_replace_callback_array( --EXPECTF-- Fatal error: Uncaught TypeError: preg_replace_callback_array(): Argument #1 ($pattern) must contain only valid callbacks in %spreg_replace_callback_array_fatal_error.php:%d Stack trace: -#0 %spreg_replace_callback_array_fatal_error.php(11): preg_replace_callback_array(Array, 'a') +#0 %spreg_replace_callback_array_fatal_error.php(%d): preg_replace_callback_array(Array, 'a') #1 {main} thrown in %spreg_replace_callback_array_fatal_error.php on line %d From 56137cd26e276359c7f281b590cad08fdc52f0f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Thu, 23 Jun 2022 17:34:08 +0200 Subject: [PATCH 069/440] Declare ext/mbstring constants in stubs (#8798) --- ext/mbstring/mbstring.c | 11 ++------ ext/mbstring/mbstring.stub.php | 49 +++++++++++++++++++++++++++++++++ ext/mbstring/mbstring_arginfo.h | 17 +++++++++++- ext/mbstring/php_mbregex.c | 8 +++--- ext/mbstring/php_mbregex.h | 2 ++ 5 files changed, 73 insertions(+), 14 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 9736d1f193694..74f582da970a5 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -1070,19 +1070,12 @@ ZEND_TSRMLS_CACHE_UPDATE(); sapi_register_post_entries(mbstr_post_entries); } - REGISTER_LONG_CONSTANT("MB_CASE_UPPER", PHP_UNICODE_CASE_UPPER, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("MB_CASE_LOWER", PHP_UNICODE_CASE_LOWER, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("MB_CASE_TITLE", PHP_UNICODE_CASE_TITLE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("MB_CASE_FOLD", PHP_UNICODE_CASE_FOLD, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("MB_CASE_UPPER_SIMPLE", PHP_UNICODE_CASE_UPPER_SIMPLE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("MB_CASE_LOWER_SIMPLE", PHP_UNICODE_CASE_LOWER_SIMPLE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("MB_CASE_TITLE_SIMPLE", PHP_UNICODE_CASE_TITLE_SIMPLE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("MB_CASE_FOLD_SIMPLE", PHP_UNICODE_CASE_FOLD_SIMPLE, CONST_CS | CONST_PERSISTENT); - #ifdef HAVE_MBREGEX PHP_MINIT(mb_regex) (INIT_FUNC_ARGS_PASSTHRU); #endif + register_mbstring_symbols(module_number); + if (FAILURE == zend_multibyte_set_functions(&php_mb_zend_multibyte_functions)) { return FAILURE; } diff --git a/ext/mbstring/mbstring.stub.php b/ext/mbstring/mbstring.stub.php index 0c4c5db9082c3..9163ac0b7090c 100644 --- a/ext/mbstring/mbstring.stub.php +++ b/ext/mbstring/mbstring.stub.php @@ -2,6 +2,55 @@ /** @generate-class-entries */ +#ifdef HAVE_MBREGEX +/** + * @var string + * @cname php_mb_oniguruma_version + */ +const MB_ONIGURUMA_VERSION = UNKNOWN; +#endif + +/** + * @var int + * @cname PHP_UNICODE_CASE_UPPER + */ +const MB_CASE_UPPER = UNKNOWN; +/** + * @var int + * @cname PHP_UNICODE_CASE_LOWER + */ +const MB_CASE_LOWER = UNKNOWN; +/** + * @var int + * @cname PHP_UNICODE_CASE_TITLE + */ +const MB_CASE_TITLE = UNKNOWN; +/** + * @var int + * @cname PHP_UNICODE_CASE_FOLD + */ +const MB_CASE_FOLD = UNKNOWN; +/** + * @var int + * @cname PHP_UNICODE_CASE_UPPER_SIMPLE + */ +const MB_CASE_UPPER_SIMPLE = UNKNOWN; +/** + * @var int + * @cname PHP_UNICODE_CASE_LOWER_SIMPLE + */ +const MB_CASE_LOWER_SIMPLE = UNKNOWN; +/** + * @var int + * @cname PHP_UNICODE_CASE_TITLE_SIMPLE + */ +const MB_CASE_TITLE_SIMPLE = UNKNOWN; +/** + * @var int + * @cname PHP_UNICODE_CASE_FOLD_SIMPLE + */ +const MB_CASE_FOLD_SIMPLE = UNKNOWN; + /** @refcount 1 */ function mb_language(?string $language = null): string|bool {} diff --git a/ext/mbstring/mbstring_arginfo.h b/ext/mbstring/mbstring_arginfo.h index 9fe44cc316d82..17e49c118f61c 100644 --- a/ext/mbstring/mbstring_arginfo.h +++ b/ext/mbstring/mbstring_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: e553c28d2afd54f1ffcdbb0363aaa2079fabe07d */ + * Stub hash: be25a22e4e90b0a7e7cbcb0b8684c5e691aee0cd */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mb_language, 0, 0, MAY_BE_STRING|MAY_BE_BOOL) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, language, IS_STRING, 1, "null") @@ -490,3 +490,18 @@ static const zend_function_entry ext_functions[] = { #endif ZEND_FE_END }; + +static void register_mbstring_symbols(int module_number) +{ +#if defined(HAVE_MBREGEX) + REGISTER_STRING_CONSTANT("MB_ONIGURUMA_VERSION", php_mb_oniguruma_version, CONST_CS | CONST_PERSISTENT); +#endif + REGISTER_LONG_CONSTANT("MB_CASE_UPPER", PHP_UNICODE_CASE_UPPER, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MB_CASE_LOWER", PHP_UNICODE_CASE_LOWER, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MB_CASE_TITLE", PHP_UNICODE_CASE_TITLE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MB_CASE_FOLD", PHP_UNICODE_CASE_FOLD, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MB_CASE_UPPER_SIMPLE", PHP_UNICODE_CASE_UPPER_SIMPLE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MB_CASE_LOWER_SIMPLE", PHP_UNICODE_CASE_LOWER_SIMPLE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MB_CASE_TITLE_SIMPLE", PHP_UNICODE_CASE_TITLE_SIMPLE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MB_CASE_FOLD_SIMPLE", PHP_UNICODE_CASE_FOLD_SIMPLE, CONST_CS | CONST_PERSISTENT); +} diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c index 1cedee5d79e40..5865268804402 100644 --- a/ext/mbstring/php_mbregex.c +++ b/ext/mbstring/php_mbregex.c @@ -46,6 +46,8 @@ typedef void OnigMatchParam; ZEND_EXTERN_MODULE_GLOBALS(mbstring) +char php_mb_oniguruma_version[256]; + struct _zend_mb_regex_globals { OnigEncoding default_mbctype; OnigEncoding current_mbctype; @@ -110,13 +112,11 @@ void php_mb_regex_globals_free(zend_mb_regex_globals *pglobals) /* {{{ PHP_MINIT_FUNCTION(mb_regex) */ PHP_MINIT_FUNCTION(mb_regex) { - char version[256]; - onig_init(); - snprintf(version, sizeof(version), "%d.%d.%d", + snprintf(php_mb_oniguruma_version, sizeof(php_mb_oniguruma_version), "%d.%d.%d", ONIGURUMA_VERSION_MAJOR, ONIGURUMA_VERSION_MINOR, ONIGURUMA_VERSION_TEENY); - REGISTER_STRING_CONSTANT("MB_ONIGURUMA_VERSION", version, CONST_CS | CONST_PERSISTENT); + return SUCCESS; } /* }}} */ diff --git a/ext/mbstring/php_mbregex.h b/ext/mbstring/php_mbregex.h index b4748582e9144..18a762d5a6142 100644 --- a/ext/mbstring/php_mbregex.h +++ b/ext/mbstring/php_mbregex.h @@ -30,6 +30,8 @@ PHP_RINIT_FUNCTION(mb_regex); PHP_RSHUTDOWN_FUNCTION(mb_regex); PHP_MINFO_FUNCTION(mb_regex); +extern char php_mb_oniguruma_version[256]; + typedef struct _zend_mb_regex_globals zend_mb_regex_globals; zend_mb_regex_globals *php_mb_regex_globals_alloc(void); From 1453dde423031f99dd26211cb31b0213a47493a2 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 23 Jun 2022 19:08:44 +0200 Subject: [PATCH 070/440] Remove zend_shared_alloc_pages declaration that was never implemented (#8852) --- ext/opcache/zend_shared_alloc.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/opcache/zend_shared_alloc.h b/ext/opcache/zend_shared_alloc.h index de5012b2204ad..1caf678e36fe4 100644 --- a/ext/opcache/zend_shared_alloc.h +++ b/ext/opcache/zend_shared_alloc.h @@ -131,7 +131,6 @@ int zend_shared_alloc_startup(size_t requested_size, size_t reserved_size); void zend_shared_alloc_shutdown(void); /* allocate shared memory block */ -void *zend_shared_alloc_pages(size_t requested_size); void *zend_shared_alloc(size_t size); /** From 50a3cb7cea370feaf2233c793e80af74a581d70a Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 23 Jun 2022 19:09:48 +0200 Subject: [PATCH 071/440] Get rid of duplicated rotr3 implementation (#8853) --- ext/opcache/zend_shared_alloc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index ad6b69b34613e..7f820fcdc27b0 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -362,12 +362,17 @@ void *zend_shared_alloc(size_t size) return NULL; } +static zend_always_inline zend_ulong zend_rotr3(zend_ulong key) +{ + return (key >> 3) | (key << ((sizeof(key) * 8) - 3)); +} + int zend_shared_memdup_size(void *source, size_t size) { void *old_p; zend_ulong key = (zend_ulong)source; - key = (key >> 3) | (key << ((sizeof(key) * 8) - 3)); /* key = _rotr(key, 3);*/ + key = zend_rotr3(key); if ((old_p = zend_hash_index_find_ptr(&ZCG(xlat_table), key)) != NULL) { /* we already duplicated this pointer */ return 0; @@ -383,7 +388,7 @@ static zend_always_inline void *_zend_shared_memdup(void *source, size_t size, b if (get_xlat) { key = (zend_ulong)source; - key = (key >> 3) | (key << ((sizeof(key) * 8) - 3)); /* key = _rotr(key, 3);*/ + key = zend_rotr3(key); if ((old_p = zend_hash_index_find_ptr(&ZCG(xlat_table), key)) != NULL) { /* we already duplicated this pointer */ return old_p; @@ -395,7 +400,7 @@ static zend_always_inline void *_zend_shared_memdup(void *source, size_t size, b if (set_xlat) { if (!get_xlat) { key = (zend_ulong)source; - key = (key >> 3) | (key << ((sizeof(key) * 8) - 3)); /* key = _rotr(key, 3);*/ + key = zend_rotr3(key); } zend_hash_index_add_new_ptr(&ZCG(xlat_table), key, retval); } @@ -535,7 +540,7 @@ void zend_shared_alloc_register_xlat_entry(const void *old, const void *new) { zend_ulong key = (zend_ulong)old; - key = (key >> 3) | (key << ((sizeof(key) * 8) - 3)); /* key = _rotr(key, 3);*/ + key = zend_rotr3(key); zend_hash_index_add_new_ptr(&ZCG(xlat_table), key, (void*)new); } @@ -544,7 +549,7 @@ void *zend_shared_alloc_get_xlat_entry(const void *old) void *retval; zend_ulong key = (zend_ulong)old; - key = (key >> 3) | (key << ((sizeof(key) * 8) - 3)); /* key = _rotr(key, 3);*/ + key = zend_rotr3(key); if ((retval = zend_hash_index_find_ptr(&ZCG(xlat_table), key)) == NULL) { return NULL; } From 45210b47294da6aafee7ca0a1b80db1c76fe4433 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Jun 2022 15:06:48 +0200 Subject: [PATCH 072/440] Fix segfault when calling from/tryFrom on empty enum --- Zend/tests/enum/empty-from.phpt | 12 ++++++++++++ Zend/zend_enum.c | 4 ++++ 2 files changed, 16 insertions(+) create mode 100644 Zend/tests/enum/empty-from.phpt diff --git a/Zend/tests/enum/empty-from.phpt b/Zend/tests/enum/empty-from.phpt new file mode 100644 index 0000000000000..db42c78ed31c7 --- /dev/null +++ b/Zend/tests/enum/empty-from.phpt @@ -0,0 +1,12 @@ +--TEST-- +Empty enum with from/tryFrom doens't segfault +--FILE-- + +--EXPECT-- +NULL diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index a4a450d22fba6..8c8c7294e5c47 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -281,6 +281,9 @@ ZEND_API zend_result zend_enum_get_case_by_value(zend_object **result, zend_clas return FAILURE; } } + if (!ce->backed_enum_table) { + goto not_found; + } zval *case_name_zv; if (ce->enum_backing_type == IS_LONG) { @@ -292,6 +295,7 @@ ZEND_API zend_result zend_enum_get_case_by_value(zend_object **result, zend_clas } if (case_name_zv == NULL) { +not_found: if (try) { *result = NULL; return SUCCESS; From 912c22cca0477a60507a957a835eccedfe1d00fe Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Jun 2022 15:07:30 +0200 Subject: [PATCH 073/440] Fix segfault when using preloaded enums --- Zend/zend_enum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index 8c8c7294e5c47..2911efa8e892c 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -199,7 +199,7 @@ zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) zend_string *name; zval *val; - ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(&ce->constants_table, name, val) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(CE_CONSTANTS_TABLE(ce), name, val) { zend_class_constant *c = Z_PTR_P(val); if ((ZEND_CLASS_CONST_FLAGS(c) & ZEND_CLASS_CONST_IS_CASE) == 0) { continue; From d9e1871c85edd96cf5bc1f7e2bed49fe415e14dc Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Jun 2022 15:14:16 +0200 Subject: [PATCH 074/440] Fix leak of backed_enum_table with preloading --- Zend/zend_enum.c | 1 + Zend/zend_execute_API.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index 2911efa8e892c..7e8654942f216 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -187,6 +187,7 @@ void zend_enum_add_interfaces(zend_class_entry *ce) zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) { ZEND_ASSERT(ce->ce_flags & ZEND_ACC_ENUM); + ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_IMMUTABLE)); ZEND_ASSERT(ce->type == ZEND_USER_CLASS); uint32_t backing_type = ce->enum_backing_type; diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index e203556a8ecd7..9822ef692a83d 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -346,6 +346,12 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) } } + if (ce->type == ZEND_USER_CLASS && ce->backed_enum_table) { + ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_IMMUTABLE)); + zend_hash_release(ce->backed_enum_table); + ce->backed_enum_table = NULL; + } + if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) { zend_op_array *op_array; ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { From bc03deec278923045235f470b4969bab358feaa2 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Jun 2022 16:16:13 +0200 Subject: [PATCH 075/440] Fix magic constants in backed enum values Fix GH-8777 --- Zend/tests/enum/magic-constants.phpt | 14 ++++++++++++++ Zend/zend_compile.c | 3 +++ 2 files changed, 17 insertions(+) create mode 100644 Zend/tests/enum/magic-constants.phpt diff --git a/Zend/tests/enum/magic-constants.phpt b/Zend/tests/enum/magic-constants.phpt new file mode 100644 index 0000000000000..7a11d7785d7a4 --- /dev/null +++ b/Zend/tests/enum/magic-constants.phpt @@ -0,0 +1,14 @@ +--TEST-- +Backed enums can contain magic constants +--FILE-- +value, "\n"; + +?> +--EXPECTF-- +%smagic-constants.php diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c18c6db7e67da..3f505ed977806 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -10474,6 +10474,9 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ case ZEND_AST_NAMED_ARG: zend_eval_const_expr(&ast->child[1]); return; + case ZEND_AST_CONST_ENUM_INIT: + zend_eval_const_expr(&ast->child[2]); + return; default: return; } From b7f0950ffe8cf1fb37e57b40977a0416c39fa7f9 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 1 Mar 2022 18:53:23 +0100 Subject: [PATCH 076/440] Add test coverage job --- .github/workflows/nightly.yml | 31 ++++++++++++++++++++++ azure-pipelines.yml | 5 ---- azure/coverage_job.yml | 48 ----------------------------------- 3 files changed, 31 insertions(+), 53 deletions(-) delete mode 100644 azure/coverage_job.yml diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 4d347323e89b3..16b99af3f730d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -153,3 +153,34 @@ jobs: -d opcache.jit=1205 - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files + COVERAGE_DEBUG_NTS: + runs-on: ubuntu-20.04 + steps: + - name: git checkout + uses: actions/checkout@v2 + - name: Create mssql container + uses: ./.github/actions/mssql + - name: apt + uses: ./.github/actions/apt-x64 + - name: Install gcovr + run: sudo -H pip install gcovr + - name: ./configure + uses: ./.github/actions/configure-x64 + with: + configurationParameters: --enable-debug --disable-zts --enable-gcov + - name: make + run: make -j$(/usr/bin/nproc) >/dev/null + - name: make install + uses: ./.github/actions/install-linux + - name: Setup + uses: ./.github/actions/setup-x64 + # We only test with OpCache, the difference in coverage is negligible + - name: Test OpCache + uses: ./.github/actions/test-linux + with: + runTestsParameters: >- + -d zend_extension=opcache.so + -d opcache.enable_cli=1 + - name: Upload Test Coverage to Codecov.io + if: always() + run: bash <(curl -s https://codecov.io/bash) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e896c993896de..ce1546f8343fd 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -49,11 +49,6 @@ jobs: CFLAGS='-fsanitize=undefined,address -fno-sanitize-recover -DZEND_TRACK_ARENA_ALLOC' LDFLAGS='-fsanitize=undefined,address' timeoutInMinutes: 90 - - template: azure/coverage_job.yml - parameters: - configurationName: COVERAGE_DEBUG_ZTS - configurationParameters: '--enable-debug --disable-zts' - timeoutInMinutes: 90 - template: azure/file_cache_job.yml parameters: configurationName: DEBUG_NTS_FILE_CACHE diff --git a/azure/coverage_job.yml b/azure/coverage_job.yml deleted file mode 100644 index 20ce581fcbbd7..0000000000000 --- a/azure/coverage_job.yml +++ /dev/null @@ -1,48 +0,0 @@ -parameters: - configurationName: '' - configurationParameters: '' - runTestsParameters: '' - timeoutInMinutes: 60 - -jobs: - - job: ${{ parameters.configurationName }} - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - pool: - vmImage: 'ubuntu-20.04' - steps: - - template: apt.yml - - script: | - sudo -H pip install gcovr - displayName: 'Install gcovr' - - template: configure.yml - parameters: - configurationParameters: --enable-gcov ${{ parameters.configurationParameters }} - - script: make -j$(/usr/bin/nproc) >/dev/null - displayName: 'Make Build' - - template: install.yml - - template: setup.yml - - template: test.yml - parameters: - configurationName: ${{ parameters.configurationName }} - runTestsParameters: ${{ parameters.runTestsParameters }} - - template: test.yml - parameters: - configurationName: ${{ parameters.configurationName }} - runTestsName: 'OpCache' - runTestsParameters: >- - ${{ parameters.runTestsParameters }} - -d zend_extension=opcache.so - - script: bash <(curl -s https://codecov.io/bash) - displayName: 'Upload ${{ parameters.configurationName }} Test Coverage to Codecov.io' - condition: or(succeeded(), failed()) - - script: | - make gcovr-xml - mv gcovr.xml coverage.xml - displayName: 'Generate ${{ parameters.configurationName }} Test Coverage Cobertura XML Report' - condition: or(succeeded(), failed()) - - task: PublishCodeCoverageResults@1 - inputs: - codeCoverageTool: 'Cobertura' - summaryFileLocation: coverage.xml - displayName: 'Publish ${{ parameters.configurationName }} Test Coverage' - condition: or(succeeded(), failed()) From 20638dba3f8df5ba4b1f8ae69584a8a55ecfce60 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 24 Jun 2022 03:38:29 +0100 Subject: [PATCH 077/440] Use the passed 'this' pointer instead of ZEND_THIS (#8854) Removes the horrible hack usage of defining execute_data to be able to use ZEND_THING --- ext/spl/spl_directory.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 9de3445b7f43d..766828ef80204 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1968,7 +1968,6 @@ static zend_result spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesys return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, intern->u.file.escape, NULL); } if (intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) { - zend_execute_data *execute_data = EG(current_execute_data); spl_filesystem_file_free_line(intern); if (php_stream_eof(intern->u.file.stream)) { @@ -1977,14 +1976,14 @@ static zend_result spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesys } return FAILURE; } - zend_call_method_with_0_params(Z_OBJ_P(this_ptr), Z_OBJCE_P(ZEND_THIS), &intern->u.file.func_getCurr, "getCurrentLine", &retval); + zend_call_method_with_0_params(Z_OBJ_P(this_ptr), Z_OBJCE_P(this_ptr), &intern->u.file.func_getCurr, "getCurrentLine", &retval); if (Z_ISUNDEF(retval)) { return FAILURE; } if (Z_TYPE(retval) != IS_STRING) { zend_type_error("%s::getCurrentLine(): Return value must be of type string, %s returned", - ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name), zend_zval_type_name(&retval)); + ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), zend_zval_type_name(&retval)); zval_ptr_dtor(&retval); return FAILURE; } From 13f55d5c1bc6690862f9d3e9b6047e6372646ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Fri, 24 Jun 2022 11:10:41 +0200 Subject: [PATCH 078/440] Use proper grammar in error message Drop period in error messages 2 reasons: - These error messages are not regular sentences. - Having the offending value between parenthesis after the period looks weird. Closes GH-8858. --- ext/bz2/bz2_filter.c | 4 ++-- ext/bz2/tests/bug72447.phpt | 2 +- ext/zlib/zlib_filter.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ext/bz2/bz2_filter.c b/ext/bz2/bz2_filter.c index 7fa0f6b918cdb..fb877e33de21e 100644 --- a/ext/bz2/bz2_filter.c +++ b/ext/bz2/bz2_filter.c @@ -366,7 +366,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi /* How much memory to allocate (1 - 9) x 100kb */ zend_long blocks = zval_get_long(tmpzval); if (blocks < 1 || blocks > 9) { - php_error_docref(NULL, E_WARNING, "Invalid parameter given for number of blocks to allocate. (" ZEND_LONG_FMT ")", blocks); + php_error_docref(NULL, E_WARNING, "Invalid parameter given for number of blocks to allocate (" ZEND_LONG_FMT ")", blocks); } else { blockSize100k = (int) blocks; } @@ -376,7 +376,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi /* Work Factor (0 - 250) */ zend_long work = zval_get_long(tmpzval); if (work < 0 || work > 250) { - php_error_docref(NULL, E_WARNING, "Invalid parameter given for work factor. (" ZEND_LONG_FMT ")", work); + php_error_docref(NULL, E_WARNING, "Invalid parameter given for work factor (" ZEND_LONG_FMT ")", work); } else { workFactor = (int) work; } diff --git a/ext/bz2/tests/bug72447.phpt b/ext/bz2/tests/bug72447.phpt index 15321042df92e..8a3c93491ecd6 100644 --- a/ext/bz2/tests/bug72447.phpt +++ b/ext/bz2/tests/bug72447.phpt @@ -16,4 +16,4 @@ fclose($fp); unlink('testfile'); ?> --EXPECTF-- -Warning: stream_filter_append(): Invalid parameter given for number of blocks to allocate. (0) in %s%ebug72447.php on line %d +Warning: stream_filter_append(): Invalid parameter given for number of blocks to allocate (0) in %s%ebug72447.php on line %d diff --git a/ext/zlib/zlib_filter.c b/ext/zlib/zlib_filter.c index cdd981afde217..fd644b1e7e991 100644 --- a/ext/zlib/zlib_filter.c +++ b/ext/zlib/zlib_filter.c @@ -327,7 +327,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f /* log-2 base of history window (9 - 15) */ zend_long tmp = zval_get_long(tmpzval); if (tmp < -MAX_WBITS || tmp > MAX_WBITS + 32) { - php_error_docref(NULL, E_WARNING, "Invalid parameter give for window size. (" ZEND_LONG_FMT ")", tmp); + php_error_docref(NULL, E_WARNING, "Invalid parameter given for window size (" ZEND_LONG_FMT ")", tmp); } else { windowBits = tmp; } @@ -359,7 +359,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f /* Memory Level (1 - 9) */ tmp = zval_get_long(tmpzval); if (tmp < 1 || tmp > MAX_MEM_LEVEL) { - php_error_docref(NULL, E_WARNING, "Invalid parameter give for memory level. (" ZEND_LONG_FMT ")", tmp); + php_error_docref(NULL, E_WARNING, "Invalid parameter given for memory level (" ZEND_LONG_FMT ")", tmp); } else { memLevel = tmp; } @@ -369,7 +369,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f /* log-2 base of history window (9 - 15) */ tmp = zval_get_long(tmpzval); if (tmp < -MAX_WBITS || tmp > MAX_WBITS + 16) { - php_error_docref(NULL, E_WARNING, "Invalid parameter give for window size. (" ZEND_LONG_FMT ")", tmp); + php_error_docref(NULL, E_WARNING, "Invalid parameter given for window size (" ZEND_LONG_FMT ")", tmp); } else { windowBits = tmp; } From 76fcd70c13f0c4b66937f381d5313c4f4c4cd548 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sat, 25 Jun 2022 14:55:46 +0200 Subject: [PATCH 079/440] Fix enum preloading again (#8859) --- Zend/zend.h | 1 + Zend/zend_API.h | 23 +++++++++++++++++++++++ Zend/zend_enum.c | 37 +++++++++++++++++++++---------------- Zend/zend_opcode.c | 5 +++++ 4 files changed, 50 insertions(+), 16 deletions(-) diff --git a/Zend/zend.h b/Zend/zend.h index d58c02f4475b4..dc147f760ee0b 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -115,6 +115,7 @@ typedef struct _zend_class_mutable_data { zval *default_properties_table; HashTable *constants_table; uint32_t ce_flags; + HashTable *backed_enum_table; } zend_class_mutable_data; typedef struct _zend_class_dependency { diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 2dbd9bd15d090..5796c4f472ca4 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -321,6 +321,9 @@ typedef struct _zend_fcall_info_cache { #define CE_DEFAULT_PROPERTIES_TABLE(ce) \ zend_class_default_properties_table(ce) +#define CE_BACKED_ENUM_TABLE(ce) \ + zend_class_backed_enum_table(ce) + #define ZEND_FCI_INITIALIZED(fci) ((fci).size != 0) ZEND_API int zend_next_free_module(void); @@ -450,6 +453,26 @@ static zend_always_inline zval *zend_class_default_properties_table(zend_class_e } } +static zend_always_inline void zend_class_set_backed_enum_table(zend_class_entry *ce, HashTable *backed_enum_table) +{ + if (ZEND_MAP_PTR(ce->mutable_data) && ce->type == ZEND_USER_CLASS) { + zend_class_mutable_data *mutable_data = (zend_class_mutable_data*)ZEND_MAP_PTR_GET_IMM(ce->mutable_data); + mutable_data->backed_enum_table = backed_enum_table; + } else { + ce->backed_enum_table = backed_enum_table; + } +} + +static zend_always_inline HashTable *zend_class_backed_enum_table(zend_class_entry *ce) +{ + if (ZEND_MAP_PTR(ce->mutable_data) && ce->type == ZEND_USER_CLASS) { + zend_class_mutable_data *mutable_data = (zend_class_mutable_data*)ZEND_MAP_PTR_GET_IMM(ce->mutable_data); + return mutable_data->backed_enum_table; + } else { + return ce->backed_enum_table; + } +} + ZEND_API void zend_update_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, zval *value); ZEND_API void zend_update_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zval *value); ZEND_API void zend_update_property_null(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length); diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index 7e8654942f216..39e0ad58ee1fd 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -187,14 +187,14 @@ void zend_enum_add_interfaces(zend_class_entry *ce) zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) { ZEND_ASSERT(ce->ce_flags & ZEND_ACC_ENUM); - ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_IMMUTABLE)); ZEND_ASSERT(ce->type == ZEND_USER_CLASS); uint32_t backing_type = ce->enum_backing_type; ZEND_ASSERT(backing_type != IS_UNDEF); - ce->backed_enum_table = emalloc(sizeof(HashTable)); - zend_hash_init(ce->backed_enum_table, 0, NULL, ZVAL_PTR_DTOR, 0); + HashTable *backed_enum_table = emalloc(sizeof(HashTable)); + zend_hash_init(backed_enum_table, 0, NULL, ZVAL_PTR_DTOR, 0); + zend_class_set_backed_enum_table(ce, backed_enum_table); zend_string *enum_class_name = ce->name; @@ -219,7 +219,7 @@ zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) if (ce->enum_backing_type == IS_LONG) { zend_long long_key = Z_LVAL_P(case_value); - zval *existing_case_name = zend_hash_index_find(ce->backed_enum_table, long_key); + zval *existing_case_name = zend_hash_index_find(backed_enum_table, long_key); if (existing_case_name) { zend_throw_error(NULL, "Duplicate value in enum %s for cases %s and %s", ZSTR_VAL(enum_class_name), @@ -227,11 +227,11 @@ zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) ZSTR_VAL(name)); goto failure; } - zend_hash_index_add_new(ce->backed_enum_table, long_key, case_name); + zend_hash_index_add_new(backed_enum_table, long_key, case_name); } else { ZEND_ASSERT(ce->enum_backing_type == IS_STRING); zend_string *string_key = Z_STR_P(case_value); - zval *existing_case_name = zend_hash_find(ce->backed_enum_table, string_key); + zval *existing_case_name = zend_hash_find(backed_enum_table, string_key); if (existing_case_name != NULL) { zend_throw_error(NULL, "Duplicate value in enum %s for cases %s and %s", ZSTR_VAL(enum_class_name), @@ -239,15 +239,15 @@ zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) ZSTR_VAL(name)); goto failure; } - zend_hash_add_new(ce->backed_enum_table, string_key, case_name); + zend_hash_add_new(backed_enum_table, string_key, case_name); } } ZEND_HASH_FOREACH_END(); return SUCCESS; failure: - zend_hash_release(ce->backed_enum_table); - ce->backed_enum_table = NULL; + zend_hash_release(backed_enum_table); + zend_class_set_backed_enum_table(ce, NULL); return FAILURE; } @@ -282,17 +282,19 @@ ZEND_API zend_result zend_enum_get_case_by_value(zend_object **result, zend_clas return FAILURE; } } - if (!ce->backed_enum_table) { + + HashTable *backed_enum_table = CE_BACKED_ENUM_TABLE(ce); + if (!backed_enum_table) { goto not_found; } zval *case_name_zv; if (ce->enum_backing_type == IS_LONG) { - case_name_zv = zend_hash_index_find(ce->backed_enum_table, long_key); + case_name_zv = zend_hash_index_find(backed_enum_table, long_key); } else { ZEND_ASSERT(ce->enum_backing_type == IS_STRING); ZEND_ASSERT(string_key != NULL); - case_name_zv = zend_hash_find(ce->backed_enum_table, string_key); + case_name_zv = zend_hash_find(backed_enum_table, string_key); } if (case_name_zv == NULL) { @@ -496,8 +498,9 @@ ZEND_API zend_class_entry *zend_register_internal_enum( ce->ce_flags |= ZEND_ACC_ENUM; ce->enum_backing_type = type; if (type != IS_UNDEF) { - ce->backed_enum_table = pemalloc(sizeof(HashTable), 1); - zend_hash_init(ce->backed_enum_table, 0, NULL, ZVAL_PTR_DTOR, 1); + HashTable *backed_enum_table = pemalloc(sizeof(HashTable), 1); + zend_hash_init(backed_enum_table, 0, NULL, ZVAL_PTR_DTOR, 1); + zend_class_set_backed_enum_table(ce, backed_enum_table); } zend_enum_register_props(ce); @@ -562,12 +565,14 @@ ZEND_API void zend_enum_add_case(zend_class_entry *ce, zend_string *case_name, z zval_make_interned_string(value); } + HashTable *backed_enum_table = CE_BACKED_ENUM_TABLE(ce); + zval case_name_zv; ZVAL_STR(&case_name_zv, case_name); if (Z_TYPE_P(value) == IS_LONG) { - zend_hash_index_add_new(ce->backed_enum_table, Z_LVAL_P(value), &case_name_zv); + zend_hash_index_add_new(backed_enum_table, Z_LVAL_P(value), &case_name_zv); } else { - zend_hash_add_new(ce->backed_enum_table, Z_STR_P(value), &case_name_zv); + zend_hash_add_new(backed_enum_table, Z_STR_P(value), &case_name_zv); } } else { ZEND_ASSERT(ce->enum_backing_type == IS_UNDEF); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 86cf4c6f9f118..93f70462ad8d3 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -275,6 +275,11 @@ ZEND_API void zend_cleanup_mutable_class_data(zend_class_entry *ce) mutable_data->default_properties_table = NULL; } + if (mutable_data->backed_enum_table) { + zend_hash_release(mutable_data->backed_enum_table); + mutable_data->backed_enum_table = NULL; + } + ZEND_MAP_PTR_SET_IMM(ce->mutable_data, NULL); } } From 973c3f6e241227ffc14c3608c774d7636b798cec Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Fri, 24 Jun 2022 11:13:49 +0100 Subject: [PATCH 080/440] Fixed #80047: DatePeriod doesn't warn with custom DateTimeImmutable --- NEWS | 4 ++++ ext/date/php_date.c | 14 ++++++++++++ ext/date/tests/bug80042.phpt | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 ext/date/tests/bug80042.phpt diff --git a/NEWS b/NEWS index 3474bfa63812f..c5bb9757b26e7 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2022, PHP 8.0.22 +- Date: + . Fixed bug #80047 (DatePeriod doesn't warn with custom DateTimeImmutable). + (Derick) + - GD: . Fixed bug GH-8848 (imagecopyresized() error refers to the wrong argument). (cmb) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index e57c3f43d3a48..3c26c11e1035d 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -4227,6 +4227,20 @@ PHP_METHOD(DatePeriod, __construct) } dpobj->start_ce = date_ce_date; } else { + /* Sanity checks */ + if (start && Z_OBJCE_P(start) != date_ce_date && Z_OBJCE_P(start) != date_ce_immutable) { + zend_string *func = get_active_function_or_method_name(); + zend_throw_error(zend_ce_exception, "%s(): Class of start date must be exactly DateTime or DateTimeImmutable, object of class %s provided", ZSTR_VAL(func), ZSTR_VAL(Z_OBJCE_P(start)->name)); + zend_string_release(func); + RETURN_THROWS(); + } + if (end && Z_OBJCE_P(end) != date_ce_date && Z_OBJCE_P(end) != date_ce_immutable) { + zend_string *func = get_active_function_or_method_name(); + zend_throw_error(zend_ce_exception, "%s(): Class of end date must be exactly DateTime or DateTimeImmutable, object of class %s provided", ZSTR_VAL(func), ZSTR_VAL(Z_OBJCE_P(end)->name)); + zend_string_release(func); + RETURN_THROWS(); + } + /* init */ php_interval_obj *intobj = Z_PHPINTERVAL_P(interval); diff --git a/ext/date/tests/bug80042.phpt b/ext/date/tests/bug80042.phpt new file mode 100644 index 0000000000000..8356d8693bafd --- /dev/null +++ b/ext/date/tests/bug80042.phpt @@ -0,0 +1,41 @@ +--TEST-- +Bug #80047: DatePeriod doesn't support custom DateTimeImmutable +--INI-- +date.timezone=UTC +--FILE-- +getMessage(), "\n"; + } +} +?> +--EXPECT-- +DatePeriod::__construct(): Class of end date must be exactly DateTime or DateTimeImmutable, object of class CustomDateTime provided +DatePeriod::__construct(): Class of start date must be exactly DateTime or DateTimeImmutable, object of class CustomDateTime provided +DatePeriod::__construct(): Class of start date must be exactly DateTime or DateTimeImmutable, object of class CustomDateTime provided +DatePeriod::__construct(): Class of end date must be exactly DateTime or DateTimeImmutable, object of class CustomDateTimeImmutable provided +DatePeriod::__construct(): Class of start date must be exactly DateTime or DateTimeImmutable, object of class CustomDateTimeImmutable provided +DatePeriod::__construct(): Class of start date must be exactly DateTime or DateTimeImmutable, object of class CustomDateTimeImmutable provided +DatePeriod::__construct(): Class of start date must be exactly DateTime or DateTimeImmutable, object of class CustomDateTime provided From 3b92a96610d7bf211424b6bc72097fb1c8569b29 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 26 Jun 2022 01:00:19 +0200 Subject: [PATCH 081/440] Convert return type of various object handlers from int to zend_result (#8755) --- UPGRADING.INTERNALS | 5 +++++ Zend/zend_closures.c | 2 +- Zend/zend_object_handlers.c | 4 ++-- Zend/zend_object_handlers.h | 12 ++++++------ Zend/zend_weakrefs.c | 2 +- ext/com_dotnet/com_handlers.c | 4 ++-- ext/com_dotnet/com_saproxy.c | 4 ++-- ext/curl/curl_private.h | 2 +- ext/curl/interface.c | 2 +- ext/ffi/ffi.c | 10 +++++----- ext/gmp/gmp.c | 6 +++--- ext/intl/resourcebundle/resourcebundle_class.c | 2 +- ext/simplexml/simplexml.c | 14 +++++++------- ext/spl/spl_array.c | 2 +- ext/spl/spl_directory.c | 2 +- ext/spl/spl_dllist.c | 2 +- ext/spl/spl_fixedarray.c | 2 +- ext/spl/spl_heap.c | 2 +- ext/tidy/tidy.c | 8 ++++---- 19 files changed, 46 insertions(+), 41 deletions(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index e411bdba99031..c752ce4823de6 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -32,6 +32,11 @@ PHP 8.2 INTERNALS UPGRADE NOTES * Deprecated zend_atoi() and zend_atol(). Use ZEND_STRTOL() for general purpose string to long conversion, or a variant of zend_ini_parse_quantity() for parsing ini quantities. +* The return types of the following object handlers has changed from int to zend_result + - zend_object_cast_t + - zend_object_count_elements_t + - zend_object_get_closure_t + - zend_object_do_operation_t ======================== 2. Build system changes diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index e141d0956dc95..1dd7715e55b6a 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -523,7 +523,7 @@ static zend_object *zend_closure_clone(zend_object *zobject) /* {{{ */ } /* }}} */ -int zend_closure_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) /* {{{ */ +static zend_result zend_closure_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) /* {{{ */ { zend_closure *closure = (zend_closure*)obj; diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 7d589356ac1d1..a8cd6dc11f646 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1841,7 +1841,7 @@ ZEND_API zend_string *zend_std_get_class_name(const zend_object *zobj) /* {{{ */ } /* }}} */ -ZEND_API int zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, int type) /* {{{ */ +ZEND_API zend_result zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, int type) /* {{{ */ { switch (type) { case IS_STRING: { @@ -1871,7 +1871,7 @@ ZEND_API int zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, } /* }}} */ -ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) /* {{{ */ +ZEND_API zend_result zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) /* {{{ */ { zend_class_entry *ce = obj->ce; zval *func = zend_hash_find_known_hash(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE)); diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 53eef829282ce..94b7f52cba3aa 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -144,17 +144,17 @@ typedef int (*zend_object_compare_t)(zval *object1, zval *object2); /* Cast an object to some other type. * readobj and retval must point to distinct zvals. */ -typedef int (*zend_object_cast_t)(zend_object *readobj, zval *retval, int type); +typedef zend_result (*zend_object_cast_t)(zend_object *readobj, zval *retval, int type); /* updates *count to hold the number of elements present and returns SUCCESS. * Returns FAILURE if the object does not have any sense of overloaded dimensions */ -typedef int (*zend_object_count_elements_t)(zend_object *object, zend_long *count); +typedef zend_result (*zend_object_count_elements_t)(zend_object *object, zend_long *count); -typedef int (*zend_object_get_closure_t)(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only); +typedef zend_result (*zend_object_get_closure_t)(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only); typedef HashTable *(*zend_object_get_gc_t)(zend_object *object, zval **table, int *n); -typedef int (*zend_object_do_operation_t)(zend_uchar opcode, zval *result, zval *op1, zval *op2); +typedef zend_result (*zend_object_do_operation_t)(zend_uchar opcode, zval *result, zval *op1, zval *op2); struct _zend_object_handlers { /* offset of real object header (usually zero) */ @@ -209,7 +209,7 @@ ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce ZEND_API HashTable *zend_std_get_properties(zend_object *object); ZEND_API HashTable *zend_std_get_gc(zend_object *object, zval **table, int *n); ZEND_API HashTable *zend_std_get_debug_info(zend_object *object, int *is_temp); -ZEND_API int zend_std_cast_object_tostring(zend_object *object, zval *writeobj, int type); +ZEND_API zend_result zend_std_cast_object_tostring(zend_object *object, zval *writeobj, int type); ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot); ZEND_API zval *zend_std_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv); ZEND_API zval *zend_std_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot); @@ -222,7 +222,7 @@ ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset); ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key); ZEND_API zend_string *zend_std_get_class_name(const zend_object *zobj); ZEND_API int zend_std_compare_objects(zval *o1, zval *o2); -ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only); +ZEND_API zend_result zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only); ZEND_API void rebuild_object_properties(zend_object *zobj); ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj); diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index 9d530047f902f..14e8bfc599d45 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -424,7 +424,7 @@ static void zend_weakmap_unset_dimension(zend_object *object, zval *offset) zend_weakref_unregister(obj_addr, ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP), 1); } -static int zend_weakmap_count_elements(zend_object *object, zend_long *count) +static zend_result zend_weakmap_count_elements(zend_object *object, zend_long *count) { zend_weakmap *wm = zend_weakmap_from(object); *count = zend_hash_num_elements(&wm->ht); diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index bb45e98e90ed0..db96118ea31c6 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -429,7 +429,7 @@ static int com_objects_compare(zval *object1, zval *object2) return ret; } -static int com_object_cast(zend_object *readobj, zval *writeobj, int type) +static zend_result com_object_cast(zend_object *readobj, zval *writeobj, int type) { php_com_dotnet_object *obj; VARIANT v; @@ -490,7 +490,7 @@ static int com_object_cast(zend_object *readobj, zval *writeobj, int type) return zend_std_cast_object_tostring(readobj, writeobj, type); } -static int com_object_count(zend_object *object, zend_long *count) +static zend_result com_object_count(zend_object *object, zend_long *count) { php_com_dotnet_object *obj; LONG ubound = 0, lbound = 0; diff --git a/ext/com_dotnet/com_saproxy.c b/ext/com_dotnet/com_saproxy.c index 4e19f6e78e5d2..6ad4680c0fe65 100644 --- a/ext/com_dotnet/com_saproxy.c +++ b/ext/com_dotnet/com_saproxy.c @@ -332,12 +332,12 @@ static int saproxy_objects_compare(zval *object1, zval *object2) return -1; } -static int saproxy_object_cast(zend_object *readobj, zval *writeobj, int type) +static zend_result saproxy_object_cast(zend_object *readobj, zval *writeobj, int type) { return FAILURE; } -static int saproxy_count_elements(zend_object *object, zend_long *count) +static zend_result saproxy_count_elements(zend_object *object, zend_long *count) { php_com_saproxy *proxy = (php_com_saproxy*) object; LONG ubound, lbound; diff --git a/ext/curl/curl_private.h b/ext/curl/curl_private.h index edf19c86f8354..ca3024bcd4926 100644 --- a/ext/curl/curl_private.h +++ b/ext/curl/curl_private.h @@ -159,6 +159,6 @@ static inline php_curlsh *curl_share_from_obj(zend_object *obj) { void curl_multi_register_handlers(void); void curl_share_register_handlers(void); void curlfile_register_class(void); -int curl_cast_object(zend_object *obj, zval *result, int type); +zend_result curl_cast_object(zend_object *obj, zval *result, int type); #endif /* _PHP_CURL_PRIVATE_H */ diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 0d574a605a6d7..0e9aae4b76458 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -1443,7 +1443,7 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n) return zend_std_get_properties(object); } -int curl_cast_object(zend_object *obj, zval *result, int type) +zend_result curl_cast_object(zend_object *obj, zval *result, int type) { if (type == IS_LONG) { /* For better backward compatibility, make (int) $curl_handle return the object ID, diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 7080a5141a4d1..cb82c3a3c3118 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -1081,7 +1081,7 @@ static zval *zend_ffi_cdata_set(zend_object *obj, zend_string *member, zval *val } /* }}} */ -static int zend_ffi_cdata_cast_object(zend_object *readobj, zval *writeobj, int type) /* {{{ */ +static zend_result zend_ffi_cdata_cast_object(zend_object *readobj, zval *writeobj, int type) /* {{{ */ { if (type == IS_STRING) { zend_ffi_cdata *cdata = (zend_ffi_cdata*)readobj; @@ -1703,7 +1703,7 @@ static int zend_ffi_cdata_compare_objects(zval *o1, zval *o2) /* {{{ */ } /* }}} */ -static int zend_ffi_cdata_count_elements(zend_object *obj, zend_long *count) /* {{{ */ +static zend_result zend_ffi_cdata_count_elements(zend_object *obj, zend_long *count) /* {{{ */ { zend_ffi_cdata *cdata = (zend_ffi_cdata*)obj; zend_ffi_type *type = ZEND_FFI_TYPE(cdata->type); @@ -1774,7 +1774,7 @@ static zend_object* zend_ffi_add(zend_ffi_cdata *base_cdata, zend_ffi_type *base } /* }}} */ -static int zend_ffi_cdata_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2) /* {{{ */ +static zend_result zend_ffi_cdata_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2) /* {{{ */ { zend_long offset; @@ -2056,7 +2056,7 @@ static HashTable *zend_ffi_cdata_get_debug_info(zend_object *obj, int *is_temp) } /* }}} */ -static int zend_ffi_cdata_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) /* {{{ */ +static zend_result zend_ffi_cdata_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only) /* {{{ */ { zend_ffi_cdata *cdata = (zend_ffi_cdata*)obj; zend_ffi_type *type = ZEND_FFI_TYPE(cdata->type); @@ -5021,7 +5021,7 @@ static HashTable *zend_fake_get_gc(zend_object *ob, zval **table, int *n) /* {{{ } /* }}} */ -static int zend_fake_cast_object(zend_object *obj, zval *result, int type) +static zend_result zend_fake_cast_object(zend_object *obj, zval *result, int type) { switch (type) { case _IS_BOOL: diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 2cb43c371ae2a..39d0da5d154af 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -276,7 +276,7 @@ static inline void gmp_create(zval *target, mpz_ptr *gmpnum_target) /* {{{ */ } /* }}} */ -static int gmp_cast_object(zend_object *readobj, zval *writeobj, int type) /* {{{ */ +static zend_result gmp_cast_object(zend_object *readobj, zval *writeobj, int type) /* {{{ */ { mpz_ptr gmpnum; switch (type) { @@ -372,7 +372,7 @@ static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zva } \ return SUCCESS; -static int gmp_do_operation_ex(zend_uchar opcode, zval *result, zval *op1, zval *op2) /* {{{ */ +static zend_result gmp_do_operation_ex(zend_uchar opcode, zval *result, zval *op1, zval *op2) /* {{{ */ { switch (opcode) { case ZEND_ADD: @@ -409,7 +409,7 @@ static int gmp_do_operation_ex(zend_uchar opcode, zval *result, zval *op1, zval } /* }}} */ -static int gmp_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2) /* {{{ */ +static zend_result gmp_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2) /* {{{ */ { zval op1_copy; int retval; diff --git a/ext/intl/resourcebundle/resourcebundle_class.c b/ext/intl/resourcebundle/resourcebundle_class.c index aa4671a1b1310..5e1e9e5312e29 100644 --- a/ext/intl/resourcebundle/resourcebundle_class.c +++ b/ext/intl/resourcebundle/resourcebundle_class.c @@ -252,7 +252,7 @@ PHP_FUNCTION( resourcebundle_get ) /* }}} */ /* {{{ resourcebundle_array_count */ -int resourcebundle_array_count(zend_object *object, zend_long *count) +static zend_result resourcebundle_array_count(zend_object *object, zend_long *count) { ResourceBundle_object *rb = php_intl_resourcebundle_fetch_object(object); diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index a57929c5f44cf..763886730158b 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -52,7 +52,7 @@ static zval *php_sxe_iterator_current_data(zend_object_iterator *iter); static void php_sxe_iterator_current_key(zend_object_iterator *iter, zval *key); static void php_sxe_iterator_move_forward(zend_object_iterator *iter); static void php_sxe_iterator_rewind(zend_object_iterator *iter); -static int sxe_object_cast_ex(zend_object *readobj, zval *writeobj, int type); +static zend_result sxe_object_cast_ex(zend_object *readobj, zval *writeobj, int type); /* {{{ _node_as_zval() */ static void _node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE_ITER itertype, char *name, const xmlChar *nsprefix, int isprefix) @@ -1801,7 +1801,7 @@ PHP_METHOD(SimpleXMLElement, addAttribute) /* }}} */ /* {{{ cast_object() */ -static int cast_object(zval *object, int type, char *contents) +static zend_result cast_object(zval *object, int type, char *contents) { if (contents) { ZVAL_STRINGL(object, contents, strlen(contents)); @@ -1833,12 +1833,12 @@ static int cast_object(zval *object, int type, char *contents) /* }}} */ /* {{{ sxe_object_cast() */ -static int sxe_object_cast_ex(zend_object *readobj, zval *writeobj, int type) +static zend_result sxe_object_cast_ex(zend_object *readobj, zval *writeobj, int type) { php_sxe_object *sxe; xmlChar *contents = NULL; xmlNodePtr node; - int rv; + zend_result rv; sxe = php_sxe_fetch_object(readobj); @@ -1882,7 +1882,7 @@ static int sxe_object_cast_ex(zend_object *readobj, zval *writeobj, int type) /* }}} */ /* {{{ Variant of sxe_object_cast_ex that handles overwritten __toString() method */ -static int sxe_object_cast(zend_object *readobj, zval *writeobj, int type) +static zend_result sxe_object_cast(zend_object *readobj, zval *writeobj, int type) { if (type == IS_STRING && zend_std_cast_object_tostring(readobj, writeobj, IS_STRING) == SUCCESS @@ -1908,7 +1908,7 @@ PHP_METHOD(SimpleXMLElement, __toString) } /* }}} */ -static int php_sxe_count_elements_helper(php_sxe_object *sxe, zend_long *count) /* {{{ */ +static zend_result php_sxe_count_elements_helper(php_sxe_object *sxe, zend_long *count) /* {{{ */ { xmlNodePtr node; zval data; @@ -1935,7 +1935,7 @@ static int php_sxe_count_elements_helper(php_sxe_object *sxe, zend_long *count) } /* }}} */ -static int sxe_count_elements(zend_object *object, zend_long *count) /* {{{ */ +static zend_result sxe_count_elements(zend_object *object, zend_long *count) /* {{{ */ { php_sxe_object *intern; intern = php_sxe_fetch_object(object); diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index db9a4f6f6b3ee..f4b1f8c427945 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -1276,7 +1276,7 @@ static zend_long spl_array_object_count_elements_helper(spl_array_object *intern } } /* }}} */ -int spl_array_object_count_elements(zend_object *object, zend_long *count) /* {{{ */ +static zend_result spl_array_object_count_elements(zend_object *object, zend_long *count) /* {{{ */ { spl_array_object *intern = spl_array_from_obj(object); diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 766828ef80204..382ec91cc235f 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1854,7 +1854,7 @@ zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zva /* }}} */ /* {{{ spl_filesystem_object_cast */ -static int spl_filesystem_object_cast(zend_object *readobj, zval *writeobj, int type) +static zend_result spl_filesystem_object_cast(zend_object *readobj, zval *writeobj, int type) { spl_filesystem_object *intern = spl_filesystem_from_obj(readobj); diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 5fd3830014a3d..2c7534a03228c 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -409,7 +409,7 @@ static zend_object *spl_dllist_object_clone(zend_object *old_object) /* {{{ */ } /* }}} */ -static int spl_dllist_object_count_elements(zend_object *object, zend_long *count) /* {{{ */ +static zend_result spl_dllist_object_count_elements(zend_object *object, zend_long *count) /* {{{ */ { spl_dllist_object *intern = spl_dllist_from_obj(object); diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 5f8dca8dd1812..fd18c3d86c378 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -510,7 +510,7 @@ static int spl_fixedarray_object_has_dimension(zend_object *object, zval *offset return spl_fixedarray_object_has_dimension_helper(intern, offset, check_empty); } -static int spl_fixedarray_object_count_elements(zend_object *object, zend_long *count) +static zend_result spl_fixedarray_object_count_elements(zend_object *object, zend_long *count) { spl_fixedarray_object *intern; diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index 3112666e33651..c541eb3c47416 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -484,7 +484,7 @@ static zend_object *spl_heap_object_clone(zend_object *old_object) /* {{{ */ } /* }}} */ -static int spl_heap_object_count_elements(zend_object *object, zend_long *count) /* {{{ */ +static zend_result spl_heap_object_count_elements(zend_object *object, zend_long *count) /* {{{ */ { spl_heap_object *intern = spl_heap_from_obj(object); diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c index d83dbdbc93a27..a59268680cacb 100644 --- a/ext/tidy/tidy.c +++ b/ext/tidy/tidy.c @@ -149,8 +149,8 @@ static void tidy_object_free_storage(zend_object *); static zend_object *tidy_object_new_node(zend_class_entry *); static zend_object *tidy_object_new_doc(zend_class_entry *); static zval *tidy_instantiate(zend_class_entry *, zval *); -static int tidy_doc_cast_handler(zend_object *, zval *, int); -static int tidy_node_cast_handler(zend_object *, zval *, int); +static zend_result tidy_doc_cast_handler(zend_object *, zval *, int); +static zend_result tidy_node_cast_handler(zend_object *, zval *, int); static void tidy_doc_update_properties(PHPTidyObj *); static void tidy_add_node_default_properties(PHPTidyObj *); static void *php_tidy_get_opt_val(PHPTidyDoc *, TidyOption, TidyOptionType *); @@ -462,7 +462,7 @@ static zval *tidy_instantiate(zend_class_entry *pce, zval *object) return object; } -static int tidy_doc_cast_handler(zend_object *in, zval *out, int type) +static zend_result tidy_doc_cast_handler(zend_object *in, zval *out, int type) { TidyBuffer output; PHPTidyObj *obj; @@ -500,7 +500,7 @@ static int tidy_doc_cast_handler(zend_object *in, zval *out, int type) return SUCCESS; } -static int tidy_node_cast_handler(zend_object *in, zval *out, int type) +static zend_result tidy_node_cast_handler(zend_object *in, zval *out, int type) { TidyBuffer buf; PHPTidyObj *obj; From bf29ee6917670a1b514e3ee78a5077cd12ff1978 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sat, 25 Jun 2022 19:04:28 +0100 Subject: [PATCH 082/440] Add `reallocarray` implementation. In a similar model as _safe_*alloc api but for the `userland` it guards against overflow before (re)allocation, usage concealed in fpm for now. Modern Linux and most of BSD already have it. Closes #8871. --- configure.ac | 4 ++-- main/php.h | 8 ++++++++ main/reallocarray.c | 41 +++++++++++++++++++++++++++++++++++++++ sapi/fpm/fpm/fpm_arrays.h | 4 +++- 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 main/reallocarray.c diff --git a/configure.ac b/configure.ac index 2dfb06dd023e0..d874a40a951c9 100644 --- a/configure.ac +++ b/configure.ac @@ -689,7 +689,7 @@ if test "$ac_cv_func_getaddrinfo" = yes; then AC_DEFINE(HAVE_GETADDRINFO,1,[Define if you have the getaddrinfo function]) fi -AC_REPLACE_FUNCS(strlcat strlcpy explicit_bzero getopt) +AC_REPLACE_FUNCS(strlcat strlcpy explicit_bzero getopt reallocarray) AC_FUNC_ALLOCA PHP_TIME_R_TYPE PHP_CHECK_IN_ADDR_T @@ -1616,7 +1616,7 @@ PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c \ php_ini_builder.c \ php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ strlcat.c explicit_bzero.c reentrancy.c php_variables.c php_ticks.c \ - network.c php_open_temporary_file.c php_odbc_utils.c safe_bcmp.c \ + network.c php_open_temporary_file.c php_odbc_utils.c safe_bcmp.c reallocarray.c \ output.c getopt.c php_syslog.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_ADD_SOURCES_X(main, fastcgi.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, PHP_FASTCGI_OBJS, no) diff --git a/main/php.h b/main/php.h index 9009ba032d3bd..27eb72389d2c7 100644 --- a/main/php.h +++ b/main/php.h @@ -179,6 +179,14 @@ END_EXTERN_C() #define explicit_bzero php_explicit_bzero #endif +#ifndef HAVE_REALLOCARRAY +BEGIN_EXTERN_C() +PHPAPI void* php_reallocarray(void *p, size_t nmb, size_t siz); +END_EXTERN_C() +#undef reallocarray +#define reallocarray php_reallocarray +#endif + BEGIN_EXTERN_C() PHPAPI int php_safe_bcmp(const zend_string *a, const zend_string *b); END_EXTERN_C() diff --git a/main/reallocarray.c b/main/reallocarray.c new file mode 100644 index 0000000000000..beee4bfa09705 --- /dev/null +++ b/main/reallocarray.c @@ -0,0 +1,41 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: David Carlier | + +----------------------------------------------------------------------+ +*/ + +#include "php.h" + +#ifndef HAVE_REALLOCARRAY + +#include + +PHPAPI void* php_reallocarray(void *p, size_t nmb, size_t siz) +{ + size_t r; +#ifndef _WIN32 + if (__builtin_mul_overflow(nmb, siz, &r)) { +#else + + r = siz * nmb; + if (siz != 0 && r / siz != nmb) { +#endif + // EOVERFLOW may have been, arguably, more appropriate + // but this is what other implementations set + errno = ENOMEM; + return NULL; + } + + return realloc(p, r); +} +#endif diff --git a/sapi/fpm/fpm/fpm_arrays.h b/sapi/fpm/fpm/fpm_arrays.h index 82c7cbc09e1e0..454ff31204b2d 100644 --- a/sapi/fpm/fpm/fpm_arrays.h +++ b/sapi/fpm/fpm/fpm_arrays.h @@ -6,6 +6,8 @@ #include #include +#include "php.h" + struct fpm_array_s { void *data; size_t sz; @@ -84,7 +86,7 @@ static inline void *fpm_array_push(struct fpm_array_s *a) /* {{{ */ if (a->used == a->allocated) { size_t new_allocated = a->allocated ? a->allocated * 2 : 20; - void *new_ptr = realloc(a->data, a->sz * new_allocated); + void *new_ptr = reallocarray(a->data, a->sz, new_allocated); if (!new_ptr) { return 0; From ad40fffd36cab87c249c28af6374c72959937dd6 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 27 Jun 2022 14:25:30 +0300 Subject: [PATCH 083/440] Fixed Bug GH-8863: RW operation on readonly property doesn't throw with JIT --- ext/opcache/jit/zend_jit_helpers.c | 5 +++++ ext/opcache/tests/jit/gh8863.phpt | 33 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 ext/opcache/tests/jit/gh8863.phpt diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index c91acff3adc11..68a820bd212ac 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -2558,6 +2558,11 @@ static void ZEND_FASTCALL zend_jit_assign_op_to_typed_prop(zval *zptr, zend_prop zend_execute_data *execute_data = EG(current_execute_data); zval z_copy; + if (UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) { + zend_readonly_property_modification_error(prop_info); + return; + } + ZVAL_DEREF(zptr); /* Make sure that in-place concatenation is used if the LHS is a string. */ if (binary_op == concat_function && Z_TYPE_P(zptr) == IS_STRING) { diff --git a/ext/opcache/tests/jit/gh8863.phpt b/ext/opcache/tests/jit/gh8863.phpt new file mode 100644 index 0000000000000..5f43e34a8ce7e --- /dev/null +++ b/ext/opcache/tests/jit/gh8863.phpt @@ -0,0 +1,33 @@ +--TEST-- +Bug GH-8863: RW operation on readonly property doesn't throw with JIT +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +prop = 1; + } + + public function rw() { + $this->prop += 1; + echo "Done\n"; + } +} + +$test = new Test(); +try { + $test->rw(); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +?> +DONE +--EXPECT-- +Cannot modify readonly property Test::$prop +DONE From 7e23c838e242b414eb46127b3829ed4c5bae3cba Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 27 Jun 2022 14:25:30 +0300 Subject: [PATCH 084/440] Fixed Bug GH-8863: RW operation on readonly property doesn't throw with JIT --- ext/opcache/jit/zend_jit_helpers.c | 5 +++++ ext/opcache/tests/jit/gh8863.phpt | 33 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 ext/opcache/tests/jit/gh8863.phpt diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index f953d704ca090..2b9f33a67be74 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -2563,6 +2563,11 @@ static void ZEND_FASTCALL zend_jit_assign_op_to_typed_prop(zval *zptr, zend_prop zend_execute_data *execute_data = EG(current_execute_data); zval z_copy; + if (UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) { + zend_readonly_property_modification_error(prop_info); + return; + } + ZVAL_DEREF(zptr); /* Make sure that in-place concatenation is used if the LHS is a string. */ if (binary_op == concat_function && Z_TYPE_P(zptr) == IS_STRING) { diff --git a/ext/opcache/tests/jit/gh8863.phpt b/ext/opcache/tests/jit/gh8863.phpt new file mode 100644 index 0000000000000..5f43e34a8ce7e --- /dev/null +++ b/ext/opcache/tests/jit/gh8863.phpt @@ -0,0 +1,33 @@ +--TEST-- +Bug GH-8863: RW operation on readonly property doesn't throw with JIT +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +prop = 1; + } + + public function rw() { + $this->prop += 1; + echo "Done\n"; + } +} + +$test = new Test(); +try { + $test->rw(); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +?> +DONE +--EXPECT-- +Cannot modify readonly property Test::$prop +DONE From 84c160dd909bc21fa410a8ad09c8732e25e1e29d Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 27 Jun 2022 16:25:33 +0200 Subject: [PATCH 085/440] Increase test portability The test as is can only work if com_dotnet is built dynamically, and not already loaded via the php.ini file. While this is given on AppVeyor, it may not be given in other environments. Closes GH-8879. --- ext/com_dotnet/tests/bug77578.phpt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ext/com_dotnet/tests/bug77578.phpt b/ext/com_dotnet/tests/bug77578.phpt index abb68cc163f4f..653a16123218d 100644 --- a/ext/com_dotnet/tests/bug77578.phpt +++ b/ext/com_dotnet/tests/bug77578.phpt @@ -7,9 +7,13 @@ com_dotnet // To actually be able to verify the crash during shutdown on Windows, we have // to execute a PHP subprocess, and check its exit status. $php = PHP_BINARY; -$ini = php_ini_loaded_file(); -$iniopt = $ini ? "-c $ini" : ''; -$command = "$php $iniopt -d extension=com_dotnet -d com.autoregister_typelib=1 -r \"new COM('WbemScripting.SWbemLocator');\""; +$extension_dir = ini_get("extension_dir"); +$script = <<