From 002d54db9f2d60a415ed4bd6112edf8466ee3c41 Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Tue, 13 Dec 2022 19:29:29 -0500 Subject: [PATCH 01/83] PHP-8.2 is now for PHP 8.2.2-dev --- NEWS | 5 ++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index b6ae41f72386d..61185a9a36b47 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.1 +?? ??? ????, PHP 8.2.2 + + +05 Jan 2023, PHP 8.2.1 - Core: . Fixed bug GH-9905 (constant() behaves inconsistent when class is undefined). diff --git a/Zend/zend.h b/Zend/zend.h index a4c13a84d963e..5e613207ae142 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.2.1-dev" +#define ZEND_VERSION "4.2.2-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 3c257b6bdfac0..efc2c2d6899a7 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.2.1-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.2-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 4cc596766d9c1..42c94eeece9bb 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 2 -#define PHP_RELEASE_VERSION 1 +#define PHP_RELEASE_VERSION 2 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.2.1-dev" -#define PHP_VERSION_ID 80201 +#define PHP_VERSION "8.2.2-dev" +#define PHP_VERSION_ID 80202 From 60cf9fbee066303b160c16183d2c3aa1ec8d7fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 13 Dec 2022 20:24:24 +0100 Subject: [PATCH 02/83] Replace another root XML element format to the "canonical" one --- build/gen_stub.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 8cf319ceaea39..5f6bffd8b09f3 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4261,16 +4261,18 @@ function replaceClassSynopses(string $targetDirectory, array $classMap, iterable $replacedXml = preg_replace( [ "/REPLACED-ENTITY-([A-Za-z0-9._{}%-]+?;)/", - "//i", - "//i", - "//i", - "//i", + '//i', + '//i', + '//i', + '//i', + '//i', ], [ "&$1", "", "", "", + "", "", ], $replacedXml @@ -4494,8 +4496,8 @@ function replaceMethodSynopses(string $targetDirectory, array $funcMap, array $a $replacedXml = preg_replace( [ "/REPLACED-ENTITY-([A-Za-z0-9._{}%-]+?;)/", - "//i", - "//i", + '//i', + '//i', ], [ "&$1", From b4df038cee08694263ac279677d92f4c594f6251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 13 Dec 2022 20:27:09 +0100 Subject: [PATCH 03/83] Remove the superfluous closing parentheses from class synopsis page includes --- build/gen_stub.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 5f6bffd8b09f3..1be94cd00434c 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2807,7 +2807,7 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera $parentReference = self::getClassSynopsisReference($parent); $includeElement = $this->createIncludeElement( $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$parentReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[not(@role='procedural')])" + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$parentReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[@role='$escapedParentName'])" ); $classSynopsis->appendChild($includeElement); } From 0fc60fab7265fabcfdaba4438f7fa0fae826cd28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 13 Dec 2022 20:41:16 +0100 Subject: [PATCH 04/83] Always include the constructor on the class manual pages --- build/gen_stub.php | 56 +++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 1be94cd00434c..945f9aa548742 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2760,40 +2760,36 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera "&InheritedProperties;" ); - if (!empty($this->funcInfos)) { - $classSynopsis->appendChild(new DOMText("\n\n ")); - $classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Methods;"); - $classSynopsisInfo->setAttribute("role", "comment"); - $classSynopsis->appendChild($classSynopsisInfo); + $classSynopsis->appendChild(new DOMText("\n\n ")); + $classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Methods;"); + $classSynopsisInfo->setAttribute("role", "comment"); + $classSynopsis->appendChild($classSynopsisInfo); - $classReference = self::getClassSynopsisReference($this->name); + $classReference = self::getClassSynopsisReference($this->name); - if ($this->hasConstructor()) { - $classSynopsis->appendChild(new DOMText("\n ")); - $includeElement = $this->createIncludeElement( - $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:constructorsynopsis[not(@role='procedural')])" - ); - $classSynopsis->appendChild($includeElement); - } + $classSynopsis->appendChild(new DOMText("\n ")); + $includeElement = $this->createIncludeElement( + $doc, + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:constructorsynopsis[not(@role='procedural')])" + ); + $classSynopsis->appendChild($includeElement); - if ($this->hasMethods()) { - $classSynopsis->appendChild(new DOMText("\n ")); - $includeElement = $this->createIncludeElement( - $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[not(@role='procedural')])" - ); - $classSynopsis->appendChild($includeElement); - } + if ($this->hasMethods()) { + $classSynopsis->appendChild(new DOMText("\n ")); + $includeElement = $this->createIncludeElement( + $doc, + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[not(@role='procedural')])" + ); + $classSynopsis->appendChild($includeElement); + } - if ($this->hasDestructor()) { - $classSynopsis->appendChild(new DOMText("\n ")); - $includeElement = $this->createIncludeElement( - $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:destructorsynopsis[not(@role='procedural')])" - ); - $classSynopsis->appendChild($includeElement); - } + if ($this->hasDestructor()) { + $classSynopsis->appendChild(new DOMText("\n ")); + $includeElement = $this->createIncludeElement( + $doc, + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:destructorsynopsis[not(@role='procedural')])" + ); + $classSynopsis->appendChild($includeElement); } if (!empty($parentsWithInheritedMethods)) { From 6aa5e58414e4fe6e689e70c36c4709cc745f277d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Fri, 16 Dec 2022 12:07:23 +0100 Subject: [PATCH 05/83] Backport methodsynopsis role attributes changes from master Commits https://github.com/php/php-src/commit/93605f286d11876da44d2ecd41c13d7e3f0aae66 and https://github.com/php/php-src/commit/d6651426f405342f74cdfe930448912ef68e23c4 --- build/gen_stub.php | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 945f9aa548742..6af9e06d16acb 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1487,14 +1487,10 @@ public function getMethodSynopsisElement(array $funcMap, array $aliasMap, DOMDoc $methodSynopsis = $doc->createElement($synopsisType); - $aliasedFunc = $this->aliasType === "alias" && isset($funcMap[$this->alias->__toString()]) ? $funcMap[$this->alias->__toString()] : null; - $aliasFunc = $aliasMap[$this->name->__toString()] ?? null; - - if (($this->aliasType === "alias" && $aliasedFunc !== null && $aliasedFunc->isMethod() !== $this->isMethod()) || - ($aliasFunc !== null && $aliasFunc->isMethod() !== $this->isMethod()) - ) { + if ($this->isMethod()) { + assert($this->name instanceof MethodName); $role = $doc->createAttribute("role"); - $role->value = $this->isMethod() ? "oop" : "procedural"; + $role->value = addslashes($this->name->className->__toString()); $methodSynopsis->appendChild($role); } @@ -2766,11 +2762,12 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera $classSynopsis->appendChild($classSynopsisInfo); $classReference = self::getClassSynopsisReference($this->name); + $escapedName = addslashes($this->name->__toString()); $classSynopsis->appendChild(new DOMText("\n ")); $includeElement = $this->createIncludeElement( $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:constructorsynopsis[not(@role='procedural')])" + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:constructorsynopsis[@role='$escapedName'])" ); $classSynopsis->appendChild($includeElement); @@ -2778,7 +2775,7 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera $classSynopsis->appendChild(new DOMText("\n ")); $includeElement = $this->createIncludeElement( $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[not(@role='procedural')])" + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[@role='$escapedName'])" ); $classSynopsis->appendChild($includeElement); } @@ -2787,7 +2784,7 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera $classSynopsis->appendChild(new DOMText("\n ")); $includeElement = $this->createIncludeElement( $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:destructorsynopsis[not(@role='procedural')])" + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:destructorsynopsis[@role='$escapedName'])" ); $classSynopsis->appendChild($includeElement); } @@ -2801,6 +2798,7 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera foreach ($parentsWithInheritedMethods as $parent) { $classSynopsis->appendChild(new DOMText("\n ")); $parentReference = self::getClassSynopsisReference($parent); + $escapedParentName = addslashes($parent->__toString()); $includeElement = $this->createIncludeElement( $doc, "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$parentReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[@role='$escapedParentName'])" From b8ac2071b897481938c6207989654cc3132ff317 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 16 Dec 2022 12:16:38 +0100 Subject: [PATCH 06/83] Fix GH-10112: LDAP\Connection::__construct() refers to ldap_create() There is no `ldap_create()`, but rather `ldap_connect()`. Closes GH-10115. --- NEWS | 4 ++++ ext/ldap/ldap.c | 2 +- ext/ldap/tests/ldap_constructor.phpt | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 9994834a7f526..6d165ca1a707f 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,10 @@ PHP NEWS - Apache: . Fixed bug GH-9949 (Partial content on incomplete POST request). (cmb) +- LDAP: + . Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()). + (cmb) + - TSRM: . Fixed Windows shmget() wrt. IPC_PRIVATE. (Tyson Andre) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 6e0f28f68080e..19b6e05d4ecf1 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -119,7 +119,7 @@ static zend_object *ldap_link_create_object(zend_class_entry *class_type) { } static zend_function *ldap_link_get_constructor(zend_object *object) { - zend_throw_error(NULL, "Cannot directly construct LDAP\\Connection, use ldap_create() instead"); + zend_throw_error(NULL, "Cannot directly construct LDAP\\Connection, use ldap_connect() instead"); return NULL; } diff --git a/ext/ldap/tests/ldap_constructor.phpt b/ext/ldap/tests/ldap_constructor.phpt index 37db6112dcee5..6c79dee8b3982 100644 --- a/ext/ldap/tests/ldap_constructor.phpt +++ b/ext/ldap/tests/ldap_constructor.phpt @@ -11,4 +11,4 @@ try { echo "Exception: ", $ex->getMessage(), "\n"; } --EXPECT-- -Exception: Cannot directly construct LDAP\Connection, use ldap_create() instead +Exception: Cannot directly construct LDAP\Connection, use ldap_connect() instead From d832125b8ed8d2b8d4c33a5e1b8bb9bb55378341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Fri, 16 Dec 2022 17:02:24 +0100 Subject: [PATCH 07/83] Only include the default constructor for non-abstract class synopses --- build/gen_stub.php | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 6af9e06d16acb..7e89007948fe6 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2756,20 +2756,26 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera "&InheritedProperties;" ); - $classSynopsis->appendChild(new DOMText("\n\n ")); - $classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Methods;"); - $classSynopsisInfo->setAttribute("role", "comment"); - $classSynopsis->appendChild($classSynopsisInfo); + $isConcreteClass = ($this->type === "class" && !($this->flags & Class_::MODIFIER_ABSTRACT)); + + if ($isConcreteClass || !empty($this->funcInfos)) { + $classSynopsis->appendChild(new DOMText("\n\n ")); + $classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Methods;"); + $classSynopsisInfo->setAttribute("role", "comment"); + $classSynopsis->appendChild($classSynopsisInfo); + } $classReference = self::getClassSynopsisReference($this->name); $escapedName = addslashes($this->name->__toString()); - $classSynopsis->appendChild(new DOMText("\n ")); - $includeElement = $this->createIncludeElement( - $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:constructorsynopsis[@role='$escapedName'])" - ); - $classSynopsis->appendChild($includeElement); + if ($isConcreteClass || $this->hasConstructor()) { + $classSynopsis->appendChild(new DOMText("\n ")); + $includeElement = $this->createIncludeElement( + $doc, + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:constructorsynopsis[@role='$escapedName'])" + ); + $classSynopsis->appendChild($includeElement); + } if ($this->hasMethods()) { $classSynopsis->appendChild(new DOMText("\n ")); From 921b6813da3237a83e908998483f46ae3d8bacba Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 31 Oct 2022 17:20:23 +0100 Subject: [PATCH 08/83] Fix #81740: PDO::quote() may return unquoted string `sqlite3_snprintf()` expects its first parameter to be `int`; we need to avoid overflow. --- ext/pdo_sqlite/sqlite_driver.c | 3 +++ ext/pdo_sqlite/tests/bug81740.phpt | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 ext/pdo_sqlite/tests/bug81740.phpt diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index 4233ff10ff2ee..5a72a1eda23f4 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -232,6 +232,9 @@ static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t /* NB: doesn't handle binary strings... use prepared stmts for that */ static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype ) { + if (unquotedlen > (INT_MAX - 3) / 2) { + return 0; + } *quoted = safe_emalloc(2, unquotedlen, 3); sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted); *quotedlen = strlen(*quoted); diff --git a/ext/pdo_sqlite/tests/bug81740.phpt b/ext/pdo_sqlite/tests/bug81740.phpt new file mode 100644 index 0000000000000..99fb07c3048b0 --- /dev/null +++ b/ext/pdo_sqlite/tests/bug81740.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #81740 (PDO::quote() may return unquoted string) +--SKIPIF-- + +--INI-- +memory_limit=-1 +--FILE-- +quote($string)); +?> +--EXPECT-- +bool(false) From 5f90134bb69a345c7edb5013e6461e84caa32dbc Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 18 Dec 2022 22:52:30 -0700 Subject: [PATCH 09/83] Make build work with newer OpenSSL --- ext/openssl/openssl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 45a7e794400d0..9827c75871668 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1325,7 +1325,9 @@ PHP_MINIT_FUNCTION(openssl) REGISTER_LONG_CONSTANT("OPENSSL_CMS_NOSIGS", CMS_NOSIGS, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_PADDING", RSA_PKCS1_PADDING, CONST_CS|CONST_PERSISTENT); +#ifdef RSA_SSLV23_PADDING REGISTER_LONG_CONSTANT("OPENSSL_SSLV23_PADDING", RSA_SSLV23_PADDING, CONST_CS|CONST_PERSISTENT); +#endif REGISTER_LONG_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_CS|CONST_PERSISTENT); From a6a80eefe0413c91acd922bc58590a4db7979af0 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 18 Dec 2022 23:20:29 -0700 Subject: [PATCH 10/83] Improve fix for bug #81740 --- ext/pdo/pdo_dbh.c | 10 ++++++++-- ext/pdo/pdo_sql_parser.re | 7 +++++++ ext/pdo_sqlite/sqlite_driver.c | 4 ++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 5d3efe12e55f7..4c8af0597a28c 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -1161,7 +1161,7 @@ PHP_METHOD(PDO, query) PHP_METHOD(PDO, quote) { pdo_dbh_t *dbh = Z_PDO_DBH_P(ZEND_THIS); - zend_string *str; + zend_string *str, *quoted; zend_long paramtype = PDO_PARAM_STR; ZEND_PARSE_PARAMETERS_START(1, 2) @@ -1177,8 +1177,14 @@ PHP_METHOD(PDO, quote) pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support quoting"); RETURN_FALSE; } + quoted = dbh->methods->quoter(dbh, str, paramtype); - RETURN_STR(dbh->methods->quoter(dbh, str, paramtype)); + if (quoted == NULL) { + PDO_HANDLE_DBH_ERR(); + RETURN_FALSE; + } + + RETURN_STR(quoted); } /* }}} */ diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re index 4c20700379731..6bb0837fb31f9 100644 --- a/ext/pdo/pdo_sql_parser.re +++ b/ext/pdo/pdo_sql_parser.re @@ -242,6 +242,13 @@ safe: if (buf) { zend_string_release_ex(buf, 0); } + if (plc->quoted == NULL) { + /* bork */ + ret = -1; + strncpy(stmt->error_code, stmt->dbh->error_code, 6); + goto clean_up; + } + } else { pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource"); ret = -1; diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index 15e06fc0302cf..6d5015e0ba6c2 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -227,8 +227,8 @@ static zend_string *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const zend_string static zend_string* sqlite_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype) { char *quoted; - if (unquotedlen > (INT_MAX - 3) / 2) { - return 0; + if (ZSTR_LEN(unquoted) > (INT_MAX - 3) / 2) { + return NULL; } quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3); /* TODO use %Q format? */ From 05c35137cd9eba8950249f62b86212af24cbfb33 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 18 Dec 2022 23:24:53 -0700 Subject: [PATCH 11/83] Add NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 0874b812f83cf..c6b0036b600b9 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2022, PHP 8.0.27 +- PDO/SQLite: + . Fixed bug #81740 (PDO::quote() may return unquoted string). (CVE-2022-31631) + (cmb) + 24 Nov 2022, PHP 8.0.26 - CLI: From 683285165e94bbe8ed387e3850b0b776b804f948 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 19 Dec 2022 12:11:16 +0300 Subject: [PATCH 12/83] Fix memory leak Fixes oss-fuzz #54320 --- Zend/tests/class_constants_007.phpt | 13 +++++++++++++ Zend/zend_inheritance.c | 1 + 2 files changed, 14 insertions(+) create mode 100644 Zend/tests/class_constants_007.phpt diff --git a/Zend/tests/class_constants_007.phpt b/Zend/tests/class_constants_007.phpt new file mode 100644 index 0000000000000..d09a12e8c17b8 --- /dev/null +++ b/Zend/tests/class_constants_007.phpt @@ -0,0 +1,13 @@ +--TEST-- +Ownership of constant expression inhereted from immutable class should be transfered to class +--FILE-- + +--EXPECT-- +string(2) " " diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index acff1da1798e9..e91195bb15a6b 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1354,6 +1354,7 @@ static void do_inherit_class_constant(zend_string *name, zend_class_constant *pa c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant)); memcpy(c, parent_const, sizeof(zend_class_constant)); parent_const = c; + Z_CONSTANT_FLAGS(c->value) |= CONST_OWNED; } } if (ce->type & ZEND_INTERNAL_CLASS) { From cf5dac07d248b8cdd082d6b327d3b4c91900bd1e Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 19 Dec 2022 15:56:56 +0100 Subject: [PATCH 13/83] Skip newly added test on 32bit platforms That bug didn't affect 32bit platforms, and besides, it is rather unlikely that allocating a 2GB string works on such platforms. --- ext/pdo_sqlite/tests/bug81740.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/pdo_sqlite/tests/bug81740.phpt b/ext/pdo_sqlite/tests/bug81740.phpt index 99fb07c3048b0..dc33641ae864e 100644 --- a/ext/pdo_sqlite/tests/bug81740.phpt +++ b/ext/pdo_sqlite/tests/bug81740.phpt @@ -3,6 +3,7 @@ Bug #81740 (PDO::quote() may return unquoted string) --SKIPIF-- --INI-- From da5cbca23ec1292cc15385f69ebc43bc8f51addd Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 19 Dec 2022 16:14:00 +0100 Subject: [PATCH 14/83] Force extension loading for new test --- ext/pdo_sqlite/tests/bug81740.phpt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/pdo_sqlite/tests/bug81740.phpt b/ext/pdo_sqlite/tests/bug81740.phpt index dc33641ae864e..2b8b9447f0fed 100644 --- a/ext/pdo_sqlite/tests/bug81740.phpt +++ b/ext/pdo_sqlite/tests/bug81740.phpt @@ -1,8 +1,10 @@ --TEST-- Bug #81740 (PDO::quote() may return unquoted string) +--EXTENSIONS-- +pdo +pdo_sqlite --SKIPIF-- From d19a70c9a0293d668fa66870610107764137d309 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Tue, 20 Dec 2022 14:41:13 +0000 Subject: [PATCH 15/83] Fix GH-9891: DateTime modify with unixtimestamp (@) must work like setTimestamp --- NEWS | 4 ++++ ext/date/php_date.c | 4 ++++ ext/date/tests/gh9891.phpt | 30 ++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 ext/date/tests/gh9891.phpt diff --git a/NEWS b/NEWS index 6d165ca1a707f..0098d6f769991 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,10 @@ PHP NEWS - Apache: . Fixed bug GH-9949 (Partial content on incomplete POST request). (cmb) +- Date: + . Fixed bug GH-9891 (DateTime modify with unixtimestamp (@) must work like + setTimestamp). (Derick) + - LDAP: . Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()). (cmb) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 4aeb17a8391b7..0305873eea0e6 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -2897,6 +2897,10 @@ static int php_date_modify(zval *object, char *modify, size_t modify_len) /* {{{ dateobj->time->us = tmp_time->us; } + if (tmp_time->have_zone && tmp_time->zone_type == TIMELIB_ZONETYPE_OFFSET) { + timelib_set_timezone_from_offset(dateobj->time, tmp_time->z); + } + timelib_time_dtor(tmp_time); timelib_update_ts(dateobj->time, NULL); diff --git a/ext/date/tests/gh9891.phpt b/ext/date/tests/gh9891.phpt new file mode 100644 index 0000000000000..6d8832b0d9237 --- /dev/null +++ b/ext/date/tests/gh9891.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug GH-9891 (DateTime modify with unixtimestamp (@) must work like setTimestamp) +--FILE-- +modify('@1234567890'); +var_dump($m->getTimeStamp()); + +echo "=======\n"; + +$a = new DateTime('2022-11-01 13:30:00', new DateTimezone('America/Lima')); +$b = clone $a; +echo '$a: ', $a->format(DateTime::ATOM), "\n"; +echo '$b: ', $b->format(DateTime::ATOM), "\n"; +echo '$a: @', $a->getTimestamp(), "\n"; +echo '$b: setTimestamp(', $b->getTimestamp(), ")\n"; +$a->modify('@' . $a->getTimestamp()); +$b->setTimestamp($b->getTimestamp()); +echo '$a: ', $a->format(DateTime::ATOM), "\n"; +echo '$b: ', $b->format(DateTime::ATOM), "\n"; +?> +--EXPECT-- +int(1234567890) +======= +$a: 2022-11-01T13:30:00-05:00 +$b: 2022-11-01T13:30:00-05:00 +$a: @1667327400 +$b: setTimestamp(1667327400) +$a: 2022-11-01T18:30:00+00:00 +$b: 2022-11-01T13:30:00-05:00 From bfa56cf62bfdb07afa93c63ec263ce24a591261d Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 20 Dec 2022 15:24:15 +0100 Subject: [PATCH 16/83] Fix #10133 set variables_order en ensure $ENV is set --- Zend/tests/traits/constant_016.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Zend/tests/traits/constant_016.phpt b/Zend/tests/traits/constant_016.phpt index 9cb2b29bcc095..0754c15716377 100644 --- a/Zend/tests/traits/constant_016.phpt +++ b/Zend/tests/traits/constant_016.phpt @@ -2,6 +2,8 @@ Compatibility of values of same name trait constants is checked after their constant expressions are evaluated --ENV-- ENSURE_CONSTANT_IS_DEFINED_AT_RUNTIME=1 +--INI-- +variables_order=EGPCS --FILE-- Date: Tue, 29 Nov 2022 21:47:53 +0000 Subject: [PATCH 17/83] Fix bug #77106: Missing separator in FPM FastCGI errors --- NEWS | 3 ++ sapi/fpm/fpm/fpm_main.c | 16 +++++-- sapi/fpm/tests/bug77106-fcgi-missing-nl.phpt | 46 ++++++++++++++++++++ sapi/fpm/tests/response.inc | 36 +++++++++++++-- 4 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 sapi/fpm/tests/bug77106-fcgi-missing-nl.phpt diff --git a/NEWS b/NEWS index 0e1c6bfa3d664..d9d6d5787bb7c 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.2 +- FPM: + . Fixed bug #77106 (Missing separator in FPM FastCGI errors). (Jakub Zelenka) + - LDAP: . Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()). (cmb) diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index a8d77ef3bed21..aa43e0c5da407 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -149,6 +149,7 @@ typedef struct _php_cgi_globals_struct { bool force_redirect; bool discard_path; bool fcgi_logging; + bool fcgi_logging_request_started; char *redirect_status_env; HashTable user_config_cache; char *error_header; @@ -598,11 +599,16 @@ void sapi_cgi_log_fastcgi(int level, char *message, size_t len) * - logging is enabled (fastcgi.logging in php.ini) * - we are currently dealing with a request * - the message is not empty - * - the fcgi_write did not fail */ - if (CGIG(fcgi_logging) && request && message && len > 0 - && fcgi_write(request, FCGI_STDERR, message, len) < 0) { - php_handle_aborted_connection(); + if (CGIG(fcgi_logging) && request && message && len > 0) { + if (CGIG(fcgi_logging_request_started)) { + fcgi_write(request, FCGI_STDERR, "; ", 2); + } else { + CGIG(fcgi_logging_request_started) = true; + } + if (fcgi_write(request, FCGI_STDERR, message, len) < 0) { + php_handle_aborted_connection(); + } } } /* }}} */ @@ -1403,6 +1409,7 @@ static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals) php_cgi_globals->fix_pathinfo = 1; php_cgi_globals->discard_path = 0; php_cgi_globals->fcgi_logging = 1; + php_cgi_globals->fcgi_logging_request_started = false; zend_hash_init(&php_cgi_globals->user_config_cache, 0, NULL, user_config_cache_entry_dtor, 1); php_cgi_globals->error_header = NULL; php_cgi_globals->fpm_config = NULL; @@ -1820,6 +1827,7 @@ consult the installation file that came with this distribution, or visit \n\ char *primary_script = NULL; request_body_fd = -1; SG(server_context) = (void *) request; + CGIG(fcgi_logging_request_started) = false; init_request_info(); fpm_request_info(); diff --git a/sapi/fpm/tests/bug77106-fcgi-missing-nl.phpt b/sapi/fpm/tests/bug77106-fcgi-missing-nl.phpt new file mode 100644 index 0000000000000..c4c7adf382545 --- /dev/null +++ b/sapi/fpm/tests/bug77106-fcgi-missing-nl.phpt @@ -0,0 +1,46 @@ +--TEST-- +FPM: bug77106 - Missing new lines in FCGI error stream +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester->request()->expectErrorPattern( + '/Undefined variable \$a in .+ on line \d+; PHP message: PHP Warning:/' +); +$tester->terminate(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/response.inc b/sapi/fpm/tests/response.inc index dd74e42990b08..c91c33f1cbe86 100644 --- a/sapi/fpm/tests/response.inc +++ b/sapi/fpm/tests/response.inc @@ -41,6 +41,11 @@ class Response */ private $expectInvalid; + /** + * @var bool + */ + private bool $debugOutputted = false; + /** * @param string|array|null $data * @param bool $expectInvalid @@ -71,9 +76,9 @@ class Response $body = implode("\n", $body); } - if (!$this->checkIfValid()) { + if ( ! $this->checkIfValid()) { $this->error('Response is invalid'); - } elseif (!$this->checkDefaultHeaders($contentType)) { + } elseif ( ! $this->checkDefaultHeaders($contentType)) { $this->error('Response default headers not found'); } elseif ($body !== $this->rawBody) { if ($multiLine) { @@ -134,6 +139,26 @@ class Response return $this; } + /** + * Expect error pattern in the response. + * + * @param string $errorMessagePattern Expected error message RegExp patter. + * + * @return Response + */ + public function expectErrorPattern(string $errorMessagePattern): Response + { + $errorData = $this->getErrorData(); + if (preg_match($errorMessagePattern, $errorData) === 0) { + $this->error( + "The expected error pattern $errorMessagePattern does not match the returned error '$errorData'" + ); + $this->debugOutput(); + } + + return $this; + } + /** * Expect no error in the response. * @@ -187,6 +212,8 @@ class Response echo "----------------- ERR -----------------\n"; echo $this->data['err_response'] . "\n"; echo "---------------------------------------\n\n"; + + $this->debugOutputted = true; } /** @@ -331,8 +358,11 @@ class Response * * @return bool */ - private function error($message): bool + private function error(string $message): bool { + if ( ! $this->debugOutputted) { + $this->debugOutput(); + } echo "ERROR: $message\n"; return false; From d3a6eedf4ae2bde358d22970ec3c92244bc02552 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 21 Dec 2022 14:53:21 +0100 Subject: [PATCH 18/83] ext/opcache/jit/zend_jit: fix inverted bailout value in zend_runtime_jit() (#10144) In the "catch" block, do_bailout must be set to true, not false, or else zend_bailout() never gets called. --- ext/opcache/jit/zend_jit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index d241a42d4bb55..28404f2d2bdf0 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -4287,7 +4287,7 @@ static int ZEND_FASTCALL zend_runtime_jit(void) /* perform real JIT for this function */ zend_real_jit_func(op_array, NULL, NULL); } zend_catch { - do_bailout = 0; + do_bailout = true; } zend_end_try(); zend_jit_protect(); From 6de376a2b47917f1e875bf7afb7461b893e7a337 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Wed, 21 Dec 2022 14:55:21 +0100 Subject: [PATCH 19/83] [ci skip] NEWS --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 0098d6f769991..16ee8ebb05b6a 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,9 @@ PHP NEWS . Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()). (cmb) +- Opcache: + . Fix inverted bailout value in zend_runtime_jit() (Max Kellermann). + - TSRM: . Fixed Windows shmget() wrt. IPC_PRIVATE. (Tyson Andre) From 9b57295d5686737ea856410da598a2bad1d328c9 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Wed, 21 Dec 2022 14:55:53 +0100 Subject: [PATCH 20/83] [ci skip] NEWS --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index d9d6d5787bb7c..7e0e5336ea43b 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,9 @@ PHP NEWS . Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()). (cmb) +- Opcache: + . Fix inverted bailout value in zend_runtime_jit() (Max Kellermann). + 05 Jan 2023, PHP 8.2.1 - Core: From c4487b7a12bf80523deb70982c9bdbb9bf4b876c Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 17 Dec 2022 16:02:55 +0100 Subject: [PATCH 21/83] Initialize ping_auto_globals_mask to prevent undefined behaviour Closes GH-10121 --- NEWS | 1 + ext/opcache/ZendAccelerator.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 16ee8ebb05b6a..8995c9e5ab8a4 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ PHP NEWS - Opcache: . Fix inverted bailout value in zend_runtime_jit() (Max Kellermann). + . Fix access to uninitialized variable in accel_preload(). (nielsdos) - TSRM: . Fixed Windows shmget() wrt. IPC_PRIVATE. (Tyson Andre) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index e5d7f650045ca..99bb33573f3b2 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -4444,6 +4444,8 @@ static int accel_preload(const char *config, bool in_child) if (PG(auto_globals_jit)) { ping_auto_globals_mask = zend_accel_get_auto_globals(); + } else { + ping_auto_globals_mask = 0; } if (EG(zend_constants)) { From bbad29b9c128c41508f26064d2cbf425b8984522 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 18 Dec 2022 14:16:01 +0100 Subject: [PATCH 22/83] Add a regression test for auto_globals_jit=0 with preloading on --- .../tests/preloading_no_auto_globals_jit.inc | 6 ++++++ .../tests/preloading_no_auto_globals_jit.phpt | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 ext/opcache/tests/preloading_no_auto_globals_jit.inc create mode 100644 ext/opcache/tests/preloading_no_auto_globals_jit.phpt diff --git a/ext/opcache/tests/preloading_no_auto_globals_jit.inc b/ext/opcache/tests/preloading_no_auto_globals_jit.inc new file mode 100644 index 0000000000000..ad80df7733d1d --- /dev/null +++ b/ext/opcache/tests/preloading_no_auto_globals_jit.inc @@ -0,0 +1,6 @@ + +--FILE-- +count_global_server()); +?> +--EXPECTF-- +int(%d) From 5f1311a92c4370f0894268f47357410e45597e81 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 22 Dec 2022 21:03:45 +0100 Subject: [PATCH 23/83] Fix undefined behaviour in phpdbg_load_module_or_extension If zend_register_module_ex were to return NULL, then module_entry will be set to NULL, and the if's body will load module_entry->name. Since module_entry is NULL, loading the name would cause a NULL pointer dereference. However, since a NULL pointer dereference is undefined behaviour, the compiler is free to remove the check. Fix it by using *name instead of module_entry->name. Closes GH-10157 Signed-off-by: George Peter Banyard --- NEWS | 3 +++ sapi/phpdbg/phpdbg_prompt.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 8995c9e5ab8a4..33fb5644fba51 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,9 @@ PHP NEWS . Fix inverted bailout value in zend_runtime_jit() (Max Kellermann). . Fix access to uninitialized variable in accel_preload(). (nielsdos) +- PHPDBG: + . Fix undefined behaviour in phpdbg_load_module_or_extension(). (nielsdos) + - TSRM: . Fixed Windows shmget() wrt. IPC_PRIVATE. (Tyson Andre) diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 6597f5fe42cf8..4c50653ce66f9 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -1321,7 +1321,7 @@ PHPDBG_API const char *phpdbg_load_module_or_extension(char **path, const char * module_entry->handle = handle; if ((module_entry = zend_register_module_ex(module_entry)) == NULL) { - phpdbg_error("Unable to register module %s", module_entry->name); + phpdbg_error("Unable to register module %s", *name); goto quit; } From a24659e70ccc61bb6231907971b58e9a9ac73c9b Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 23 Dec 2022 15:29:09 +0100 Subject: [PATCH 24/83] Update test for changed behaviour of GMP constructor Closed GH-10160 Signed-off-by: George Peter Banyard --- ext/gmp/tests/gmp_dynamic_property.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/gmp/tests/gmp_dynamic_property.phpt b/ext/gmp/tests/gmp_dynamic_property.phpt index 547fe51a7f6a3..ff3d4ac94e012 100644 --- a/ext/gmp/tests/gmp_dynamic_property.phpt +++ b/ext/gmp/tests/gmp_dynamic_property.phpt @@ -5,7 +5,7 @@ gmp --FILE-- {1} = 123; $serialized = serialize($g); From 233ffccc354f2da7ec7f1df162208462b12bb1e2 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Mon, 12 Dec 2022 14:22:41 +0000 Subject: [PATCH 25/83] Fix GH-10072: PHP crashes when execute_ex is overridden and a __call trampoline is used from internal code --- Zend/tests/gh10072.phpt | 105 ++++++++++++++++++++++++++++++++++++++++ Zend/zend_vm_def.h | 6 ++- Zend/zend_vm_execute.h | 12 +++-- 3 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 Zend/tests/gh10072.phpt diff --git a/Zend/tests/gh10072.phpt b/Zend/tests/gh10072.phpt new file mode 100644 index 0000000000000..2499ab0ca02fb --- /dev/null +++ b/Zend/tests/gh10072.phpt @@ -0,0 +1,105 @@ +--TEST-- +GH-10072 (PHP crashes when execute_ex is overridden and a trampoline is used from internal code) +--EXTENSIONS-- +zend_test +--INI-- +zend_test.replace_zend_execute_ex=1 +--FILE-- +handle; + } + + + public function stream_close(): void + { + } + + public function stream_open(string $path, string $mode, int $options = 0, ?string &$openedPath = null): bool + { + return true; + } + + + public function stream_read(int $count) + { + return 0; + } + + + public function stream_seek(int $offset, int $whence = SEEK_SET): bool + { + return true; + } + + + public function stream_set_option(int $option, int $arg1, ?int $arg2): bool + { + return false; + } + + + public function stream_stat() + { + return []; + } + + + public function stream_tell() + { + return []; + } + + + public function stream_truncate(int $newSize): bool + { + return true; + } + + + public function stream_write(string $data) + { + } + + + public function unlink(string $path): bool + { + return false; + } +} + +class TrampolineTest { + /** @var resource|null */ + public $context; + + /** @var object|null */ + private $wrapper; + + public function __call(string $name, array $arguments) { + if (!$this->wrapper) { + $this->wrapper = new DummyStreamWrapper(); + } + echo 'Trampoline for ', $name, PHP_EOL; + return $this->wrapper->$name(...$arguments); + } + +} + +stream_wrapper_register('custom', TrampolineTest::class); + + +$fp = fopen("custom://myvar", "r+"); +?> +--EXPECT-- +Trampoline for stream_open +Trampoline for stream_close diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index eb40d3023066f..d869116c33e33 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8663,7 +8663,9 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER)) SAVE_OPLINE_EX(); ZEND_OBSERVER_FCALL_BEGIN(execute_data); execute_data = EX(prev_execute_data); - LOAD_OPLINE(); + if (execute_data) { + LOAD_OPLINE(); + } ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } @@ -8713,7 +8715,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER)) execute_data = EG(current_execute_data); - if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) { + if (!execute_data || !EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) { ZEND_VM_RETURN(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a0b4efd737286..c22a1a104e93c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3319,7 +3319,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z SAVE_OPLINE_EX(); execute_data = EX(prev_execute_data); - LOAD_OPLINE(); + if (execute_data) { + LOAD_OPLINE(); + } ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } @@ -3369,7 +3371,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z execute_data = EG(current_execute_data); - if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) { + if (!execute_data || !EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) { ZEND_VM_RETURN(); } @@ -3456,7 +3458,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_ SAVE_OPLINE_EX(); zend_observer_fcall_begin(execute_data); execute_data = EX(prev_execute_data); - LOAD_OPLINE(); + if (execute_data) { + LOAD_OPLINE(); + } ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } @@ -3506,7 +3510,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_ execute_data = EG(current_execute_data); - if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) { + if (!execute_data || !EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) { ZEND_VM_RETURN(); } From b489e0f2b847f21cdd8decbd3c1c9e83d0c61c1e Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Mon, 12 Dec 2022 15:29:48 +0000 Subject: [PATCH 26/83] Make sure to disable JIT when overriding execute_ex --- Zend/tests/gh10072.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/Zend/tests/gh10072.phpt b/Zend/tests/gh10072.phpt index 2499ab0ca02fb..95a0d43450525 100644 --- a/Zend/tests/gh10072.phpt +++ b/Zend/tests/gh10072.phpt @@ -4,6 +4,7 @@ GH-10072 (PHP crashes when execute_ex is overridden and a trampoline is used fro zend_test --INI-- zend_test.replace_zend_execute_ex=1 +opcache.jit=disable --FILE-- Date: Tue, 13 Dec 2022 07:30:21 +0000 Subject: [PATCH 27/83] Add secondary test that registers a trampoline as a shutdown function --- Zend/tests/gh10072-2.phpt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Zend/tests/gh10072-2.phpt diff --git a/Zend/tests/gh10072-2.phpt b/Zend/tests/gh10072-2.phpt new file mode 100644 index 0000000000000..3de75a2b6c09f --- /dev/null +++ b/Zend/tests/gh10072-2.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-10072 (PHP crashes when execute_ex is overridden and a trampoline is used from internal code during shutdown) +--EXTENSIONS-- +zend_test +--INI-- +zend_test.replace_zend_execute_ex=1 +opcache.jit=disable +--FILE-- + +--EXPECT-- +Trampoline for shutdown From a3891d9d1a7067105cbd8a4dabfd7947dde14674 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 22 Dec 2022 18:32:16 +0000 Subject: [PATCH 28/83] Fix GH-9981: FPM does not reset fastcgi.error_header --- NEWS | 4 ++ sapi/fpm/fpm/fpm_main.c | 3 ++ .../gh9981-fastcgi-error-header-reset.phpt | 51 +++++++++++++++++++ sapi/fpm/tests/response.inc | 30 +++++++++++ 4 files changed, 88 insertions(+) create mode 100644 sapi/fpm/tests/gh9981-fastcgi-error-header-reset.phpt diff --git a/NEWS b/NEWS index bdcce4579ec07..5cde54978395f 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,10 @@ PHP NEWS . Fixed bug GH-9891 (DateTime modify with unixtimestamp (@) must work like setTimestamp). (Derick) +- FPM: + . Fixed bug GH-9981 (FPM does not reset fastcgi.error_header). + (Jakub Zelenka) + - LDAP: . Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()). (cmb) diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index eb8fab8e832c0..5d83ee08af2c7 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -1911,6 +1911,9 @@ consult the installation file that came with this distribution, or visit \n\ fpm_request_executing(); + /* Reset exit status from the previous execution */ + EG(exit_status) = 0; + php_execute_script(&file_handle); fastcgi_request_done: diff --git a/sapi/fpm/tests/gh9981-fastcgi-error-header-reset.phpt b/sapi/fpm/tests/gh9981-fastcgi-error-header-reset.phpt new file mode 100644 index 0000000000000..5a1d65f1cb0bd --- /dev/null +++ b/sapi/fpm/tests/gh9981-fastcgi-error-header-reset.phpt @@ -0,0 +1,51 @@ +--TEST-- +FPM: gh9981 - fastcgi.error_header is not reset +--SKIPIF-- + +--FILE-- +start(iniEntries: [ + 'fastcgi.error_header' => '"HTTP/1.1 500 PHP Error"', + 'output_buffering' => 4096, +]); +$tester->expectLogStartNotices(); +$tester->request()->expectStatus('500 PHP Error'); +$tester->request('q=1')->expectNoStatus(); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->expectNoLogPattern('/Cannot modify header information/'); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/response.inc b/sapi/fpm/tests/response.inc index 9112da6ed7756..99290e72f41d4 100644 --- a/sapi/fpm/tests/response.inc +++ b/sapi/fpm/tests/response.inc @@ -134,6 +134,36 @@ class Response return $this; } + /** + * Expect response status. + * + * @param string|null $status Expected status. + * + * @return Response + */ + public function expectStatus(string|null $status): Response { + $headers = $this->getHeaders(); + if (is_null($status) && !isset($headers['status'])) { + return $this; + } + if (!is_null($status) && !isset($headers['status'])) { + $this->error('Status is expected but not supplied'); + } elseif ($status !== $headers['status']) { + $statusMessage = $status === null ? "expected not to be set": "expected to be $status"; + $this->error("Status is $statusMessage but the actual value is {$headers['status']}"); + } + return $this; + } + + /** + * Expect response status not to be set. + * + * @return Response + */ + public function expectNoStatus(): Response { + return $this->expectStatus(null); + } + /** * Expect no error in the response. * From 0464524292635eb5de1764845f52e7aa877138e7 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 26 Dec 2022 13:20:55 +0300 Subject: [PATCH 29/83] Fix memory leak because of incorrect optimization Fixes oss-fuzz #54488 --- Zend/Optimizer/block_pass.c | 7 +++++++ ext/opcache/tests/opt/match_002.phpt | 15 +++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 ext/opcache/tests/opt/match_002.phpt diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index b176ba2704e26..e522f65067d89 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -256,6 +256,13 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array } break; + case ZEND_MATCH_ERROR: + if (opline->op1_type == IS_TMP_VAR) { + src = VAR_SOURCE(opline->op1); + VAR_SOURCE(opline->op1) = NULL; + } + break; + case ZEND_FREE: if (opline->op1_type == IS_TMP_VAR) { src = VAR_SOURCE(opline->op1); diff --git a/ext/opcache/tests/opt/match_002.phpt b/ext/opcache/tests/opt/match_002.phpt new file mode 100644 index 0000000000000..ecda31ee7c0ec --- /dev/null +++ b/ext/opcache/tests/opt/match_002.phpt @@ -0,0 +1,15 @@ +--TEST-- +Match 002: memory leak because of incorrect optimization +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Error: Undefined constant "y" in %smatch_002.php:2 +Stack trace: +#0 {main} + thrown in %smatch_002.php on line 2 From 21d8980d274e38ea8f9987498dde5ddb1b4b2f90 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 23 Dec 2022 19:24:57 +0000 Subject: [PATCH 30/83] Fix bug #68591: Configuration test does not perform UID lookups Addition check in fpm config test to verify existence of user, group, listen.owner and listen.group. Closes GH-10165 --- NEWS | 2 + sapi/fpm/fpm/fpm_conf.c | 7 ++ sapi/fpm/fpm/fpm_unix.c | 75 +++++++++++++++---- sapi/fpm/fpm/fpm_unix.h | 2 + sapi/fpm/tests/bug68591-conf-test-group.phpt | 38 ++++++++++ .../bug68591-conf-test-listen-group.phpt | 38 ++++++++++ .../bug68591-conf-test-listen-owner.phpt | 38 ++++++++++ sapi/fpm/tests/bug68591-conf-test-user.phpt | 38 ++++++++++ sapi/fpm/tests/tester.inc | 29 ++++--- 9 files changed, 242 insertions(+), 25 deletions(-) create mode 100644 sapi/fpm/tests/bug68591-conf-test-group.phpt create mode 100644 sapi/fpm/tests/bug68591-conf-test-listen-group.phpt create mode 100644 sapi/fpm/tests/bug68591-conf-test-listen-owner.phpt create mode 100644 sapi/fpm/tests/bug68591-conf-test-user.phpt diff --git a/NEWS b/NEWS index 26ce34b3cea7f..2c52262b7ff8a 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ PHP NEWS . Fixed bug #77106 (Missing separator in FPM FastCGI errors). (Jakub Zelenka) . Fixed bug GH-9981 (FPM does not reset fastcgi.error_header). (Jakub Zelenka) + . Fixed bug #68591 (Configuration test does not perform UID lookups). + (Jakub Zelenka) - LDAP: . Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()). diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c index f2d9d3c088a75..ef9b35a9994aa 100644 --- a/sapi/fpm/fpm/fpm_conf.c +++ b/sapi/fpm/fpm/fpm_conf.c @@ -34,6 +34,7 @@ #include "fpm_status.h" #include "fpm_log.h" #include "fpm_events.h" +#include "fpm_unix.h" #include "zlog.h" #ifdef HAVE_SYSTEMD #include "fpm_systemd.h" @@ -1854,6 +1855,12 @@ int fpm_conf_init_main(int test_conf, int force_daemon) /* {{{ */ } if (test_conf) { + for (struct fpm_worker_pool_s *wp = fpm_worker_all_pools; wp; wp = wp->next) { + if (!fpm_unix_test_config(wp)) { + return -1; + } + } + if (test_conf > 1) { fpm_conf_dump(); } diff --git a/sapi/fpm/fpm/fpm_unix.c b/sapi/fpm/fpm/fpm_unix.c index b1127b35949d3..d10a6f3254b24 100644 --- a/sapi/fpm/fpm/fpm_unix.c +++ b/sapi/fpm/fpm/fpm_unix.c @@ -46,6 +46,55 @@ size_t fpm_pagesize; + +static inline bool fpm_unix_is_id(const char* name) +{ + return strlen(name) == strspn(name, "0123456789"); +} + +static struct passwd *fpm_unix_get_passwd(struct fpm_worker_pool_s *wp, const char *name, int flags) +{ + struct passwd *pwd = getpwnam(name); + if (!pwd) { + zlog(flags, "[pool %s] cannot get uid for user '%s'", wp->config->name, name); + return NULL; + } + + return pwd; +} + +static inline bool fpm_unix_check_passwd(struct fpm_worker_pool_s *wp, const char *name, int flags) +{ + return !name || fpm_unix_is_id(name) || fpm_unix_get_passwd(wp, name, flags); +} + +static struct group *fpm_unix_get_group(struct fpm_worker_pool_s *wp, const char *name, int flags) +{ + struct group *group = getgrnam(name); + if (!group) { + zlog(flags, "[pool %s] cannot get gid for group '%s'", wp->config->name, name); + return NULL; + } + + return group; +} + +static inline bool fpm_unix_check_group(struct fpm_worker_pool_s *wp, const char *name, int flags) +{ + return !name || fpm_unix_is_id(name) || fpm_unix_get_group(wp, name, flags); +} + +bool fpm_unix_test_config(struct fpm_worker_pool_s *wp) +{ + struct fpm_worker_pool_config_s *config = wp->config; + return ( + fpm_unix_check_passwd(wp, config->user, ZLOG_ERROR) && + fpm_unix_check_group(wp, config->group, ZLOG_ERROR) && + fpm_unix_check_passwd(wp, config->listen_owner, ZLOG_SYSERROR) && + fpm_unix_check_group(wp, config->listen_group, ZLOG_SYSERROR) + ); +} + int fpm_unix_resolve_socket_permissions(struct fpm_worker_pool_s *wp) /* {{{ */ { struct fpm_worker_pool_config_s *c = wp->config; @@ -105,11 +154,10 @@ int fpm_unix_resolve_socket_permissions(struct fpm_worker_pool_s *wp) /* {{{ */ if ((end = strchr(p, ','))) { *end++ = 0; } - pwd = getpwnam(p); + pwd = fpm_unix_get_passwd(wp, p, ZLOG_SYSERROR); if (pwd) { zlog(ZLOG_DEBUG, "[pool %s] user '%s' have uid=%d", wp->config->name, p, pwd->pw_uid); } else { - zlog(ZLOG_SYSERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, p); acl_free(acl); efree(tmp); return -1; @@ -138,11 +186,10 @@ int fpm_unix_resolve_socket_permissions(struct fpm_worker_pool_s *wp) /* {{{ */ if ((end = strchr(p, ','))) { *end++ = 0; } - grp = getgrnam(p); + grp = fpm_unix_get_group(wp, p, ZLOG_SYSERROR); if (grp) { zlog(ZLOG_DEBUG, "[pool %s] group '%s' have gid=%d", wp->config->name, p, grp->gr_gid); } else { - zlog(ZLOG_SYSERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, p); acl_free(acl); efree(tmp); return -1; @@ -175,14 +222,13 @@ int fpm_unix_resolve_socket_permissions(struct fpm_worker_pool_s *wp) /* {{{ */ #endif if (c->listen_owner && *c->listen_owner) { - if (strlen(c->listen_owner) == strspn(c->listen_owner, "0123456789")) { + if (fpm_unix_is_id(c->listen_owner)) { wp->socket_uid = strtoul(c->listen_owner, 0, 10); } else { struct passwd *pwd; - pwd = getpwnam(c->listen_owner); + pwd = fpm_unix_get_passwd(wp, c->listen_owner, ZLOG_SYSERROR); if (!pwd) { - zlog(ZLOG_SYSERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, c->listen_owner); return -1; } @@ -192,14 +238,13 @@ int fpm_unix_resolve_socket_permissions(struct fpm_worker_pool_s *wp) /* {{{ */ } if (c->listen_group && *c->listen_group) { - if (strlen(c->listen_group) == strspn(c->listen_group, "0123456789")) { + if (fpm_unix_is_id(c->listen_group)) { wp->socket_gid = strtoul(c->listen_group, 0, 10); } else { struct group *grp; - grp = getgrnam(c->listen_group); + grp = fpm_unix_get_group(wp, c->listen_group, ZLOG_SYSERROR); if (!grp) { - zlog(ZLOG_SYSERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, c->listen_group); return -1; } wp->socket_gid = grp->gr_gid; @@ -279,7 +324,7 @@ static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */ if (is_root) { if (wp->config->user && *wp->config->user) { - if (strlen(wp->config->user) == strspn(wp->config->user, "0123456789")) { + if (fpm_unix_is_id(wp->config->user)) { wp->set_uid = strtoul(wp->config->user, 0, 10); pwd = getpwuid(wp->set_uid); if (pwd) { @@ -289,9 +334,8 @@ static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */ } else { struct passwd *pwd; - pwd = getpwnam(wp->config->user); + pwd = fpm_unix_get_passwd(wp, wp->config->user, ZLOG_ERROR); if (!pwd) { - zlog(ZLOG_ERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, wp->config->user); return -1; } @@ -304,14 +348,13 @@ static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */ } if (wp->config->group && *wp->config->group) { - if (strlen(wp->config->group) == strspn(wp->config->group, "0123456789")) { + if (fpm_unix_is_id(wp->config->group)) { wp->set_gid = strtoul(wp->config->group, 0, 10); } else { struct group *grp; - grp = getgrnam(wp->config->group); + grp = fpm_unix_get_group(wp, wp->config->group, ZLOG_ERROR); if (!grp) { - zlog(ZLOG_ERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, wp->config->group); return -1; } wp->set_gid = grp->gr_gid; diff --git a/sapi/fpm/fpm/fpm_unix.h b/sapi/fpm/fpm/fpm_unix.h index 0bb22687b02f9..6fc9e5e8450dc 100644 --- a/sapi/fpm/fpm/fpm_unix.h +++ b/sapi/fpm/fpm/fpm_unix.h @@ -5,6 +5,8 @@ #include "fpm_worker_pool.h" +bool fpm_unix_test_config(struct fpm_worker_pool_s *wp); + int fpm_unix_resolve_socket_permissions(struct fpm_worker_pool_s *wp); int fpm_unix_set_socket_permissions(struct fpm_worker_pool_s *wp, const char *path); int fpm_unix_free_socket_permissions(struct fpm_worker_pool_s *wp); diff --git a/sapi/fpm/tests/bug68591-conf-test-group.phpt b/sapi/fpm/tests/bug68591-conf-test-group.phpt new file mode 100644 index 0000000000000..14d6390801163 --- /dev/null +++ b/sapi/fpm/tests/bug68591-conf-test-group.phpt @@ -0,0 +1,38 @@ +--TEST-- +FPM: bug68591 - config test group existence +--SKIPIF-- + +--FILE-- +testConfig(); + +?> +Done +--EXPECT-- +ERROR: [pool unconfined] cannot get gid for group 'aaaaaa' +ERROR: FPM initialization failed +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/bug68591-conf-test-listen-group.phpt b/sapi/fpm/tests/bug68591-conf-test-listen-group.phpt new file mode 100644 index 0000000000000..a98f32aa40a6c --- /dev/null +++ b/sapi/fpm/tests/bug68591-conf-test-listen-group.phpt @@ -0,0 +1,38 @@ +--TEST-- +FPM: bug68591 - config test listen group existence +--SKIPIF-- + +--FILE-- +testConfig(); + +?> +Done +--EXPECTF-- +ERROR: [pool unconfined] cannot get gid for group 'aaaaaa': %s +ERROR: FPM initialization failed +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/bug68591-conf-test-listen-owner.phpt b/sapi/fpm/tests/bug68591-conf-test-listen-owner.phpt new file mode 100644 index 0000000000000..e649117026750 --- /dev/null +++ b/sapi/fpm/tests/bug68591-conf-test-listen-owner.phpt @@ -0,0 +1,38 @@ +--TEST-- +FPM: bug68591 - config test listen owner existence +--SKIPIF-- + +--FILE-- +testConfig(); + +?> +Done +--EXPECTF-- +ERROR: [pool unconfined] cannot get uid for user 'aaaaaa': %s +ERROR: FPM initialization failed +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/bug68591-conf-test-user.phpt b/sapi/fpm/tests/bug68591-conf-test-user.phpt new file mode 100644 index 0000000000000..5627151f3f13e --- /dev/null +++ b/sapi/fpm/tests/bug68591-conf-test-user.phpt @@ -0,0 +1,38 @@ +--TEST-- +FPM: bug68591 - config test user existence +--SKIPIF-- + +--FILE-- +testConfig(); + +?> +Done +--EXPECT-- +ERROR: [pool unconfined] cannot get uid for user 'aaaaaa' +ERROR: FPM initialization failed +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index 50de960aa8dde..db8f0c04f4a61 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -269,10 +269,11 @@ class Tester static public function skipIfConfigFails(string $configTemplate) { $tester = new self($configTemplate, '', [], self::getCallerFileName()); - $testResult = $tester->testConfig(); + $testResult = $tester->testConfig(true); if ($testResult !== null) { self::clean(2); - die("skip $testResult"); + $message = $testResult[0] ?? 'Config failed'; + die("skip $message"); } } @@ -378,17 +379,26 @@ class Tester /** * Test configuration file. * - * @return null|string + * @return null|array * @throws \Exception */ - public function testConfig() + public function testConfig($silent = false) { $configFile = $this->createConfig(); $cmd = self::findExecutable() . ' -tt -y ' . $configFile . ' 2>&1'; $this->trace('Testing config using command', $cmd, true); exec($cmd, $output, $code); if ($code) { - return preg_replace("/\[.+?\]/", "", $output[0]); + $messages = []; + foreach ($output as $outputLine) { + $message = preg_replace("/\[.+?\]/", "", $outputLine, 1); + $messages[] = $message; + if ( ! $silent) { + $this->error($message, null, false); + } + } + + return $messages; } return null; @@ -1259,14 +1269,15 @@ class Tester /** * Display error. * - * @param string $msg - * @param \Exception|null $exception + * @param string $msg Error message. + * @param \Exception|null $exception If there is an exception, log its message + * @param bool $prefix Whether to prefix the error message * * @return false */ - private function error($msg, \Exception $exception = null): bool + private function error(string $msg, \Exception $exception = null, bool $prefix = true): bool { - $this->error = 'ERROR: ' . $msg; + $this->error = $prefix ? 'ERROR: ' . $msg : ltrim($msg); if ($exception) { $this->error .= '; EXCEPTION: ' . $exception->getMessage(); } From b26b758952d0073156d861f0145e5b36f943e0df Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 22 Dec 2022 13:02:52 +0100 Subject: [PATCH 31/83] ext/opcache/jit: handle zend_jit_find_trace() failures Commit 6c25413 added the flag ZEND_JIT_EXIT_INVALIDATE which resets the trace handlers in zend_jit_trace_exit(), but forgot to consider that on ZEND_JIT_TRACE_STOP_LINK, this changed handler gets passed to zend_jit_find_trace(), causing it to fail, either by returning 0 (results in bogus data) or by aborting due to ZEND_UNREACHABLE(). In either case, this crashes the PHP process. I'm not quite sure how to fix this multi-threading problem properly; my suggestion is to just fail the zend_jit_trace() call. After all, the whole ZEND_JIT_EXIT_INVALIDATE fix was about reloading modified scripts, so there's probably no point in this pending zend_jit_trace() call. --- NEWS | 1 + ext/opcache/jit/zend_jit_trace.c | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 5cde54978395f..2ef70d371d116 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,7 @@ PHP NEWS - Opcache: . Fix inverted bailout value in zend_runtime_jit() (Max Kellermann). . Fix access to uninitialized variable in accel_preload(). (nielsdos) + . Fix zend_jit_find_trace() crashes. (Max Kellermann) - PHPDBG: . Fix undefined behaviour in phpdbg_load_module_or_extension(). (nielsdos) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 5aa450d096bdc..fc42add8bf1e3 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -247,6 +247,13 @@ static void zend_jit_trace_add_code(const void *start, uint32_t size) t->code_size = size; } +/** + * Locate a trace in the #zend_jit_traces array with the specified + * #code_start address. + * + * @return the #zend_jit_traces index or 0 if no such #code_start + * address was found + */ static uint32_t zend_jit_find_trace(const void *addr) { uint32_t i; @@ -256,7 +263,6 @@ static uint32_t zend_jit_find_trace(const void *addr) return i; } } - ZEND_UNREACHABLE(); return 0; } @@ -6843,6 +6849,15 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par const void *timeout_exit_addr = NULL; t->link = zend_jit_find_trace(p->opline->handler); + if (t->link == 0) { + /* this can happen if ZEND_JIT_EXIT_INVALIDATE was handled + * by zend_jit_trace_exit() in another thread after this + * thread set ZEND_JIT_TRACE_STOP_LINK in zend_jit_trace_execute(); + * ZEND_JIT_EXIT_INVALIDATE resets the opline handler to one of + * the "_counter_handler" functions, and these are not registered + * tracer functions */ + goto jit_failure; + } if ((zend_jit_traces[t->link].flags & ZEND_JIT_TRACE_USES_INITIAL_IP) && !zend_jit_set_ip(&dasm_state, p->opline)) { goto jit_failure; From e217138b4004dcc92a465a39b5fedff117d5d946 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 19 Dec 2022 22:35:22 +0100 Subject: [PATCH 32/83] ext/opcache/jit/zend_jit_trace: add missing lock for EXIT_INVALIDATE Commit 6c254131831 added the flag ZEND_JIT_EXIT_INVALIDATE which resets the trace handlers in zend_jit_trace_exit(), but forgot to lock the shared memory section. This could cause another worker process who still saw the ZEND_JIT_TRACE_JITED flag to schedule ZEND_JIT_TRACE_STOP_LINK, but when it arrived at the ZEND_JIT_DEBUG_TRACE_STOP, the handler was already reverted by the first worker process and thus zend_jit_find_trace() fails. This in turn generated a bogus jump offset in the JITed code, crashing the PHP process. --- NEWS | 1 + ext/opcache/jit/zend_jit_trace.c | 36 +++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index 2ef70d371d116..39260e4f70475 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,7 @@ PHP NEWS . Fix inverted bailout value in zend_runtime_jit() (Max Kellermann). . Fix access to uninitialized variable in accel_preload(). (nielsdos) . Fix zend_jit_find_trace() crashes. (Max Kellermann) + . Added missing lock for EXIT_INVALIDATE in zend_jit_trace_exit. (Max Kellermann) - PHPDBG: . Fix undefined behaviour in phpdbg_load_module_or_extension(). (nielsdos) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index fc42add8bf1e3..56b01e7daca04 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -8141,22 +8141,34 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf t = &zend_jit_traces[num]; } - SHM_UNPROTECT(); - zend_jit_unprotect(); + zend_shared_alloc_lock(); jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(t->op_array); - if (ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_START_LOOP) { - ((zend_op*)(t->opline))->handler = (const void*)zend_jit_loop_trace_counter_handler; - } else if (ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_START_ENTER) { - ((zend_op*)(t->opline))->handler = (const void*)zend_jit_func_trace_counter_handler; - } else if (ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_START_RETURN) { - ((zend_op*)(t->opline))->handler = (const void*)zend_jit_ret_trace_counter_handler; + + /* Checks under lock, just in case something has changed while we were waiting for the lock */ + if (!(ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & (ZEND_JIT_TRACE_JITED|ZEND_JIT_TRACE_BLACKLISTED))) { + /* skip: not JIT-ed nor blacklisted */ + } else if (ZEND_JIT_TRACE_NUM >= JIT_G(max_root_traces)) { + /* skip: too many root traces */ + } else { + SHM_UNPROTECT(); + zend_jit_unprotect(); + + if (ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_START_LOOP) { + ((zend_op*)(t->opline))->handler = (const void*)zend_jit_loop_trace_counter_handler; + } else if (ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_START_ENTER) { + ((zend_op*)(t->opline))->handler = (const void*)zend_jit_func_trace_counter_handler; + } else if (ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_START_RETURN) { + ((zend_op*)(t->opline))->handler = (const void*)zend_jit_ret_trace_counter_handler; + } + ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags &= + ZEND_JIT_TRACE_START_LOOP|ZEND_JIT_TRACE_START_ENTER|ZEND_JIT_TRACE_START_RETURN; + + zend_jit_protect(); + SHM_PROTECT(); } - ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags &= - ZEND_JIT_TRACE_START_LOOP|ZEND_JIT_TRACE_START_ENTER|ZEND_JIT_TRACE_START_RETURN; - zend_jit_protect(); - SHM_PROTECT(); + zend_shared_alloc_unlock(); return 0; } From f7a19181d7a38c4930b589af5c6876ca85d5ec53 Mon Sep 17 00:00:00 2001 From: Alex Dowad Date: Wed, 28 Dec 2022 19:41:43 +0200 Subject: [PATCH 33/83] Allow 'h' and 'k' flags to be combined for mb_convert_kana The 'h' flag makes mb_convert_kana convert zenkaku hiragana to hankaku katakana; 'k' makes it convert zenkaku katakana to hankaku katakana. When working on the implementation of mb_convert_kana, I added some additional checks to catch combinations of flags which do not make sense; but there is no conflict between 'h' and 'k' (they control conversions for two disjoint ranges of codepoints) and this combination should not have been restricted. Thanks to the GitHub user 'akira345' for reporting this problem. Closes GH-10174. --- ext/mbstring/mbstring.c | 5 +---- ext/mbstring/tests/mb_convert_kana.phpt | 5 ++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 9735bfef80bb2..34678ea3d0f7f 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -3185,10 +3185,7 @@ PHP_FUNCTION(mb_convert_kana) * or all FW hiragana to FW katakana, or all FW katakana to FW hiragana, but not * more than one of these */ if (opt & MBFL_ZEN2HAN_HIRAGANA) { - if (opt & MBFL_ZEN2HAN_KATAKANA) { - zend_argument_value_error(2, "must not combine 'h' and 'k' flags"); - RETURN_THROWS(); - } else if (opt & MBFL_ZENKAKU_HIRA2KATA) { + if (opt & MBFL_ZENKAKU_HIRA2KATA) { zend_argument_value_error(2, "must not combine 'h' and 'C' flags"); RETURN_THROWS(); } else if (opt & MBFL_ZENKAKU_KATA2HIRA) { diff --git a/ext/mbstring/tests/mb_convert_kana.phpt b/ext/mbstring/tests/mb_convert_kana.phpt index 69ea5560d4803..b263fec0f1b67 100644 --- a/ext/mbstring/tests/mb_convert_kana.phpt +++ b/ext/mbstring/tests/mb_convert_kana.phpt @@ -78,6 +78,7 @@ echo bin2hex(mb_convert_kana("\x30\x9B", 'k', 'UTF-16BE')), "\n"; echo bin2hex(mb_convert_kana("\x30\x9C", 'k', 'UTF-16BE')), "\n"; echo bin2hex(mb_convert_kana("\x30\xFC", 'k', 'UTF-16BE')), "\n"; echo bin2hex(mb_convert_kana("\x30\xFB", 'k', 'UTF-16BE')), "\n"; +echo bin2hex(mb_convert_kana("fooあいうエオ", "rnaskh", "UTF-8")), "\n"; echo "Including one which will expand to two codepoints:\n"; echo bin2hex(mb_convert_kana("\x30\x52", 'h', 'UTF-16BE')), "\n\n"; @@ -117,7 +118,6 @@ tryIncompatibleFlags('R', 'r'); tryIncompatibleFlags('N', 'n'); tryIncompatibleFlags('S', 's'); tryIncompatibleFlags('K', 'H'); -tryIncompatibleFlags('k', 'h'); tryIncompatibleFlags('C', 'c'); tryIncompatibleFlags('M', 'm'); tryIncompatibleFlags('h', 'C'); @@ -204,6 +204,7 @@ ff9e ff9f ff70 ff65 +666f6fefbdb1efbdb2efbdb3efbdb4efbdb5 Including one which will expand to two codepoints: ff79ff9e @@ -237,8 +238,6 @@ mb_convert_kana(): Argument #2 ($mode) must not combine 'S' and 's' flags mb_convert_kana(): Argument #2 ($mode) must not combine 'S' and 's' flags mb_convert_kana(): Argument #2 ($mode) must not combine 'H' and 'K' flags mb_convert_kana(): Argument #2 ($mode) must not combine 'H' and 'K' flags -mb_convert_kana(): Argument #2 ($mode) must not combine 'h' and 'k' flags -mb_convert_kana(): Argument #2 ($mode) must not combine 'h' and 'k' flags mb_convert_kana(): Argument #2 ($mode) must not combine 'C' and 'c' flags mb_convert_kana(): Argument #2 ($mode) must not combine 'C' and 'c' flags mb_convert_kana(): Argument #2 ($mode) must not combine 'M' and 'm' flags From 3a44c78f14015625e5cea9d999b642afc153285a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 26 Dec 2022 21:43:53 +0100 Subject: [PATCH 34/83] Fix null pointer dereference of param When the validation logic for param->type was added, the logic did not account for the case where param could be NULL. The existing code did take that into account as can be seen in the `if (param)` check below. Furthermore, phpdbg_set_breakpoint_expression even calls phpdbg_create_conditional_break with param == NULL. Fix it by placing the validation logic inside a NULL check. --- NEWS | 1 + sapi/phpdbg/phpdbg_bp.c | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index 39260e4f70475..8553567777a4f 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,7 @@ PHP NEWS - PHPDBG: . Fix undefined behaviour in phpdbg_load_module_or_extension(). (nielsdos) + . Fix NULL pointer dereference in phpdbg_create_conditional_breal(). (nielsdos) - TSRM: . Fixed Windows shmget() wrt. IPC_PRIVATE. (Tyson Andre) diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index e48ed5ceba2a9..aa35402cfe6e6 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -829,19 +829,21 @@ static inline void phpdbg_create_conditional_break(phpdbg_breakcond_t *brake, co uint32_t cops = CG(compiler_options); zend_string *bp_code; - switch (param->type) { - case STR_PARAM: - case NUMERIC_FUNCTION_PARAM: - case METHOD_PARAM: - case NUMERIC_METHOD_PARAM: - case FILE_PARAM: - case ADDR_PARAM: - /* do nothing */ - break; + if (param) { + switch (param->type) { + case STR_PARAM: + case NUMERIC_FUNCTION_PARAM: + case METHOD_PARAM: + case NUMERIC_METHOD_PARAM: + case FILE_PARAM: + case ADDR_PARAM: + /* do nothing */ + break; - default: - phpdbg_error("Invalid parameter type for conditional breakpoint"); - return; + default: + phpdbg_error("Invalid parameter type for conditional breakpoint"); + return; + } } PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_COND); From c2b0be5570aeae64c327021677b14d8dc84e4a3b Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 30 Dec 2022 15:11:09 +0000 Subject: [PATCH 35/83] Fix memory leak in posix_ttyname() Closes GH-10190 --- NEWS | 3 +++ ext/posix/posix.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 8553567777a4f..62a771f4c568b 100644 --- a/NEWS +++ b/NEWS @@ -31,6 +31,9 @@ PHP NEWS . Fix undefined behaviour in phpdbg_load_module_or_extension(). (nielsdos) . Fix NULL pointer dereference in phpdbg_create_conditional_breal(). (nielsdos) +- Posix: + . Fix memory leak in posix_ttyname() (girgias) + - TSRM: . Fixed Windows shmget() wrt. IPC_PRIVATE. (Tyson Andre) diff --git a/ext/posix/posix.c b/ext/posix/posix.c index e6655f0d95b3b..d32f1cfa0488d 100644 --- a/ext/posix/posix.c +++ b/ext/posix/posix.c @@ -547,15 +547,15 @@ PHP_FUNCTION(posix_ttyname) efree(p); RETURN_FALSE; } - RETURN_STRING(p); + RETVAL_STRING(p); efree(p); #else if (NULL == (p = ttyname(fd))) { POSIX_G(last_error) = errno; RETURN_FALSE; } -#endif RETURN_STRING(p); +#endif } /* }}} */ From 4c9375e504a6ba15de56fcf6b630d8c95155057d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 30 Dec 2022 14:31:40 +0100 Subject: [PATCH 36/83] Fix GH-10187: Segfault in stripslashes() with arm64 Closes GH-10188 Co-authored-by: todeveni Signed-off-by: George Peter Banyard --- NEWS | 3 +++ ext/standard/string.c | 18 +++++++++++------- ext/standard/tests/strings/gh10187.phpt | 8 ++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 ext/standard/tests/strings/gh10187.phpt diff --git a/NEWS b/NEWS index 62a771f4c568b..feb6e882ff55a 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,9 @@ PHP NEWS - Posix: . Fix memory leak in posix_ttyname() (girgias) +- Standard: + . Fix GH-10187 (Segfault in stripslashes() with arm64). (nielsdos) + - TSRM: . Fixed Windows shmget() wrt. IPC_PRIVATE. (Tyson Andre) diff --git a/ext/standard/string.c b/ext/standard/string.c index 8a223b72f4e33..e171448f243e1 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -3988,19 +3988,23 @@ static zend_always_inline char *php_stripslashes_impl(const char *str, char *out quad_word q; vst1q_u8(q.mem, vceqq_u8(x, vdupq_n_u8('\\'))); if (q.dw[0] | q.dw[1]) { - int i = 0; - for (; i < 16; i++) { + unsigned int i = 0; + while (i < 16) { if (q.mem[i] == 0) { *out++ = str[i]; + i++; continue; } i++; /* skip the slash */ - char s = str[i]; - if (s == '0') - *out++ = '\0'; - else - *out++ = s; /* preserve the next character */ + if (i < len) { + char s = str[i]; + if (s == '0') + *out++ = '\0'; + else + *out++ = s; /* preserve the next character */ + i++; + } } str += i; len -= i; diff --git a/ext/standard/tests/strings/gh10187.phpt b/ext/standard/tests/strings/gh10187.phpt new file mode 100644 index 0000000000000..b42c95e591ed0 --- /dev/null +++ b/ext/standard/tests/strings/gh10187.phpt @@ -0,0 +1,8 @@ +--TEST-- +GH-10187 (Segfault in stripslashes() with arm64) +--FILE-- + +--EXPECT-- +string(15) "1234567890abcde" From eebf3bc0babb60227e7ac891bddeb296e2fc9149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Sun, 18 Dec 2022 22:32:37 +0100 Subject: [PATCH 37/83] Better document constructors Until https://github.com/php/php-src/pull/10098 default constructors were sometimes documented, sometimes omitted. The above PR made adding documentation for constructor of all non-abstract classes required. However, this is not desired when such a class inherits a constructor from its parent. The current PR fixes the behavior the following way: - documents inherited constructors (along with destructors) - makes it possible to generate/replace the methodsynopsis of implicit default constructors which don't have a stub counterpart --- build/gen_stub.php | 159 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 129 insertions(+), 30 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 7e89007948fe6..8d8344062ef06 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2700,17 +2700,18 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera } $classSynopsisInfo->appendChild(new DOMText("\n ")); - /** @var Name[] $parentsWithInheritedConstants */ + /** @var array $parentsWithInheritedConstants */ $parentsWithInheritedConstants = []; - /** @var Name[] $parentsWithInheritedProperties */ + /** @var array $parentsWithInheritedProperties */ $parentsWithInheritedProperties = []; - /** @var Name[] $parentsWithInheritedMethods */ + /** @var array $parentsWithInheritedMethods */ $parentsWithInheritedMethods = []; $this->collectInheritedMembers( $parentsWithInheritedConstants, $parentsWithInheritedProperties, $parentsWithInheritedMethods, + $this->hasConstructor(), $classMap ); @@ -2756,9 +2757,9 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera "&InheritedProperties;" ); - $isConcreteClass = ($this->type === "class" && !($this->flags & Class_::MODIFIER_ABSTRACT)); + $isConcreteClassWithoutParentConstructor = $this->isConcreteClassWithoutParentConstructor($classMap); - if ($isConcreteClass || !empty($this->funcInfos)) { + if ($isConcreteClassWithoutParentConstructor || !empty($this->funcInfos)) { $classSynopsis->appendChild(new DOMText("\n\n ")); $classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Methods;"); $classSynopsisInfo->setAttribute("role", "comment"); @@ -2768,7 +2769,7 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera $classReference = self::getClassSynopsisReference($this->name); $escapedName = addslashes($this->name->__toString()); - if ($isConcreteClass || $this->hasConstructor()) { + if ($isConcreteClassWithoutParentConstructor || $this->hasConstructor()) { $classSynopsis->appendChild(new DOMText("\n ")); $includeElement = $this->createIncludeElement( $doc, @@ -2802,14 +2803,21 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera $classSynopsis->appendChild($classSynopsisInfo); foreach ($parentsWithInheritedMethods as $parent) { - $classSynopsis->appendChild(new DOMText("\n ")); - $parentReference = self::getClassSynopsisReference($parent); - $escapedParentName = addslashes($parent->__toString()); - $includeElement = $this->createIncludeElement( - $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$parentReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[@role='$escapedParentName'])" - ); - $classSynopsis->appendChild($includeElement); + $parentName = $parent["name"]; + $parentMethodsynopsisTypes = $parent["types"]; + + $parentReference = self::getClassSynopsisReference($parentName); + $escapedParentName = addslashes($parentName->__toString()); + + foreach ($parentMethodsynopsisTypes as $parentMethodsynopsisType) { + $classSynopsis->appendChild(new DOMText("\n ")); + $includeElement = $this->createIncludeElement( + $doc, + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$parentReference')/db:refentry/db:refsect1[@role='description']/descendant::db:{$parentMethodsynopsisType}[@role='$escapedParentName'])" + ); + + $classSynopsis->appendChild($includeElement); + } } } @@ -2818,6 +2826,31 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera return $classSynopsis; } + /** + * @param array $classMap + */ + public function getNonExistentDefaultConstructorForManual(array $classMap): ?FuncInfo { + if (!$this->isConcreteClassWithoutParentConstructor($classMap) || $this->hasConstructor()) { + return null; + } + + return new FuncInfo( + new MethodName($this->name, "__construct"), + $this->flags, + 0, + null, + null, + false, + false, + true, + [], + new ReturnInfo(false, null, null, false, null), + 0, + null, + false + ); + } + private static function createOoElement( DOMDocument $doc, ClassInfo $classInfo, @@ -2867,39 +2900,54 @@ public static function getClassSynopsisReference(Name $name): string { } /** - * @param Name[] $parentsWithInheritedConstants - * @param Name[] $parentsWithInheritedProperties - * @param Name[] $parentsWithInheritedMethods + * @param array $parentsWithInheritedConstants + * @param array $parentsWithInheritedProperties + * @param array $parentsWithInheritedMethods * @param array $classMap */ private function collectInheritedMembers( array &$parentsWithInheritedConstants, array &$parentsWithInheritedProperties, array &$parentsWithInheritedMethods, + bool $hasConstructor, array $classMap ): void { foreach ($this->extends as $parent) { $parentInfo = $classMap[$parent->toString()] ?? null; + $parentName = $parent->toString(); + if (!$parentInfo) { - throw new Exception("Missing parent class " . $parent->toString()); + throw new Exception("Missing parent class $parentName"); } - if (!empty($parentInfo->constInfos) && !isset($parentsWithInheritedConstants[$parent->toString()])) { - $parentsWithInheritedConstants[$parent->toString()] = $parent; + if (!empty($parentInfo->constInfos) && !isset($parentsWithInheritedConstants[$parentName])) { + $parentsWithInheritedConstants[] = $parent; + } + + if (!empty($parentInfo->propertyInfos) && !isset($parentsWithInheritedProperties[$parentName])) { + $parentsWithInheritedProperties[$parentName] = $parent; } - if (!empty($parentInfo->propertyInfos) && !isset($parentsWithInheritedProperties[$parent->toString()])) { - $parentsWithInheritedProperties[$parent->toString()] = $parent; + if (!$hasConstructor && $parentInfo->hasConstructor()) { + $parentsWithInheritedMethods[$parentName]["name"] = $parent; + $parentsWithInheritedMethods[$parentName]["types"][] = "constructorsynopsis"; } - if (!isset($parentsWithInheritedMethods[$parent->toString()]) && $parentInfo->hasMethods()) { - $parentsWithInheritedMethods[$parent->toString()] = $parent; + if ($parentInfo->hasMethods()) { + $parentsWithInheritedMethods[$parentName]["name"] = $parent; + $parentsWithInheritedMethods[$parentName]["types"][] = "methodsynopsis"; + } + + if ($parentInfo->hasDestructor()) { + $parentsWithInheritedMethods[$parentName]["name"] = $parent; + $parentsWithInheritedMethods[$parentName]["types"][] = "destructorsynopsis"; } $parentInfo->collectInheritedMembers( $parentsWithInheritedConstants, $parentsWithInheritedProperties, $parentsWithInheritedMethods, + $hasConstructor, $classMap ); } @@ -2921,6 +2969,7 @@ private function collectInheritedMembers( $parentsWithInheritedConstants, $unusedParentsWithInheritedProperties, $unusedParentsWithInheritedMethods, + $hasConstructor, $classMap ); } @@ -2937,6 +2986,29 @@ private function hasConstructor(): bool return false; } + /** + * @param array $classMap + */ + private function hasParentConstructor(array $classMap): bool + { + foreach ($this->extends as $parentName) { + $parent = $classMap[$parentName->toString()] ?? null; + if ($parent === null) { + throw new Exception("Missing parent class " . $parent->toString()); + } + + if ($parent->hasConstructor()) { + return true; + } + + if ($parent->hasParentConstructor($classMap)) { + return true; + } + } + + return false; + } + private function hasDestructor(): bool { foreach ($this->funcInfos as $funcInfo) { @@ -2959,6 +3031,13 @@ private function hasMethods(): bool return false; } + /** + * @param array $classMap + */ + private function isConcreteClassWithoutParentConstructor(array $classMap) { + return $this->type === "class" && !($this->flags & Class_::MODIFIER_ABSTRACT) && !$this->hasParentConstructor($classMap); + } + private function createIncludeElement(DOMDocument $doc, string $query): DOMElement { $includeElement = $doc->createElement("xi:include"); @@ -3036,6 +3115,18 @@ public function getAllFuncInfos(): iterable { } } + /** + * @return array $classMap + */ + public function getAllNonExistentDefaultConstructorsForManual(array $classMap): iterable { + foreach ($this->classInfos as $classInfo) { + $funcInfo = $classInfo->getNonExistentDefaultConstructorForManual($classMap); + if ($funcInfo !== null) { + yield $funcInfo; + } + } + } + /** * @return iterable */ @@ -4058,14 +4149,14 @@ static function (FuncInfo $funcInfo) use ($allConstInfos) { ); } -/** @param FuncInfo $funcInfos */ -function generateOptimizerInfo(array $funcInfos): string { +/** @param array $funcMap */ +function generateOptimizerInfo(array $funcMap): string { $code = "/* This is a generated file, edit the .stub.php files instead. */\n\n"; $code .= "static const func_info_t func_infos[] = {\n"; - $code .= generateCodeWithConditions($funcInfos, "", static function (FuncInfo $funcInfo) { + $code .= generateCodeWithConditions($funcMap, "", static function (FuncInfo $funcInfo) { return $funcInfo->getOptimizerInfo(); }); @@ -4688,7 +4779,6 @@ function initPhpParser() { foreach ($fileInfos as $fileInfo) { foreach ($fileInfo->getAllFuncInfos() as $funcInfo) { - /** @var FuncInfo $funcInfo */ $funcMap[$funcInfo->name->__toString()] = $funcInfo; // TODO: Don't use aliasMap for methodsynopsis? @@ -4702,6 +4792,15 @@ function initPhpParser() { } } +/** @var array $funcMapForManual */ +$funcMapForManual = $funcMap; + +foreach ($fileInfos as $fileInfo) { + foreach ($fileInfo->getAllNonExistentDefaultConstructorsForManual($classMap) as $funcInfo) { + $funcMapForManual[$funcInfo->name->__toString()] = $funcInfo; + } +} + if ($verify) { $errors = []; @@ -4817,7 +4916,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc if ($generateMethodSynopses) { $methodSynopsesDirectory = getcwd() . "/methodsynopses"; - $methodSynopses = generateMethodSynopses($funcMap, $aliasMap); + $methodSynopses = generateMethodSynopses($funcMapForManual, $aliasMap); if (!empty($methodSynopses)) { if (!file_exists($methodSynopsesDirectory)) { mkdir($methodSynopsesDirectory); @@ -4832,7 +4931,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc } if ($replaceMethodSynopses) { - $methodSynopses = replaceMethodSynopses($targetSynopses, $funcMap, $aliasMap, $verify); + $methodSynopses = replaceMethodSynopses($targetSynopses, $funcMapForManual, $aliasMap, $verify); foreach ($methodSynopses as $filename => $content) { if (file_put_contents($filename, $content)) { From 38e138798d23d46446549053bd8b3b557009e434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Mon, 26 Dec 2022 23:20:37 +0100 Subject: [PATCH 38/83] Do not display non-existent constructors --- build/gen_stub.php | 113 ++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 84 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 8d8344062ef06..fed766da794fc 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2757,43 +2757,41 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera "&InheritedProperties;" ); - $isConcreteClassWithoutParentConstructor = $this->isConcreteClassWithoutParentConstructor($classMap); - - if ($isConcreteClassWithoutParentConstructor || !empty($this->funcInfos)) { + if (!empty($this->funcInfos)) { $classSynopsis->appendChild(new DOMText("\n\n ")); $classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Methods;"); $classSynopsisInfo->setAttribute("role", "comment"); $classSynopsis->appendChild($classSynopsisInfo); - } - $classReference = self::getClassSynopsisReference($this->name); - $escapedName = addslashes($this->name->__toString()); + $classReference = self::getClassSynopsisReference($this->name); + $escapedName = addslashes($this->name->__toString()); - if ($isConcreteClassWithoutParentConstructor || $this->hasConstructor()) { - $classSynopsis->appendChild(new DOMText("\n ")); - $includeElement = $this->createIncludeElement( - $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:constructorsynopsis[@role='$escapedName'])" - ); - $classSynopsis->appendChild($includeElement); - } + if ($this->hasConstructor()) { + $classSynopsis->appendChild(new DOMText("\n ")); + $includeElement = $this->createIncludeElement( + $doc, + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:constructorsynopsis[@role='$escapedName'])" + ); + $classSynopsis->appendChild($includeElement); + } - if ($this->hasMethods()) { - $classSynopsis->appendChild(new DOMText("\n ")); - $includeElement = $this->createIncludeElement( - $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[@role='$escapedName'])" - ); - $classSynopsis->appendChild($includeElement); - } + if ($this->hasMethods()) { + $classSynopsis->appendChild(new DOMText("\n ")); + $includeElement = $this->createIncludeElement( + $doc, + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[@role='$escapedName'])" + ); + $classSynopsis->appendChild($includeElement); + } - if ($this->hasDestructor()) { - $classSynopsis->appendChild(new DOMText("\n ")); - $includeElement = $this->createIncludeElement( - $doc, - "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:destructorsynopsis[@role='$escapedName'])" - ); - $classSynopsis->appendChild($includeElement); + if ($this->hasDestructor()) { + $classSynopsis->appendChild(new DOMText("\n ")); + $includeElement = $this->createIncludeElement( + $doc, + "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:destructorsynopsis[@role='$escapedName'])" + ); + $classSynopsis->appendChild($includeElement); + } } if (!empty($parentsWithInheritedMethods)) { @@ -2826,31 +2824,6 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera return $classSynopsis; } - /** - * @param array $classMap - */ - public function getNonExistentDefaultConstructorForManual(array $classMap): ?FuncInfo { - if (!$this->isConcreteClassWithoutParentConstructor($classMap) || $this->hasConstructor()) { - return null; - } - - return new FuncInfo( - new MethodName($this->name, "__construct"), - $this->flags, - 0, - null, - null, - false, - false, - true, - [], - new ReturnInfo(false, null, null, false, null), - 0, - null, - false - ); - } - private static function createOoElement( DOMDocument $doc, ClassInfo $classInfo, @@ -3031,13 +3004,6 @@ private function hasMethods(): bool return false; } - /** - * @param array $classMap - */ - private function isConcreteClassWithoutParentConstructor(array $classMap) { - return $this->type === "class" && !($this->flags & Class_::MODIFIER_ABSTRACT) && !$this->hasParentConstructor($classMap); - } - private function createIncludeElement(DOMDocument $doc, string $query): DOMElement { $includeElement = $doc->createElement("xi:include"); @@ -3115,18 +3081,6 @@ public function getAllFuncInfos(): iterable { } } - /** - * @return array $classMap - */ - public function getAllNonExistentDefaultConstructorsForManual(array $classMap): iterable { - foreach ($this->classInfos as $classInfo) { - $funcInfo = $classInfo->getNonExistentDefaultConstructorForManual($classMap); - if ($funcInfo !== null) { - yield $funcInfo; - } - } - } - /** * @return iterable */ @@ -4792,15 +4746,6 @@ function initPhpParser() { } } -/** @var array $funcMapForManual */ -$funcMapForManual = $funcMap; - -foreach ($fileInfos as $fileInfo) { - foreach ($fileInfo->getAllNonExistentDefaultConstructorsForManual($classMap) as $funcInfo) { - $funcMapForManual[$funcInfo->name->__toString()] = $funcInfo; - } -} - if ($verify) { $errors = []; @@ -4916,7 +4861,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc if ($generateMethodSynopses) { $methodSynopsesDirectory = getcwd() . "/methodsynopses"; - $methodSynopses = generateMethodSynopses($funcMapForManual, $aliasMap); + $methodSynopses = generateMethodSynopses($funcMap, $aliasMap); if (!empty($methodSynopses)) { if (!file_exists($methodSynopsesDirectory)) { mkdir($methodSynopsesDirectory); @@ -4931,7 +4876,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc } if ($replaceMethodSynopses) { - $methodSynopses = replaceMethodSynopses($targetSynopses, $funcMapForManual, $aliasMap, $verify); + $methodSynopses = replaceMethodSynopses($targetSynopses, $funcMap, $aliasMap, $verify); foreach ($methodSynopses as $filename => $content) { if (file_put_contents($filename, $content)) { From 7b08fe9f2d2f5e701972cd1054bd55fea7d56fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Wed, 28 Dec 2022 15:34:50 +0100 Subject: [PATCH 39/83] Do not list private constructors as inherited --- build/gen_stub.php | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index fed766da794fc..9e6a945a5c4e7 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2901,7 +2901,7 @@ private function collectInheritedMembers( $parentsWithInheritedProperties[$parentName] = $parent; } - if (!$hasConstructor && $parentInfo->hasConstructor()) { + if (!$hasConstructor && $parentInfo->hasNonPrivateConstructor()) { $parentsWithInheritedMethods[$parentName]["name"] = $parent; $parentsWithInheritedMethods[$parentName]["types"][] = "constructorsynopsis"; } @@ -2959,22 +2959,10 @@ private function hasConstructor(): bool return false; } - /** - * @param array $classMap - */ - private function hasParentConstructor(array $classMap): bool + private function hasNonPrivateConstructor(): bool { - foreach ($this->extends as $parentName) { - $parent = $classMap[$parentName->toString()] ?? null; - if ($parent === null) { - throw new Exception("Missing parent class " . $parent->toString()); - } - - if ($parent->hasConstructor()) { - return true; - } - - if ($parent->hasParentConstructor($classMap)) { + foreach ($this->funcInfos as $funcInfo) { + if ($funcInfo->name->isConstructor() && !($funcInfo->flags & Class_::MODIFIER_PRIVATE)) { return true; } } From c2404915e016c63c1873f588cbfeb0909a314e62 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 2 Jan 2023 15:34:03 +0100 Subject: [PATCH 40/83] Fix GH-10200: zif_get_object_vars: Assertion `!(((__ht)->u.flags & (1<<2)) != 0)' failed. This occurs because the array of properties is a single element with an integer key, not an associative array. Therefore it is a packed array and thus the assumption the iteration macro makes is invalid. This restores the behaviour of PHP<8.2. Closes GH-10209 Co-authored-by: Deltik Signed-off-by: George Peter Banyard --- NEWS | 4 ++++ Zend/tests/gh10200.phpt | 20 ++++++++++++++++++++ Zend/zend_builtin_functions.c | 2 +- 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/gh10200.phpt diff --git a/NEWS b/NEWS index 341af094271f5..ba9b1c1142d3c 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.2 +- Core: + . Fixed bug GH-10200 (zif_get_object_vars: + Assertion `!(((__ht)->u.flags & (1<<2)) != 0)' failed). (nielsdos) + - FPM: . Fixed bug #77106 (Missing separator in FPM FastCGI errors). (Jakub Zelenka) . Fixed bug GH-9981 (FPM does not reset fastcgi.error_header). diff --git a/Zend/tests/gh10200.phpt b/Zend/tests/gh10200.phpt new file mode 100644 index 0000000000000..5462352e7ae5b --- /dev/null +++ b/Zend/tests/gh10200.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-10200 (zif_get_object_vars: Assertion `!(((__ht)->u.flags & (1<<2)) != 0)' failed.) +--FILE-- + +https://github.com/php/php-src/issues/10200 not encountered +EOF; + +$xml = simplexml_load_string($xmlData); +$output = get_object_vars($xml); +var_dump($output); + +?> +--EXPECT-- +array(1) { + [0]=> + string(59) "https://github.com/php/php-src/issues/10200%20not%20encountered" +} diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 8813fa9788a97..5cebbbc560894 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -760,7 +760,7 @@ ZEND_FUNCTION(get_object_vars) } else { array_init_size(return_value, zend_hash_num_elements(properties)); - ZEND_HASH_MAP_FOREACH_KEY_VAL(properties, num_key, key, value) { + ZEND_HASH_FOREACH_KEY_VAL(properties, num_key, key, value) { bool is_dynamic = 1; if (Z_TYPE_P(value) == IS_INDIRECT) { value = Z_INDIRECT_P(value); From d5f0362e59ec0408518fd0bcc6556650fdb7fa14 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 2 Jan 2023 14:30:11 +0100 Subject: [PATCH 41/83] Fix GH-10202: posix_getgr(gid|nam)_basic.phpt fail The issue was that passwd was empty for the issue reporter, but the test expected passwd to be non-empty. An empty passwd can occur if there is no (encrypted) group password set up. --- ext/posix/tests/posix_getgrgid_basic.phpt | 2 +- ext/posix/tests/posix_getgrnam_basic.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/posix/tests/posix_getgrgid_basic.phpt b/ext/posix/tests/posix_getgrgid_basic.phpt index 6b0daa5e940fc..392e81d491d61 100644 --- a/ext/posix/tests/posix_getgrgid_basic.phpt +++ b/ext/posix/tests/posix_getgrgid_basic.phpt @@ -17,7 +17,7 @@ Basic test of POSIX getgid and getgrid functions Array ( [name] => %s - [passwd] => %a + [passwd] => %A [members] => Array %a diff --git a/ext/posix/tests/posix_getgrnam_basic.phpt b/ext/posix/tests/posix_getgrnam_basic.phpt index 5203d1ea0f056..acf8f4473e5d8 100644 --- a/ext/posix/tests/posix_getgrnam_basic.phpt +++ b/ext/posix/tests/posix_getgrnam_basic.phpt @@ -20,7 +20,7 @@ array(4) { ["name"]=> string(%d) "%s" ["passwd"]=> - string(1) "%s" + string(%d) "%S" ["members"]=> %a ["gid"]=> From 4ce48e9a39073444d526960dd954db28e9a1164a Mon Sep 17 00:00:00 2001 From: Gabriel Caruso Date: Tue, 3 Jan 2023 11:36:20 -0300 Subject: [PATCH 42/83] [ci skip] Prepare for PHP 8.0.27 GA --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index c6b0036b600b9..3be34b3bfd752 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? 2022, PHP 8.0.27 +05 Jan 2023, PHP 8.0.27 - PDO/SQLite: . Fixed bug #81740 (PDO::quote() may return unquoted string). (CVE-2022-31631) From c2737b40d72c323ec51a6b026b720e1b196be85b Mon Sep 17 00:00:00 2001 From: Gabriel Caruso Date: Tue, 3 Jan 2023 11:39:21 -0300 Subject: [PATCH 43/83] [ci skip] Next release will be 8.0.28 --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 3be34b3bfd752..907a06b90ec97 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +?? ??? ????, PHP 8.0.28 + + 05 Jan 2023, PHP 8.0.27 - PDO/SQLite: From 255e08ac56539f07cdbfa2f32922f20f7d21de5c Mon Sep 17 00:00:00 2001 From: Gabriel Caruso Date: Tue, 3 Jan 2023 13:00:44 -0300 Subject: [PATCH 44/83] Revert "Make build work with newer OpenSSL" This reverts commit 5f90134bb69a345c7edb5013e6461e84caa32dbc. --- ext/openssl/openssl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 9827c75871668..45a7e794400d0 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1325,9 +1325,7 @@ PHP_MINIT_FUNCTION(openssl) REGISTER_LONG_CONSTANT("OPENSSL_CMS_NOSIGS", CMS_NOSIGS, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_PADDING", RSA_PKCS1_PADDING, CONST_CS|CONST_PERSISTENT); -#ifdef RSA_SSLV23_PADDING REGISTER_LONG_CONSTANT("OPENSSL_SSLV23_PADDING", RSA_SSLV23_PADDING, CONST_CS|CONST_PERSISTENT); -#endif REGISTER_LONG_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_CS|CONST_PERSISTENT); From bbb90d4d05ff517fc44214a6711d3ba423be4b58 Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Tue, 3 Jan 2023 14:27:16 -0500 Subject: [PATCH 45/83] [ci skip] Add missing CVE in NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index ba9b1c1142d3c..22b1a57967447 100644 --- a/NEWS +++ b/NEWS @@ -84,6 +84,10 @@ PHP NEWS . Fixed bug GH-9971 (Incorrect NUMERIC value returned from PDO_Firebird). (cmb) +- PDO/SQLite: + . Fixed bug #81740 (PDO::quote() may return unquoted string). (CVE-2022-31631) + (cmb) + - Session: . Fixed GH-9932 (session name silently fails with . and [). (David Carlier) From 275bf3beaeb2699e6a0efc7ff488399d28ef9068 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Wed, 4 Jan 2023 00:03:23 -0600 Subject: [PATCH 46/83] Update NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index feb6e882ff55a..6833d8a4ee4a7 100644 --- a/NEWS +++ b/NEWS @@ -89,6 +89,10 @@ PHP NEWS . Fixed bug GH-9971 (Incorrect NUMERIC value returned from PDO_Firebird). (cmb) +- PDO/SQLite: + . Fixed bug #81740 (PDO::quote() may return unquoted string). (CVE-2022-31631) + (cmb) + - Session: . Fixed GH-9932 (session name silently fails with . and [). (David Carlier) From d104481af822bcae68d9e3b0e0cf192297420b7f Mon Sep 17 00:00:00 2001 From: Alex Dowad Date: Wed, 4 Jan 2023 08:49:31 +0200 Subject: [PATCH 47/83] Correct entry for 0x80,0xFD-FF in SJIS multi-byte character length table As a performance optimization, mbstring implements some functions using tables which give the (byte) length of a multi-byte character using a lookup based on the value of the first byte. These tables are called `mblen_table`. For many years, the mblen_table for SJIS has had '2' in position 0x80. That is wrong; it should have been '1'. Reasons: For SJIS, SJIS-2004, and mobile variants of SJIS, 0x80 has never been treated as the first byte of a 2-byte character. It has always been treated as a single erroneous byte. On the other hand, 0x80 is a valid character in MacJapanese... but a 1-byte character, not a 2-byte one. The same applies to bytes 0xFD-FF; these are 1-byte characters in MacJapanese, and in other SJIS variants, they are not valid (as the first byte of a character). Thanks to the GitHub user 'youkidearitai' for finding this problem. --- ext/mbstring/libmbfl/filters/mbfilter_sjis.c | 6 +- ext/mbstring/tests/mb_str_split_jp.phpt | 24 +++ ext/mbstring/tests/mb_strlen.phpt | 72 ++++++--- ext/mbstring/tests/mb_substr.phpt | 156 ++++++++++++++++++- 4 files changed, 233 insertions(+), 25 deletions(-) diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis.c index cf03e9cc0db2d..9e0b053d0da73 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_sjis.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis.c @@ -38,7 +38,7 @@ static int mbfl_filt_conv_sjis_wchar_flush(mbfl_convert_filter *filter); -const unsigned char mblen_table_sjis[] = { /* 0x80-0x9f,0xE0-0xFF */ +const unsigned char mblen_table_sjis[] = { /* 0x81-0x9F,0xE0-0xFC */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -47,14 +47,14 @@ const unsigned char mblen_table_sjis[] = { /* 0x80-0x9f,0xE0-0xFF */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 }; static const char *mbfl_encoding_sjis_aliases[] = {"x-sjis", "SHIFT-JIS", NULL}; diff --git a/ext/mbstring/tests/mb_str_split_jp.phpt b/ext/mbstring/tests/mb_str_split_jp.phpt index f57531eeb25dd..674298ce3be98 100644 --- a/ext/mbstring/tests/mb_str_split_jp.phpt +++ b/ext/mbstring/tests/mb_str_split_jp.phpt @@ -62,6 +62,17 @@ if(end($array) !== $enc){ last array element: %s expected: %s\n", unpack("H*", end($array))[1],unpack("H*", $enc)[1]); } +/* SJIS byte 0x80 was previously wrongly treated as the starting byte for a 2-byte character */ +echo "== Regression test for SJIS byte 0x80 ==\n"; +foreach (['SJIS', 'SJIS-2004', 'MacJapanese', 'SJIS-Mobile#DOCOMO', 'SJIS-Mobile#KDDI', 'SJIS-Mobile#SoftBank'] as $encoding) { + $array = mb_str_split("\x80\xA1abc\x80\xA1", 2, $encoding); + echo "$encoding: [" . implode(', ', array_map('bin2hex', $array)) . "]\n"; + + // Also try bytes 0xFD, 0xFE, and 0xFF + $array = mb_str_split("abc\xFD\xFE\xFFab\xFD\xFE\xFF", 2, $encoding); + echo "$encoding: [" . implode(', ', array_map('bin2hex', $array)) . "]\n"; +} + ?> --EXPECT-- BIG-5: a4e9 a5bb @@ -73,3 +84,16 @@ UTF-16LE: e565 2c67 UTF-32BE: 000065e5 0000672c UTF-32LE: e5650000 2c670000 UTF-8: e697a5 e69cac +== Regression test for SJIS byte 0x80 == +SJIS: [80a1, 6162, 6380, a1] +SJIS: [6162, 63fd, feff, 6162, fdfe, ff] +SJIS-2004: [80a1, 6162, 6380, a1] +SJIS-2004: [6162, 63fd, feff, 6162, fdfe, ff] +MacJapanese: [80a1, 6162, 6380, a1] +MacJapanese: [6162, 63fd, feff, 6162, fdfe, ff] +SJIS-Mobile#DOCOMO: [80a1, 6162, 6380, a1] +SJIS-Mobile#DOCOMO: [6162, 63fd, feff, 6162, fdfe, ff] +SJIS-Mobile#KDDI: [80a1, 6162, 6380, a1] +SJIS-Mobile#KDDI: [6162, 63fd, feff, 6162, fdfe, ff] +SJIS-Mobile#SoftBank: [80a1, 6162, 6380, a1] +SJIS-Mobile#SoftBank: [6162, 63fd, feff, 6162, fdfe, ff] diff --git a/ext/mbstring/tests/mb_strlen.phpt b/ext/mbstring/tests/mb_strlen.phpt index 11225917140c2..5ebfcd1aec065 100644 --- a/ext/mbstring/tests/mb_strlen.phpt +++ b/ext/mbstring/tests/mb_strlen.phpt @@ -13,43 +13,59 @@ include_once('common.inc'); mb_detect_order('auto'); // Test string -$euc_jp = '0123����ʸ��������ܸ�Ǥ���EUC-JP��ȤäƤ��ޤ���0123���ܸ�����ݽ�����'; +$euc_jp = mb_convert_encoding("0123この文字列は日本語です。EUC-JPを使っています。0123日本語は面倒臭い。", 'EUC-JP', 'UTF-8'); $ascii = 'abcdefghijklmnopqrstuvwxyz;]=#0123456789'; -// ASCII echo "== ASCII ==\n"; -print mb_strlen($ascii,'ASCII') . "\n"; -print strlen($ascii) . "\n"; +print mb_strlen($ascii,'ASCII') . "\n"; +print strlen($ascii) . "\n"; -// EUC-JP echo "== EUC-JP ==\n"; -print mb_strlen($euc_jp,'EUC-JP') . "\n"; +print mb_strlen($euc_jp,'EUC-JP') . "\n"; mb_internal_encoding('EUC-JP') or print("mb_internal_encoding() failed\n"); -print strlen($euc_jp) . "\n"; +print strlen($euc_jp) . "\n"; -// SJIS echo "== SJIS ==\n"; $sjis = mb_convert_encoding($euc_jp, 'SJIS','EUC-JP'); -print mb_strlen($sjis,'SJIS') . "\n"; +print mb_strlen($sjis,'SJIS') . "\n"; mb_internal_encoding('SJIS') or print("mb_internal_encoding() failed\n"); -print strlen($sjis) . "\n"; +print strlen($sjis) . "\n"; +print "-- Testing illegal bytes 0x80,0xFD-FF --\n"; +// mb_strlen used to wrongly treat 0x80 as the starting byte of a 2-byte SJIS character +print mb_strlen("\x80\xA1", 'SJIS') . "\n"; +print mb_strlen("abc\xFD\xFE\xFF", 'SJIS') . "\n"; + +echo "== MacJapanese ==\n"; +print mb_strlen("\x80\xA1", 'MacJapanese') . "\n"; +print mb_strlen("abc\xFD\xFE\xFF", 'MacJapanese') . "\n"; + +echo "== SJIS-2004 ==\n"; +print mb_strlen("\x80\xA1", 'SJIS-2004') . "\n"; +print mb_strlen("abc\xFD\xFE\xFF", 'SJIS-2004') . "\n"; + +echo "== SJIS-Mobile#DOCOMO ==\n"; +print mb_strlen("\x80\xA1", 'SJIS-Mobile#DOCOMO') . "\n"; +print mb_strlen("abc\xFD\xFE\xFF", 'SJIS-Mobile#DOCOMO') . "\n"; + +echo "== SJIS-Mobile#KDDI ==\n"; +print mb_strlen("\x80\xA1", 'SJIS-Mobile#KDDI') . "\n"; +print mb_strlen("abc\xFD\xFE\xFF", 'SJIS-Mobile#KDDI') . "\n"; + +echo "== SJIS-Mobile#SoftBank ==\n"; +print mb_strlen("\x80\xA1", 'SJIS-Mobile#SoftBank') . "\n"; +print mb_strlen("abc\xFD\xFE\xFF", 'SJIS-Mobile#SoftBank') . "\n"; -// JIS -// Note: either convert_encoding or strlen has problem echo "== JIS ==\n"; $jis = mb_convert_encoding($euc_jp, 'JIS','EUC-JP'); -print mb_strlen($jis,'JIS') . "\n"; +print mb_strlen($jis,'JIS') . "\n"; mb_internal_encoding('JIS') or print("mb_internal_encoding() failed\n"); -print strlen($jis) . "\n"; +print strlen($jis) . "\n"; -// UTF-8 -// Note: either convert_encoding or strlen has problem echo "== UTF-8 ==\n"; $utf8 = mb_convert_encoding($euc_jp, 'UTF-8','EUC-JP'); -print mb_strlen($utf8,'UTF-8') . "\n"; +print mb_strlen($utf8,'UTF-8') . "\n"; mb_internal_encoding('UTF-8') or print("mb_internal_encoding() failed\n"); -print strlen($utf8) . "\n"; - +print strlen($utf8) . "\n"; // Wrong Parameters echo "== WRONG PARAMETERS ==\n"; @@ -72,6 +88,24 @@ try { == SJIS == 43 72 +-- Testing illegal bytes 0x80,0xFD-FF -- +2 +6 +== MacJapanese == +2 +6 +== SJIS-2004 == +2 +6 +== SJIS-Mobile#DOCOMO == +2 +6 +== SJIS-Mobile#KDDI == +2 +6 +== SJIS-Mobile#SoftBank == +2 +6 == JIS == 43 90 diff --git a/ext/mbstring/tests/mb_substr.phpt b/ext/mbstring/tests/mb_substr.phpt index 366173eab8661..b027eaa90848e 100644 --- a/ext/mbstring/tests/mb_substr.phpt +++ b/ext/mbstring/tests/mb_substr.phpt @@ -11,7 +11,21 @@ ini_set('include_path','.'); include_once('common.inc'); // EUC-JP -$euc_jp = '0123����ʸ��������ܸ�Ǥ���EUC-JP��ȤäƤ��ޤ������ܸ�����ݽ�����'; +$euc_jp = mb_convert_encoding('0123この文字列は日本語です。EUC-JPを使っています。日本語は面倒臭い。', 'EUC-JP', 'UTF-8'); +// SJIS +$sjis = mb_convert_encoding('日本語テキストです。0123456789。', 'SJIS', 'UTF-8'); +// ISO-2022-JP +$iso2022jp = "\x1B\$B\x21\x21!r\x1B(BABC"; +// GB-18030 +$gb18030 = mb_convert_encoding('密码用户名密码名称名称', 'GB18030', 'UTF-8'); +// HZ +$hz = "The next sentence is in GB.~{<:Ky2;S{#,NpJ)l6HK!#~}Bye."; +// UTF-8 +$utf8 = "Greek: Σὲ γνωρίζω ἀπὸ τὴν κόψη Russian: Зарегистрируйтесь"; +// UTF-32 +$utf32 = mb_convert_encoding($utf8, 'UTF-32', 'UTF-8'); +// UTF-7 +$utf7 = mb_convert_encoding($utf8, 'UTF-7', 'UTF-8'); print "1: ". bin2hex(mb_substr($euc_jp, 10, 10,'EUC-JP')) . "\n"; print "2: ". bin2hex(mb_substr($euc_jp, 0, 100,'EUC-JP')) . "\n"; @@ -20,8 +34,82 @@ $str = mb_substr($euc_jp, 100, 10,'EUC-JP'); // Note: returns last character ($str === "") ? print "3 OK\n" : print "NG: ".bin2hex($str)."\n"; -$str = mb_substr($euc_jp, -100, 10,'EUC-JP'); -($str !== "") ? print "4 OK: ".bin2hex($str)."\n" : print "NG: ".bin2hex($str)."\n"; +$str = mb_substr($euc_jp, -100, 10, 'EUC-JP'); +print ($str !== "") ? "4 OK: " . bin2hex($str) . "\n" : "BAD: " . bin2hex($str) . "\n"; + +echo "SJIS:\n"; +print "1: " . bin2hex(mb_substr($sjis, 0, 3, 'SJIS')) . "\n"; +print "2: " . bin2hex(mb_substr($sjis, -1, null, 'SJIS')) . "\n"; +print "3: " . bin2hex(mb_substr($sjis, -5, 3, 'SJIS')) . "\n"; +print "4: " . bin2hex(mb_substr($sjis, 1, null, 'SJIS')) . "\n"; +print "5:" . bin2hex(mb_substr($sjis, 10, 0, 'SJIS')) . "\n"; +echo "-- Testing illegal SJIS byte 0x80 --\n"; +print bin2hex(mb_substr("\x80abc\x80\xA1", 3, 2, 'SJIS')) . "\n"; +print bin2hex(mb_substr("\x80abc\x80\xA1", 0, 3, 'SJIS')) . "\n"; + +echo "SJIS-2004:\n"; +print bin2hex(mb_substr("\x80abc\x80\xA1", 3, 2, 'SJIS-2004')) . "\n"; +print bin2hex(mb_substr("\x80abc\x80\xA1", 0, 3, 'SJIS-2004')) . "\n"; + +echo "MacJapanese:\n"; +print bin2hex(mb_substr("\x80abc\x80\xA1", 3, 2, 'MacJapanese')) . "\n"; +print bin2hex(mb_substr("\x80abc\x80\xA1", 0, 3, 'MacJapanese')) . "\n"; + +echo "SJIS-Mobile#DOCOMO:\n"; +print bin2hex(mb_substr("\x80abc\x80\xA1", 3, 2, 'SJIS-Mobile#DOCOMO')) . "\n"; +print bin2hex(mb_substr("\x80abc\x80\xA1", 0, 3, 'SJIS-Mobile#DOCOMO')) . "\n"; + +echo "SJIS-Mobile#KDDI:\n"; +print bin2hex(mb_substr("\x80abc\x80\xA1", 3, 2, 'SJIS-Mobile#KDDI')) . "\n"; +print bin2hex(mb_substr("\x80abc\x80\xA1", 0, 3, 'SJIS-Mobile#KDDI')) . "\n"; + +echo "SJIS-Mobile#SoftBank:\n"; +print bin2hex(mb_substr("\x80abc\x80\xA1", 3, 2, 'SJIS-Mobile#SoftBank')) . "\n"; +print bin2hex(mb_substr("\x80abc\x80\xA1", 0, 3, 'SJIS-Mobile#SoftBank')) . "\n"; + +echo "ISO-2022-JP:\n"; +print "1: " . bin2hex(mb_substr($iso2022jp, 0, 3, 'ISO-2022-JP')) . "\n"; +print "2: " . bin2hex(mb_substr($iso2022jp, -1, null, 'ISO-2022-JP')) . "\n"; +print "3: " . bin2hex(mb_substr($iso2022jp, -6, 3, 'ISO-2022-JP')) . "\n"; +print "4: " . bin2hex(mb_substr($iso2022jp, -3, 2, 'ISO-2022-JP')) . "\n"; +print "5: " . bin2hex(mb_substr($iso2022jp, 1, null, 'ISO-2022-JP')) . "\n"; +print "6:" . bin2hex(mb_substr($iso2022jp, 10, 0, 'ISO-2022-JP')) . "\n"; +print "7:" . bin2hex(mb_substr($iso2022jp, 100, 10, 'ISO-2022-JP')) . "\n"; + +echo "GB-18030:\n"; +print "1: " . bin2hex(mb_substr($gb18030, 0, 3, 'GB-18030')) . "\n"; +print "2: " . bin2hex(mb_substr($gb18030, -1, null, 'GB-18030')) . "\n"; +print "3: " . bin2hex(mb_substr($gb18030, -5, 3, 'GB-18030')) . "\n"; +print "4: " . bin2hex(mb_substr($gb18030, 1, null, 'GB-18030')) . "\n"; +print "5:" . bin2hex(mb_substr($gb18030, 10, 0, 'GB-18030')) . "\n"; + +echo "HZ:\n"; +print "1: " . mb_substr($hz, 0, 3, 'HZ') . "\n"; +print "2: " . mb_substr($hz, -1, null, 'HZ') . "\n"; +print "3: " . mb_substr($hz, -5, 3, 'HZ') . "\n"; +print "4: " . mb_substr($hz, 1, null, 'HZ') . "\n"; +print "5:" . mb_substr($hz, 10, 0, 'HZ') . "\n"; + +echo "UTF-8:\n"; +print "1: " . mb_substr($utf8, 0, 3, 'UTF-8') . "\n"; +print "2: " . mb_substr($utf8, -1, null, 'UTF-8') . "\n"; +print "3: " . mb_substr($utf8, -5, 3, 'UTF-8') . "\n"; +print "4: " . mb_substr($utf8, 1, null, 'UTF-8') . "\n"; +print "5:" . mb_substr($utf8, 10, 0, 'UTF-8') . "\n"; + +echo "UTF-32:\n"; +print "1: " . mb_convert_encoding(mb_substr($utf32, 0, 3, 'UTF-32'), 'UTF-8', 'UTF-32') . "\n"; +print "2: " . mb_convert_encoding(mb_substr($utf32, -1, null, 'UTF-32'), 'UTF-8', 'UTF-32') . "\n"; +print "3: " . mb_convert_encoding(mb_substr($utf32, -5, 3, 'UTF-32'), 'UTF-8', 'UTF-32') . "\n"; +print "4: " . mb_convert_encoding(mb_substr($utf32, 1, null, 'UTF-32'), 'UTF-8', 'UTF-32') . "\n"; +print "5:" . mb_convert_encoding(mb_substr($utf32, 10, 0, 'UTF-32'), 'UTF-8', 'UTF-32') . "\n"; + +echo "UTF-7:\n"; +print "1: " . mb_convert_encoding(mb_substr($utf7, 0, 3, 'UTF-7'), 'UTF-8', 'UTF-7') . "\n"; +print "2: " . mb_convert_encoding(mb_substr($utf7, -1, null, 'UTF-7'), 'UTF-8', 'UTF-7') . "\n"; +print "3: " . mb_convert_encoding(mb_substr($utf7, -5, 3, 'UTF-7'), 'UTF-8', 'UTF-7') . "\n"; +print "4: " . mb_convert_encoding(mb_substr($utf7, 1, null, 'UTF-7'), 'UTF-8', 'UTF-7') . "\n"; +print "5:" . mb_convert_encoding(mb_substr($utf7, 10, 0, 'UTF-7'), 'UTF-8', 'UTF-7') . "\n"; ?> --EXPECT-- @@ -29,3 +117,65 @@ $str = mb_substr($euc_jp, -100, 10,'EUC-JP'); 2: 30313233a4b3a4cecab8bbfacef3a4cfc6fccbdcb8eca4c7a4b9a1a34555432d4a50a4f2bbc8a4c3a4c6a4a4a4dea4b9a1a3c6fccbdcb8eca4cfccccc5ddbdada4a4a1a3 3 OK 4 OK: 30313233a4b3a4cecab8bbfacef3a4cf +SJIS: +1: 93fa967b8cea +2: 8142 +3: 825582568257 +4: 967b8cea8365834c8358836782c582b781423031323334825482558256825782588142 +5: +-- Testing illegal SJIS byte 0x80 -- +6380 +806162 +SJIS-2004: +6380 +806162 +MacJapanese: +6380 +806162 +SJIS-Mobile#DOCOMO: +6380 +806162 +SJIS-Mobile#KDDI: +6380 +806162 +SJIS-Mobile#SoftBank: +6380 +806162 +ISO-2022-JP: +1: 1b2442212121721b284241 +2: 43 +3: 1b2442212121721b284241 +4: 4142 +5: 1b244221721b2842414243 +6: +7: +GB-18030: +1: c3dcc2ebd3c3 +2: b3c6 +3: c2ebc3fbb3c6 +4: c2ebd3c3bba7c3fbc3dcc2ebc3fbb3c6c3fbb3c6 +5: +HZ: +1: The +2: . +3: ~{!#~}By +4: he next sentence is in GB.~{<:Ky2;S{#,NpJ)l6HK!#~}Bye. +5: +UTF-8: +1: Gre +2: ь +3: йте +4: reek: Σὲ γνωρίζω ἀπὸ τὴν κόψη Russian: Зарегистрируйтесь +5: +UTF-32: +1: Gre +2: ь +3: йте +4: reek: Σὲ γνωρίζω ἀπὸ τὴν κόψη Russian: Зарегистрируйтесь +5: +UTF-7: +1: Gre +2: ь +3: йте +4: reek: Σὲ γνωρίζω ἀπὸ τὴν κόψη Russian: Зарегистрируйтесь +5: From de633c31dd492a158c4db2979f76c98372cc017a Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Thu, 5 Jan 2023 13:10:28 +0000 Subject: [PATCH 48/83] Add missing EXTENSIONS section to test file gh10200 --- Zend/tests/gh10200.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Zend/tests/gh10200.phpt b/Zend/tests/gh10200.phpt index 5462352e7ae5b..ad02d45bfe63c 100644 --- a/Zend/tests/gh10200.phpt +++ b/Zend/tests/gh10200.phpt @@ -1,5 +1,7 @@ --TEST-- GH-10200 (zif_get_object_vars: Assertion `!(((__ht)->u.flags & (1<<2)) != 0)' failed.) +--EXTENSIONS-- +simplexml --FILE-- Date: Thu, 5 Jan 2023 11:34:33 +0200 Subject: [PATCH 49/83] Use different mblen_table for different SJIS variants --- NEWS | 3 +++ ext/mbstring/libmbfl/filters/mbfilter_sjis.c | 4 +-- .../libmbfl/filters/mbfilter_sjis_2004.c | 4 +-- .../libmbfl/filters/mbfilter_sjis_mac.c | 21 +++++++++++++-- .../libmbfl/filters/mbfilter_sjis_mobile.c | 26 ++++++++++++++++--- 5 files changed, 48 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index 6833d8a4ee4a7..76c801f136a59 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,9 @@ PHP NEWS . Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()). (cmb) +- MBString: + . Fixed: mb_strlen (and a couple of other mbstring functions) would wrongly treat 0x80, 0xFD, 0xFE, 0xFF, and certain other byte values as the first byte of a 2-byte SJIS character. (Alex Dowad) + - Opcache: . Fix inverted bailout value in zend_runtime_jit() (Max Kellermann). . Fix access to uninitialized variable in accel_preload(). (nielsdos) diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis.c index 9e0b053d0da73..3406cc0cf4bfd 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_sjis.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis.c @@ -38,7 +38,7 @@ static int mbfl_filt_conv_sjis_wchar_flush(mbfl_convert_filter *filter); -const unsigned char mblen_table_sjis[] = { /* 0x81-0x9F,0xE0-0xFC */ +const unsigned char mblen_table_sjis[] = { /* 0x81-0x9F,0xE0-0xEF */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -54,7 +54,7 @@ const unsigned char mblen_table_sjis[] = { /* 0x81-0x9F,0xE0-0xFC */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; static const char *mbfl_encoding_sjis_aliases[] = {"x-sjis", "SHIFT-JIS", NULL}; diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c index 95816206d5629..6a6fe92f49722 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c @@ -39,7 +39,7 @@ #include "unicode_table_jis2004.h" #include "unicode_table_jis.h" -extern const unsigned char mblen_table_sjis[]; +extern const unsigned char mblen_table_sjis_mobile[]; extern int mbfl_bisec_srch(int w, const unsigned short *tbl, int n); extern int mbfl_bisec_srch2(int w, const unsigned short tbl[], int n); @@ -51,7 +51,7 @@ const mbfl_encoding mbfl_encoding_sjis2004 = { "SJIS-2004", "Shift_JIS", mbfl_encoding_sjis2004_aliases, - mblen_table_sjis, + mblen_table_sjis_mobile, /* Leading byte values used for SJIS-2004 are the same as mobile SJIS variants */ MBFL_ENCTYPE_GL_UNSAFE, &vtbl_sjis2004_wchar, &vtbl_wchar_sjis2004 diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c index bbc6895ce8fae..3f85cb5eecb5a 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c @@ -35,7 +35,24 @@ #include "sjis_mac2uni.h" -extern const unsigned char mblen_table_sjis[]; +const unsigned char mblen_table_sjismac[] = { /* 0x81-0x9F,0xE0-0xED */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; static int mbfl_filt_conv_wchar_sjis_mac_flush(mbfl_convert_filter *filter); static int mbfl_filt_conv_sjis_mac_wchar_flush(mbfl_convert_filter *filter); @@ -47,7 +64,7 @@ const mbfl_encoding mbfl_encoding_sjis_mac = { "SJIS-mac", "Shift_JIS", mbfl_encoding_sjis_mac_aliases, - mblen_table_sjis, + mblen_table_sjismac, MBFL_ENCTYPE_GL_UNSAFE, &vtbl_sjis_mac_wchar, &vtbl_wchar_sjis_mac diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c index f2c230b0cbcb1..cecfe063121fe 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c @@ -35,8 +35,26 @@ #include "emoji2uni.h" +const unsigned char mblen_table_sjis_mobile[] = { /* 0x81-0x9F,0xE0-0xFC */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 +}; + extern int mbfl_bisec_srch2(int w, const unsigned short tbl[], int n); -extern const unsigned char mblen_table_sjis[]; static int mbfl_filt_conv_sjis_wchar_flush(mbfl_convert_filter *filter); @@ -49,7 +67,7 @@ const mbfl_encoding mbfl_encoding_sjis_docomo = { "SJIS-Mobile#DOCOMO", "Shift_JIS", mbfl_encoding_sjis_docomo_aliases, - mblen_table_sjis, + mblen_table_sjis_mobile, MBFL_ENCTYPE_GL_UNSAFE, &vtbl_sjis_docomo_wchar, &vtbl_wchar_sjis_docomo @@ -60,7 +78,7 @@ const mbfl_encoding mbfl_encoding_sjis_kddi = { "SJIS-Mobile#KDDI", "Shift_JIS", mbfl_encoding_sjis_kddi_aliases, - mblen_table_sjis, + mblen_table_sjis_mobile, MBFL_ENCTYPE_GL_UNSAFE, &vtbl_sjis_kddi_wchar, &vtbl_wchar_sjis_kddi @@ -71,7 +89,7 @@ const mbfl_encoding mbfl_encoding_sjis_sb = { "SJIS-Mobile#SOFTBANK", "Shift_JIS", mbfl_encoding_sjis_sb_aliases, - mblen_table_sjis, + mblen_table_sjis_mobile, MBFL_ENCTYPE_GL_UNSAFE, &vtbl_sjis_sb_wchar, &vtbl_wchar_sjis_sb From df96346f9c3f487e52ab90f0f8166f445a01c5b3 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 6 Jan 2023 23:06:17 +0100 Subject: [PATCH 50/83] Move test for GH-10200 to the simplexml extension test directory Closes GH-10252 Signed-off-by: George Peter Banyard --- {Zend => ext/simplexml}/tests/gh10200.phpt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {Zend => ext/simplexml}/tests/gh10200.phpt (100%) diff --git a/Zend/tests/gh10200.phpt b/ext/simplexml/tests/gh10200.phpt similarity index 100% rename from Zend/tests/gh10200.phpt rename to ext/simplexml/tests/gh10200.phpt From 32f503e4e358126238f8f7c30f490c64302da3b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sat, 7 Jan 2023 14:03:13 +0100 Subject: [PATCH 51/83] random: Fix check before closing `random_fd` (#10247) If, for whatever reason, the random_fd has been assigned file descriptor `0` it previously failed to close during module shutdown, thus leaking the descriptor. --- NEWS | 3 +++ ext/random/random.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 22b1a57967447..57e947cf59fbd 100644 --- a/NEWS +++ b/NEWS @@ -30,6 +30,9 @@ PHP NEWS - Posix: . Fix memory leak in posix_ttyname() (girgias) +- Random: + . Fixed bug GH-10247 (Theoretical file descriptor leak for /dev/urandom). (timwolla) + - Standard: . Fix GH-10187 (Segfault in stripslashes() with arm64). (nielsdos) diff --git a/ext/random/random.c b/ext/random/random.c index 161eb8e685203..64e30e5087186 100644 --- a/ext/random/random.c +++ b/ext/random/random.c @@ -828,7 +828,7 @@ static PHP_GINIT_FUNCTION(random) /* {{{ PHP_GSHUTDOWN_FUNCTION */ static PHP_GSHUTDOWN_FUNCTION(random) { - if (random_globals->random_fd > 0) { + if (random_globals->random_fd >= 0) { close(random_globals->random_fd); random_globals->random_fd = -1; } From 8ff2b6abb2cd0993f6c5c60e25feba094cdb6272 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 5 Jan 2023 22:11:15 +0100 Subject: [PATCH 52/83] Fix GH-9710: phpdbg memory leaks by option "-h" Closes GH-10237 Signed-off-by: George Peter Banyard --- NEWS | 1 + sapi/phpdbg/phpdbg.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 76c801f136a59..24b7c9a9e70f3 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,7 @@ PHP NEWS - PHPDBG: . Fix undefined behaviour in phpdbg_load_module_or_extension(). (nielsdos) . Fix NULL pointer dereference in phpdbg_create_conditional_breal(). (nielsdos) + . Fix GH-9710: phpdbg memory leaks by option "-h" (nielsdos) - Posix: . Fix memory leak in posix_ttyname() (girgias) diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 221803f88e7e9..e1824ecb1fc7a 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -1414,6 +1414,8 @@ int main(int argc, char **argv) /* {{{ */ get_zend_version() ); } + PHPDBG_G(flags) |= PHPDBG_IS_QUITTING; + php_module_shutdown(); sapi_deactivate(); sapi_shutdown(); if (ini_entries) { From d03025bf590dc03b69e75d1159ed4b2e6ee6ad37 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 7 Jan 2023 13:49:24 +0100 Subject: [PATCH 53/83] Fix GH-10251: Assertion `(flag & (1<<3)) == 0' failed. zend_get_property_guard previously assumed that at least "str" has a pre-computed hash. This is not always the case, for example when a string is created by bitwise operations, its hash is not set. Instead of forcing a computation of the hashes, drop the hash comparison. Closes GH-10254 Co-authored-by: Changochen Signed-off-by: George Peter Banyard --- NEWS | 1 + Zend/tests/gh10251.phpt | 24 ++++++++++++++++++++++++ Zend/zend_object_handlers.c | 5 ++--- 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 Zend/tests/gh10251.phpt diff --git a/NEWS b/NEWS index 24b7c9a9e70f3..ad29b8f611839 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,7 @@ PHP NEWS - Core: . Fixed bug GH-10072 (PHP crashes when execute_ex is overridden and a __call trampoline is used from internal code). (Derick) + . Fix GH-10251 (Assertion `(flag & (1<<3)) == 0' failed). (nielsdos) - Date: . Fixed bug GH-9891 (DateTime modify with unixtimestamp (@) must work like diff --git a/Zend/tests/gh10251.phpt b/Zend/tests/gh10251.phpt new file mode 100644 index 0000000000000..eb942824802ac --- /dev/null +++ b/Zend/tests/gh10251.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-10251 (Assertion `(flag & (1<<3)) == 0' failed.) +--FILE-- +$p = $v; + } +} +$a = new A(); +$pp = ""; +$op = $pp & ""; +// Bitwise operators on strings don't compute the hash. +// The code below previously assumed a hash was actually computed, leading to a crash. +$a->$op = 0; +echo "Done\n"; +?> +--EXPECTF-- +Warning: Undefined variable $v in %s on line %d + +Warning: Undefined variable $p in %s on line %d +Done diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 5fa80c1adc5e5..e4ae4450b534f 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -535,9 +535,8 @@ ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *membe if (EXPECTED(Z_TYPE_P(zv) == IS_STRING)) { zend_string *str = Z_STR_P(zv); if (EXPECTED(str == member) || - /* "str" always has a pre-calculated hash value here */ - (EXPECTED(ZSTR_H(str) == zend_string_hash_val(member)) && - EXPECTED(zend_string_equal_content(str, member)))) { + /* str and member don't necessarily have a pre-calculated hash value here */ + EXPECTED(zend_string_equal_content(str, member))) { return &Z_PROPERTY_GUARD_P(zv); } else if (EXPECTED(Z_PROPERTY_GUARD_P(zv) == 0)) { zval_ptr_dtor_str(zv); From 6faeb9571d11b0e92efa94439262deb9cd19a69c Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sun, 8 Jan 2023 18:04:10 +0100 Subject: [PATCH 54/83] Fix recently introduced gh10251.phpt As of PHP 8.2.0, creation of dynamic properties is deprecated, so we slap a `AllowDynamicProperties` attribute on the class. --- Zend/tests/gh10251.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/Zend/tests/gh10251.phpt b/Zend/tests/gh10251.phpt index eb942824802ac..da8d8767a3656 100644 --- a/Zend/tests/gh10251.phpt +++ b/Zend/tests/gh10251.phpt @@ -2,6 +2,7 @@ GH-10251 (Assertion `(flag & (1<<3)) == 0' failed.) --FILE-- Date: Mon, 9 Jan 2023 07:50:30 +0100 Subject: [PATCH 55/83] ext/opcache/jit/zend_jit_trace: fix memory leak in _compile_root_trace() (#10146) A copy of this piece of code exists in zend_jit_compile_side_trace(), but there, the leak bug does not exist. This bug exists since both copies of this piece of code were added in commit 4bf2d09edeb14 --- ext/opcache/jit/zend_jit_trace.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 56b01e7daca04..555a868b2d553 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -7114,6 +7114,7 @@ static zend_jit_trace_stop zend_jit_compile_root_trace(zend_jit_trace_rec *trace if (t->stack_map_size) { zend_jit_trace_stack *shared_stack_map = (zend_jit_trace_stack*)zend_shared_alloc(t->stack_map_size * sizeof(zend_jit_trace_stack)); if (!shared_stack_map) { + efree(t->stack_map); ret = ZEND_JIT_TRACE_STOP_NO_SHM; goto exit; } From 4d4a53beee2b815ccd9f2905efd4f7f177c18ec8 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 9 Jan 2023 13:51:57 +0300 Subject: [PATCH 56/83] Fix incorrect optimization of ASSIGN_OP may lead to incorrect result (sub assign -> pre dec conversion for null values) --- Zend/Optimizer/dfa_pass.c | 2 +- ext/opcache/tests/opt/assign_op_002.phpt | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/opt/assign_op_002.phpt diff --git a/Zend/Optimizer/dfa_pass.c b/Zend/Optimizer/dfa_pass.c index a1124199bb447..754dec7ee60cf 100644 --- a/Zend/Optimizer/dfa_pass.c +++ b/Zend/Optimizer/dfa_pass.c @@ -1687,7 +1687,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx && Z_TYPE_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) == IS_LONG && Z_LVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) == 1 && ssa->ops[op_1].op1_use >= 0 - && !(ssa->var_info[ssa->ops[op_1].op1_use].type & (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) { + && !(ssa->var_info[ssa->ops[op_1].op1_use].type & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) { // op_1: ASSIGN_SUB #?.CV [undef,null,int,foat] -> #v.CV, int(1) => PRE_DEC #?.CV ->#v.CV diff --git a/ext/opcache/tests/opt/assign_op_002.phpt b/ext/opcache/tests/opt/assign_op_002.phpt new file mode 100644 index 0000000000000..63746ac1c86b6 --- /dev/null +++ b/ext/opcache/tests/opt/assign_op_002.phpt @@ -0,0 +1,18 @@ +--TEST-- +ASSIGN_OP 002: Incorrect optimization of ASSIGN_OP may lead to incorrect result (sub assign -> pre dec conversion for null values) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +--EXPECT-- +int(1) +int(-1) From a9e7b90cc2e2a120f24c97a0186b39debbfdc5dd Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 21 Oct 2022 20:11:35 +0200 Subject: [PATCH 57/83] Adapt ext/intl tests for ICU 72.1 This version replaces SPACEs before the meridian with NARROW NO-BREAK SPACEs. Thus, we split the affected test cases as usual. (cherry picked from commit 8dd51b462d72bd3abeeb82f602a269e0b087b901) Fixes GH-10262. --- .../tests/dateformat_calendars_variant3.phpt | 1 + .../dateformat_calendars_variant_icu72-1.phpt | 48 +++ ext/intl/tests/dateformat_create_default.phpt | 2 + .../dateformat_create_default_icu72-1.phpt | 26 ++ ...format_formatObject_calendar_variant5.phpt | 1 + ...formatObject_calendar_variant_icu72-1.phpt | 37 +++ ...format_formatObject_datetime_variant5.phpt | 1 + ...formatObject_datetime_variant_icu72-1.phpt | 30 ++ .../dateformat_format_parse_version2.phpt | 1 + ...teformat_format_parse_version_icu72-1.phpt | 296 ++++++++++++++++++ .../tests/dateformat_set_timezone_id3.phpt | 1 + .../dateformat_set_timezone_id_icu72-1.phpt | 85 +++++ ...datepatterngenerator_get_best_pattern.phpt | 2 + ...erngenerator_get_best_pattern_icu72-1.phpt | 38 +++ ext/intl/tests/msgfmt_format_datetime.phpt | 2 + .../tests/msgfmt_format_datetime_icu72-1.phpt | 29 ++ ...t_format_simple_types_numeric_strings.phpt | 2 + ..._simple_types_numeric_strings_icu72-1.phpt | 54 ++++ ...cebundle_null_mandatory_args_variant2.phpt | 1 + ...e_null_mandatory_args_variant_icu72-1.phpt | 24 ++ 20 files changed, 681 insertions(+) create mode 100644 ext/intl/tests/dateformat_calendars_variant_icu72-1.phpt create mode 100644 ext/intl/tests/dateformat_create_default_icu72-1.phpt create mode 100644 ext/intl/tests/dateformat_formatObject_calendar_variant_icu72-1.phpt create mode 100644 ext/intl/tests/dateformat_formatObject_datetime_variant_icu72-1.phpt create mode 100644 ext/intl/tests/dateformat_format_parse_version_icu72-1.phpt create mode 100644 ext/intl/tests/dateformat_set_timezone_id_icu72-1.phpt create mode 100644 ext/intl/tests/datepatterngenerator_get_best_pattern_icu72-1.phpt create mode 100644 ext/intl/tests/msgfmt_format_datetime_icu72-1.phpt create mode 100644 ext/intl/tests/msgfmt_format_simple_types_numeric_strings_icu72-1.phpt create mode 100644 ext/intl/tests/resourcebundle_null_mandatory_args_variant_icu72-1.phpt diff --git a/ext/intl/tests/dateformat_calendars_variant3.phpt b/ext/intl/tests/dateformat_calendars_variant3.phpt index 0e7f8b0183d71..bf2f1e918f172 100644 --- a/ext/intl/tests/dateformat_calendars_variant3.phpt +++ b/ext/intl/tests/dateformat_calendars_variant3.phpt @@ -6,6 +6,7 @@ date.timezone=Atlantic/Azores intl --SKIPIF-- = 54.1'); ?> += 0) die('skip for ICU < 72.1'); ?> --FILE-- = 72.1'); ?> +--FILE-- +format(strtotime('2012-01-01 00:00:00 +0000'))); +var_dump($fmt2->format(strtotime('2012-01-01 00:00:00 +0000'))); +var_dump($fmt3->format(strtotime('2012-01-01 00:00:00 +0000'))); + +new IntlDateFormatter('en_US@calendar=hebrew', + IntlDateFormatter::FULL, + IntlDateFormatter::FULL, + 'GMT+05:12', + -1); +?> +==DONE== +--EXPECTF-- +string(49) "Sunday, January 1, 2012 at 5:12:00 AM GMT+05:12" +string(49) "Sunday, January 1, 2012 at 5:12:00 AM GMT+05:12" +string(46) "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 %s:%d +Stack trace: +#0 %s(%d): IntlDateFormatter->__construct('en_US@calendar=...', 0, 0, 'GMT+05:12', -1) +#1 {main} + thrown in %s on line %d diff --git a/ext/intl/tests/dateformat_create_default.phpt b/ext/intl/tests/dateformat_create_default.phpt index eddac36f5ea39..1479ee9a98476 100644 --- a/ext/intl/tests/dateformat_create_default.phpt +++ b/ext/intl/tests/dateformat_create_default.phpt @@ -4,6 +4,8 @@ IntlDateFormatter::create() with default date and time types intl --INI-- date.timezone=UTC +--SKIPIF-- += 0) die('skip for ICU < 72.1'); ?> --FILE-- = 72.1'); ?> +--FILE-- +format($ts), "\n"; + +$fmt = new IntlDateFormatter('en_US'); +echo $fmt->format($ts), "\n"; + +$fmt = datefmt_create('en_US'); +echo $fmt->format($ts), "\n"; + +?> +--EXPECT-- +Sunday, January 1, 2012 at 12:00:00 AM Coordinated Universal Time +Sunday, January 1, 2012 at 12:00:00 AM Coordinated Universal Time +Sunday, January 1, 2012 at 12:00:00 AM Coordinated Universal Time diff --git a/ext/intl/tests/dateformat_formatObject_calendar_variant5.phpt b/ext/intl/tests/dateformat_formatObject_calendar_variant5.phpt index 494b66768906f..9eb9f39a917a7 100644 --- a/ext/intl/tests/dateformat_formatObject_calendar_variant5.phpt +++ b/ext/intl/tests/dateformat_formatObject_calendar_variant5.phpt @@ -4,6 +4,7 @@ IntlDateFormatter::formatObject(): IntlCalendar tests intl --SKIPIF-- = 55.1'); ?> += 0) die('skip for ICU < 72.1'); ?> --FILE-- = 72.1'); ?> +--FILE-- +setTime(strtotime('2012-01-01 00:00:00')*1000.); +echo IntlDateFormatter::formatObject($cal), "\n"; +echo IntlDateFormatter::formatObject($cal, IntlDateFormatter::FULL, "en-US"), "\n"; + +?> +--EXPECTF-- +01/01/2012, 00:00:00 +domingo, 1 de janeiro de 2012 às 00:00:00 Hora padrão %Sda Europa Ocidental +Jan 1, 2012, 12:00:00 AM +1/1/12, 12:00:00 AM Western European Standard Time +Sun 2012-01-1 00,00,00.000 Portugal Time +domingo, 1 de janeiro de 2012 às 05:00:00 GMT+03:00 +06/02/1433, 00:00:00 +Sunday, Safar 6, 1433 at 12:00:00 AM Western European Standard Time diff --git a/ext/intl/tests/dateformat_formatObject_datetime_variant5.phpt b/ext/intl/tests/dateformat_formatObject_datetime_variant5.phpt index b51a46d7f3976..b3c2ecc8e7932 100644 --- a/ext/intl/tests/dateformat_formatObject_datetime_variant5.phpt +++ b/ext/intl/tests/dateformat_formatObject_datetime_variant5.phpt @@ -4,6 +4,7 @@ IntlDateFormatter::formatObject(): DateTime tests intl --SKIPIF-- = 55.1'); ?> += 0) die('skip for ICU < 72.1'); ?> --FILE-- +--FILE-- + +--EXPECTF-- +01/01/2012, 00:00:00 +domingo, 1 de janeiro de 2012 às 00:00:00 Hora padrão %Sda Europa Ocidental +Jan 1, 2012, 12:00:00 AM +1/1/12, 12:00:00 AM Western European Standard Time +Sun 2012-01-1 00,00,00.000 Portugal Time +domingo, 1 de janeiro de 2012 às 05:00:00 GMT+03:00 diff --git a/ext/intl/tests/dateformat_format_parse_version2.phpt b/ext/intl/tests/dateformat_format_parse_version2.phpt index 19e7d914adcfd..1293d29c383bf 100644 --- a/ext/intl/tests/dateformat_format_parse_version2.phpt +++ b/ext/intl/tests/dateformat_format_parse_version2.phpt @@ -4,6 +4,7 @@ datefmt_format_code() and datefmt_parse_code() intl --SKIPIF-- = 51.2'); ?> += 0) die('skip for ICU < 72.1'); ?> --FILE-- = 72.1'); ?> +--FILE-- + 24 , + 'tm_min' => 3, + 'tm_hour' => 19, + 'tm_mday' => 3, + 'tm_mon' => 3, + 'tm_year' => 105, + ); + $localtime_arr2 = array ( + 'tm_sec' => 21, + 'tm_min' => 5, + 'tm_hour' => 7, + 'tm_mday' => 13, + 'tm_mon' => 7, + 'tm_year' => 205, + ); + $localtime_arr3 = array ( + 'tm_sec' => 11, + 'tm_min' => 13, + 'tm_hour' => 0, + 'tm_mday' => 17, + 'tm_mon' => 11, + 'tm_year' => -5 + ); + + $localtime_arr = array ( + $localtime_arr1, + $localtime_arr2, + $localtime_arr3 + ); + + //Test format and parse with a timestamp : long + foreach( $time_arr as $timestamp_entry){ + $res_str .= "\n------------\n"; + $res_str .= "\nInput timestamp is : $timestamp_entry"; + $res_str .= "\n------------\n"; + foreach( $locale_arr as $locale_entry ){ + foreach( $datetype_arr as $datetype_entry ) { + $res_str .= "\nIntlDateFormatter locale= $locale_entry ,datetype = $datetype_entry ,timetype =$datetype_entry "; + $fmt = ut_datefmt_create( $locale_entry , $datetype_entry ,$datetype_entry,$timezone); + $formatted = ut_datefmt_format( $fmt , $timestamp_entry); + $res_str .= "\nFormatted timestamp is : $formatted"; + $parsed = ut_datefmt_parse( $fmt , $formatted); + if( intl_get_error_code() == U_ZERO_ERROR){ + $res_str .= "\nParsed timestamp is : $parsed"; + }else{ + $res_str .= "\nError while parsing as: '".intl_get_error_message()."'"; + } + } + } + } + + //Test format and parse with a localtime :array + foreach( $localtime_arr as $localtime_entry){ + $res_str .= "\n------------\n"; + $res_str .= "\nInput localtime is : "; + foreach( $localtime_entry as $key => $value){ + $res_str .= "$key : '$value' , "; + } + + $res_str .= "\n------------\n"; + foreach( $locale_arr as $locale_entry ){ + foreach( $datetype_arr as $datetype_entry ) { + $res_str .= "\nIntlDateFormatter locale= $locale_entry ,datetype = $datetype_entry ,timetype =$datetype_entry "; + $fmt = ut_datefmt_create( $locale_entry , $datetype_entry ,$datetype_entry,$timezone); + $formatted1 = ut_datefmt_format( $fmt , $localtime_entry); + if( intl_get_error_code() == U_ZERO_ERROR){ + $res_str .= "\nFormatted localtime_array is : $formatted1"; + }else{ + $res_str .= "\nError while formatting as: '".intl_get_error_message()."'"; + } + //Parsing + $parsed_arr = ut_datefmt_localtime( $fmt, $formatted1 ); + + if( $parsed_arr){ + $res_str .= "\nParsed array is: "; + foreach( $parsed_arr as $key => $value){ + $res_str .= "$key : '$value' , "; + } + } +/* + else{ + //$res_str .= "No values found from LocaleTime parsing."; + $res_str .= "\tError : '".intl_get_error_message()."'"; + } +*/ + } + } + } + + return $res_str; + +} + +include_once( 'ut_common.inc' ); + +// Run the test +ut_run(); +?> +--EXPECT-- +------------ + +Input timestamp is : 0 +------------ + +IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0 +Formatted timestamp is : Thursday, January 1, 1970 at 5:00:00 AM GMT+05:00 +Parsed timestamp is : 0 +IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1 +Formatted timestamp is : January 1, 1970 at 5:00:00 AM GMT+5 +Parsed timestamp is : 0 +IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2 +Formatted timestamp is : Jan 1, 1970, 5:00:00 AM +Parsed timestamp is : 0 +------------ + +Input timestamp is : -1200000 +------------ + +IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0 +Formatted timestamp is : Thursday, December 18, 1969 at 7:40:00 AM GMT+05:00 +Parsed timestamp is : -1200000 +IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1 +Formatted timestamp is : December 18, 1969 at 7:40:00 AM GMT+5 +Parsed timestamp is : -1200000 +IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2 +Formatted timestamp is : Dec 18, 1969, 7:40:00 AM +Parsed timestamp is : -1200000 +------------ + +Input timestamp is : 1200000 +------------ + +IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0 +Formatted timestamp is : Thursday, January 15, 1970 at 2:20:00 AM GMT+05:00 +Parsed timestamp is : 1200000 +IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1 +Formatted timestamp is : January 15, 1970 at 2:20:00 AM GMT+5 +Parsed timestamp is : 1200000 +IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2 +Formatted timestamp is : Jan 15, 1970, 2:20:00 AM +Parsed timestamp is : 1200000 +------------ + +Input timestamp is : 2200000000 +------------ + +IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0 +Formatted timestamp is : Monday, September 19, 2039 at 4:06:40 AM GMT+05:00 +Parsed timestamp is : 2200000000 +IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1 +Formatted timestamp is : September 19, 2039 at 4:06:40 AM GMT+5 +Parsed timestamp is : 2200000000 +IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2 +Formatted timestamp is : Sep 19, 2039, 4:06:40 AM +Parsed timestamp is : 2200000000 +------------ + +Input timestamp is : -2200000000 +------------ + +IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0 +Formatted timestamp is : Sunday, April 15, 1900 at 5:53:20 AM GMT+05:00 +Parsed timestamp is : -2200000000 +IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1 +Formatted timestamp is : April 15, 1900 at 5:53:20 AM GMT+5 +Parsed timestamp is : -2200000000 +IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2 +Formatted timestamp is : Apr 15, 1900, 5:53:20 AM +Parsed timestamp is : -2200000000 +------------ + +Input timestamp is : 90099999 +------------ + +IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0 +Formatted timestamp is : Thursday, November 9, 1972 at 12:46:39 AM GMT+05:00 +Parsed timestamp is : 90099999 +IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1 +Formatted timestamp is : November 9, 1972 at 12:46:39 AM GMT+5 +Parsed timestamp is : 90099999 +IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2 +Formatted timestamp is : Nov 9, 1972, 12:46:39 AM +Parsed timestamp is : 90099999 +------------ + +Input timestamp is : 3600 +------------ + +IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0 +Formatted timestamp is : Thursday, January 1, 1970 at 6:00:00 AM GMT+05:00 +Parsed timestamp is : 3600 +IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1 +Formatted timestamp is : January 1, 1970 at 6:00:00 AM GMT+5 +Parsed timestamp is : 3600 +IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2 +Formatted timestamp is : Jan 1, 1970, 6:00:00 AM +Parsed timestamp is : 3600 +------------ + +Input timestamp is : -3600 +------------ + +IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0 +Formatted timestamp is : Thursday, January 1, 1970 at 4:00:00 AM GMT+05:00 +Parsed timestamp is : -3600 +IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1 +Formatted timestamp is : January 1, 1970 at 4:00:00 AM GMT+5 +Parsed timestamp is : -3600 +IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2 +Formatted timestamp is : Jan 1, 1970, 4:00:00 AM +Parsed timestamp is : -3600 +------------ + +Input localtime is : tm_sec : '24' , tm_min : '3' , tm_hour : '19' , tm_mday : '3' , tm_mon : '3' , tm_year : '105' , +------------ + +IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0 +Formatted localtime_array is : Sunday, April 3, 2005 at 7:03:24 PM GMT+05:00 +Parsed array is: tm_sec : '24' , tm_min : '3' , tm_hour : '19' , tm_year : '105' , tm_mday : '3' , tm_wday : '0' , tm_yday : '93' , tm_mon : '3' , tm_isdst : '0' , +IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1 +Formatted localtime_array is : April 3, 2005 at 7:03:24 PM GMT+5 +Parsed array is: tm_sec : '24' , tm_min : '3' , tm_hour : '19' , tm_year : '105' , tm_mday : '3' , tm_wday : '0' , tm_yday : '93' , tm_mon : '3' , tm_isdst : '0' , +IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2 +Formatted localtime_array is : Apr 3, 2005, 7:03:24 PM +Parsed array is: tm_sec : '24' , tm_min : '3' , tm_hour : '19' , tm_year : '105' , tm_mday : '3' , tm_wday : '0' , tm_yday : '93' , tm_mon : '3' , tm_isdst : '0' , +------------ + +Input localtime is : tm_sec : '21' , tm_min : '5' , tm_hour : '7' , tm_mday : '13' , tm_mon : '7' , tm_year : '205' , +------------ + +IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0 +Formatted localtime_array is : Thursday, August 13, 2105 at 7:05:21 AM GMT+05:00 +Parsed array is: tm_sec : '21' , tm_min : '5' , tm_hour : '7' , tm_year : '205' , tm_mday : '13' , tm_wday : '4' , tm_yday : '225' , tm_mon : '7' , tm_isdst : '0' , +IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1 +Formatted localtime_array is : August 13, 2105 at 7:05:21 AM GMT+5 +Parsed array is: tm_sec : '21' , tm_min : '5' , tm_hour : '7' , tm_year : '205' , tm_mday : '13' , tm_wday : '4' , tm_yday : '225' , tm_mon : '7' , tm_isdst : '0' , +IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2 +Formatted localtime_array is : Aug 13, 2105, 7:05:21 AM +Parsed array is: tm_sec : '21' , tm_min : '5' , tm_hour : '7' , tm_year : '205' , tm_mday : '13' , tm_wday : '4' , tm_yday : '225' , tm_mon : '7' , tm_isdst : '0' , +------------ + +Input localtime is : tm_sec : '11' , tm_min : '13' , tm_hour : '0' , tm_mday : '17' , tm_mon : '11' , tm_year : '-5' , +------------ + +IntlDateFormatter locale= en_US ,datetype = 0 ,timetype =0 +Formatted localtime_array is : Tuesday, December 17, 1895 at 12:13:11 AM GMT+05:00 +Parsed array is: tm_sec : '11' , tm_min : '13' , tm_hour : '0' , tm_year : '-5' , tm_mday : '17' , tm_wday : '2' , tm_yday : '351' , tm_mon : '11' , tm_isdst : '0' , +IntlDateFormatter locale= en_US ,datetype = 1 ,timetype =1 +Formatted localtime_array is : December 17, 1895 at 12:13:11 AM GMT+5 +Parsed array is: tm_sec : '11' , tm_min : '13' , tm_hour : '0' , tm_year : '-5' , tm_mday : '17' , tm_wday : '2' , tm_yday : '351' , tm_mon : '11' , tm_isdst : '0' , +IntlDateFormatter locale= en_US ,datetype = 2 ,timetype =2 +Formatted localtime_array is : Dec 17, 1895, 12:13:11 AM +Parsed array is: tm_sec : '11' , tm_min : '13' , tm_hour : '0' , tm_year : '-5' , tm_mday : '17' , tm_wday : '2' , tm_yday : '351' , tm_mon : '11' , tm_isdst : '0' , diff --git a/ext/intl/tests/dateformat_set_timezone_id3.phpt b/ext/intl/tests/dateformat_set_timezone_id3.phpt index e0d7cd0e52607..a4952eb5a3dcb 100644 --- a/ext/intl/tests/dateformat_set_timezone_id3.phpt +++ b/ext/intl/tests/dateformat_set_timezone_id3.phpt @@ -6,6 +6,7 @@ date.timezone=Atlantic/Azores intl --SKIPIF-- = 51.2'); ?> += 0) die('skip for ICU < 72.1'); ?> --FILE-- = 4.8 +--INI-- +date.timezone=Atlantic/Azores +--EXTENSIONS-- +intl +--SKIPIF-- += 72.1'); ?> +--FILE-- + +--EXPECTF-- +Warning: IntlDateFormatter::setTimeZone(): datefmt_set_timezone: No such time zone: 'CN' in %sut_common.inc on line %d + +Warning: datefmt_set_timezone(): datefmt_set_timezone: No such time zone: 'CN' in %sut_common.inc on line %d + +After creation of the dateformatter : timezone_id= US/Pacific +----------- +Trying to set timezone_id= America/New_York +After call to set_timezone_id : timezone_id= America/New_York +Formatting timestamp=0 resulted in Wednesday, December 31, 1969 at 7:00:00 PM Eastern Standard Time +Formatting timestamp=3600 resulted in Wednesday, December 31, 1969 at 8:00:00 PM Eastern Standard Time +----------- +Trying to set timezone_id= America/Los_Angeles +After call to set_timezone_id : timezone_id= America/Los_Angeles +Formatting timestamp=0 resulted in Wednesday, December 31, 1969 at 4:00:00 PM Pacific Standard Time +Formatting timestamp=3600 resulted in Wednesday, December 31, 1969 at 5:00:00 PM Pacific Standard Time +----------- +Trying to set timezone_id= America/Chicago +After call to set_timezone_id : timezone_id= America/Chicago +Formatting timestamp=0 resulted in Wednesday, December 31, 1969 at 6:00:00 PM Central Standard Time +Formatting timestamp=3600 resulted in Wednesday, December 31, 1969 at 7:00:00 PM Central Standard Time +----------- +Trying to set timezone_id= CN +After call to set_timezone_id : timezone_id= America/Chicago +Formatting timestamp=0 resulted in Wednesday, December 31, 1969 at 6:00:00 PM Central Standard Time +Formatting timestamp=3600 resulted in Wednesday, December 31, 1969 at 7:00:00 PM Central Standard Time diff --git a/ext/intl/tests/datepatterngenerator_get_best_pattern.phpt b/ext/intl/tests/datepatterngenerator_get_best_pattern.phpt index 9e29bc90493e9..279554123b795 100644 --- a/ext/intl/tests/datepatterngenerator_get_best_pattern.phpt +++ b/ext/intl/tests/datepatterngenerator_get_best_pattern.phpt @@ -2,6 +2,8 @@ IntlDatePatternGenerator::getBestPattern() --EXTENSIONS-- intl +--SKIPIF-- += 0) die('skip for ICU < 72.1'); ?> --FILE-- = 72.1'); ?> +--FILE-- +getBestPattern("jjmm"), "\n"; +echo $dtpg2->getBestPattern("jjmm"), "\n"; +echo $dtpg3->getBestPattern("YYYYMMMdd"), "\n"; +echo $dtpg4->getBestPattern("YYYYMMMdd"), "\n"; + +echo $dtpg->getBestPattern(""), "\n"; + +try { + $dtpg->getBestPattern(); +} catch(\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +h:mm a +HH:mm +MMM dd, YYYY +dd. MMM YYYY + +IntlDatePatternGenerator::getBestPattern() expects exactly 1 argument, 0 given diff --git a/ext/intl/tests/msgfmt_format_datetime.phpt b/ext/intl/tests/msgfmt_format_datetime.phpt index 8b3e37ab30f5d..e6a7451906f77 100644 --- a/ext/intl/tests/msgfmt_format_datetime.phpt +++ b/ext/intl/tests/msgfmt_format_datetime.phpt @@ -4,6 +4,8 @@ MessageFormatter::format(): DateTime accepted to format dates and times date.timezone=Atlantic/Azores --EXTENSIONS-- intl +--SKIPIF-- += 0) die('skip for ICU < 72.1'); ?> --FILE-- = 72.1'); ?> +--FILE-- +format(array($dt))); +var_dump($mf->format(array($dti))); + +?> +--EXPECT-- +string(24) "May 6, 2012 5:00:42 PM" +string(24) "May 6, 2012 5:00:42 PM" diff --git a/ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt b/ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt index 9bc38b683cd0a..f92eaa2bdb54a 100644 --- a/ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt +++ b/ext/intl/tests/msgfmt_format_simple_types_numeric_strings.phpt @@ -4,6 +4,8 @@ MessageFormatter::format(): simple types handling with numeric strings date.timezone=Atlantic/Azores --EXTENSIONS-- intl +--SKIPIF-- += 0) die('skip for ICU < 72.1'); ?> --FILE-- = 72.1'); ?> +--FILE-- +format(array( +'a' => $ex, +'b' => $ex, +'c' => $ex, +'d' => $ex, +'e' => $ex, +'f' => " 1336317965.5", +'g' => " 1336317965.5", +'h' => $ex, +'i' => $ex, +'j' => $ex, +))); + +?> +--EXPECTF-- +string(%d) " + none 1336317965.5 str + number 1,336,317,965.5 + number integer 1,336,317,965 + number currency $1,336,317,965.50 + number percent 133,631,796,550% + date May %d, 2012 + time 3:26:05 PM + spellout one billion three hundred thirty-six million three hundred seventeen thousand nine hundred sixty-five point five + ordinal 1,336,317,966th + duration 371,199:26:06 +" diff --git a/ext/intl/tests/resourcebundle_null_mandatory_args_variant2.phpt b/ext/intl/tests/resourcebundle_null_mandatory_args_variant2.phpt index 31250027184b3..5aefcf268dff5 100644 --- a/ext/intl/tests/resourcebundle_null_mandatory_args_variant2.phpt +++ b/ext/intl/tests/resourcebundle_null_mandatory_args_variant2.phpt @@ -6,6 +6,7 @@ date.timezone=Atlantic/Azores intl --SKIPIF-- = 51.2'); ?> += 0) die('skip for ICU < 72.1'); ?> --FILE-- = 72.1'); ?> +--FILE-- +get('calendar')->get('gregorian')->get('DateTimePatterns')->get(0); +var_dump($c); + +ini_set('intl.default_locale', 'pt_PT'); +$r = new ResourceBundle(NULL, NULL); +$c = $r->get('calendar')->get('gregorian')->get('DateTimePatterns')->get(0); +var_dump($c); +?> +--EXPECT-- +string(16) "h:mm:ss a zzzz" +string(13) "HH:mm:ss zzzz" From d12ba111e03fa4e6d76a66a029f5dbe6265b1ea9 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Tue, 10 Jan 2023 15:15:49 +0000 Subject: [PATCH 58/83] Fixed GH-10218: DateTimeZone fails to parse time zones that contain the "+" character --- NEWS | 2 ++ ext/date/lib/parse_date.c | 4 ++-- ext/date/lib/parse_date.re | 2 +- ext/date/tests/gh10218.phpt | 15 +++++++++++++++ 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 ext/date/tests/gh10218.phpt diff --git a/NEWS b/NEWS index ad29b8f611839..0f8bbc310013e 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,8 @@ PHP NEWS - Date: . Fixed bug GH-9891 (DateTime modify with unixtimestamp (@) must work like setTimestamp). (Derick) + . Fixed bug GH-10218 (DateTimeZone fails to parse time zones that contain the + "+" character). (Derick) - FPM: . Fixed bug GH-9981 (FPM does not reset fastcgi.error_header). diff --git a/ext/date/lib/parse_date.c b/ext/date/lib/parse_date.c index 99ec21baf56e6..78feb7420813c 100644 --- a/ext/date/lib/parse_date.c +++ b/ext/date/lib/parse_date.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.15.3 on Thu Dec 1 10:57:42 2022 */ +/* Generated by re2c 0.15.3 on Tue Jan 10 15:14:08 2023 */ #line 1 "ext/date/lib/parse_date.re" /* * The MIT License (MIT) @@ -761,7 +761,7 @@ static timelib_long timelib_lookup_abbr(const char **ptr, int *dst, char **tz_ab (**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z') || (**ptr >= '0' && **ptr <= '9') || - **ptr == '/' || **ptr == '_' || **ptr == '-' + **ptr == '/' || **ptr == '_' || **ptr == '-' || **ptr == '+' ) { ++*ptr; } diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re index 923091ea89f45..f0db34d302b31 100644 --- a/ext/date/lib/parse_date.re +++ b/ext/date/lib/parse_date.re @@ -759,7 +759,7 @@ static timelib_long timelib_lookup_abbr(const char **ptr, int *dst, char **tz_ab (**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z') || (**ptr >= '0' && **ptr <= '9') || - **ptr == '/' || **ptr == '_' || **ptr == '-' + **ptr == '/' || **ptr == '_' || **ptr == '-' || **ptr == '+' ) { ++*ptr; } diff --git a/ext/date/tests/gh10218.phpt b/ext/date/tests/gh10218.phpt new file mode 100644 index 0000000000000..ff1b493ce7f01 --- /dev/null +++ b/ext/date/tests/gh10218.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug GH-10218 (DateTimeZone fails to parse time zones that contain the "+" character) +--FILE-- + +--EXPECTF-- +object(DateTime)#%d (%d) { + ["date"]=> + string(%d) "%s" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(9) "Etc/GMT+1" +} From 55514a111935153ff33ef26aac0545567b8e12f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 10 Jan 2023 10:02:49 +0100 Subject: [PATCH 59/83] fix: indirect_return compilation warning Closes GH-10274 Signed-off-by: George Peter Banyard --- Zend/zend_portability.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 74f8be3c1a26c..8f545ecba807c 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -679,7 +679,7 @@ extern "C++" { # define ZEND_VOIDP(ptr) (ptr) #endif -#if defined(__GNUC__) && ZEND_GCC_VERSION >= 9000 +#if __has_attribute(__indirect_return__) # define ZEND_INDIRECT_RETURN __attribute__((__indirect_return__)) #else # define ZEND_INDIRECT_RETURN From 1b48a5c80228cc1a115298840084682a4cd060cf Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 12 Jan 2023 11:55:14 +0000 Subject: [PATCH 60/83] Fix ASAN reported leak in FPM config test This happens because config test does not shutdown SAPI. In addition this commit also fixes few failures when running FPM tests under root. Closes GH-10296 --- NEWS | 1 + sapi/fpm/fpm/fpm_main.c | 3 ++- sapi/fpm/tests/bug68591-conf-test-group.phpt | 1 + sapi/fpm/tests/bug68591-conf-test-listen-group.phpt | 1 + sapi/fpm/tests/bug68591-conf-test-listen-owner.phpt | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index def6114b30f19..44631c9b610ff 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,7 @@ PHP NEWS (Jakub Zelenka) . Fixed bug #68591 (Configuration test does not perform UID lookups). (Jakub Zelenka) + . Fixed memory leak when running FPM config test. (Jakub Zelenka) - LDAP: . Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()). diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index c5972f10d1800..0a61abacd70df 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -1798,7 +1798,8 @@ consult the installation file that came with this distribution, or visit \n\ zend_quiet_write(fpm_globals.send_config_pipe[1], &writeval, sizeof(writeval)); close(fpm_globals.send_config_pipe[1]); } - return FPM_EXIT_CONFIG; + exit_status = FPM_EXIT_CONFIG; + goto out; } if (fpm_globals.send_config_pipe[1]) { diff --git a/sapi/fpm/tests/bug68591-conf-test-group.phpt b/sapi/fpm/tests/bug68591-conf-test-group.phpt index 14d6390801163..d496d0549e87f 100644 --- a/sapi/fpm/tests/bug68591-conf-test-group.phpt +++ b/sapi/fpm/tests/bug68591-conf-test-group.phpt @@ -14,6 +14,7 @@ $cfg = << Date: Sun, 8 Jan 2023 19:15:55 +0100 Subject: [PATCH 61/83] Use absolute paths in OPCache tests when calling `opcache_compile_file()` This make sure the tests do not fail if they are not run from the repository root. Closes GH-10266 Signed-off-by: George Peter Banyard --- ext/opcache/tests/gh9968-1.inc | 2 +- ext/opcache/tests/preload_const_autoload.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/tests/gh9968-1.inc b/ext/opcache/tests/gh9968-1.inc index 468178c78483f..0f2b14673513c 100644 --- a/ext/opcache/tests/gh9968-1.inc +++ b/ext/opcache/tests/gh9968-1.inc @@ -1,3 +1,3 @@ Date: Thu, 12 Jan 2023 19:55:54 +0100 Subject: [PATCH 62/83] unserialize: Strictly check for `:{` at object start (#10214) * unserialize: Strictly check for `:{` at object start * unserialize: Update CVE tests It's unlikely that the object syntax error contributed to the actual CVE. The CVE is rather caused by the incorrect object serialization data of the `C` format. Add a second string without such a syntax error to ensure that path is still executed as well to ensure the CVE is absent. * Fix test expectation in gmp/tests/bug74670.phpt No changes to the input required, because the test actually is intended to verify the behavior for a missing `}`, it's just that the report position changed. * NEWS * UPGRADING --- NEWS | 2 ++ UPGRADING | 4 +++ ext/gmp/tests/bug74670.phpt | 2 +- ext/spl/tests/bug73029.phpt | 13 +++++++- ext/standard/tests/serialize/bug73341.phpt | 9 +++++ ext/standard/tests/serialize/bug74111.phpt | 2 +- .../serialize/serialization_objects_017.phpt | 17 ++++++++++ .../serialize/serialization_objects_018.phpt | 33 +++++++++++++++++++ ext/standard/var_unserializer.re | 24 ++++++++++++++ 9 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 ext/standard/tests/serialize/serialization_objects_017.phpt create mode 100644 ext/standard/tests/serialize/serialization_objects_018.phpt diff --git a/NEWS b/NEWS index 44631c9b610ff..d1f9267b44149 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,8 @@ PHP NEWS - Standard: . Fix GH-10187 (Segfault in stripslashes() with arm64). (nielsdos) + . Fixed bug GH-10214 (Incomplete validation of object syntax during + unserialize()). (timwolla) 05 Jan 2023, PHP 8.2.1 diff --git a/UPGRADING b/UPGRADING index 5f69712a4b02b..bc92affa46e80 100644 --- a/UPGRADING +++ b/UPGRADING @@ -223,6 +223,10 @@ PHP 8.2 UPGRADE NOTES widened to iterable from Iterator, allowing arrays to be passed. RFC: https://wiki.php.net/rfc/iterator_xyz_accept_array +- Standard + . unserialize() now performs a stricter validation of the structure of serialized + objects. + - XML . xml_parser_set_option() now actually returns false when attempting to set a negative tag start. Previously it returned true while emitting an E_WARNING. diff --git a/ext/gmp/tests/bug74670.phpt b/ext/gmp/tests/bug74670.phpt index 5f9de9330e591..1d09509a91316 100644 --- a/ext/gmp/tests/bug74670.phpt +++ b/ext/gmp/tests/bug74670.phpt @@ -8,5 +8,5 @@ $str = 'C:3:"GMP":4:{s:6666666666:""}'; var_dump(unserialize($str)); ?> --EXPECTF-- -Notice: unserialize(): Error at offset 13 of 29 bytes in %s on line %d +Notice: unserialize(): Error at offset 17 of 29 bytes in %s on line %d bool(false) diff --git a/ext/spl/tests/bug73029.phpt b/ext/spl/tests/bug73029.phpt index 5c3cd8420da8d..9e002f1182939 100644 --- a/ext/spl/tests/bug73029.phpt +++ b/ext/spl/tests/bug73029.phpt @@ -3,6 +3,13 @@ Bug #73029: Missing type check when unserializing SplArray --FILE-- getMessage() . "\n"; +} +try { $a = 'C:11:"ArrayObject":19:0x:i:0;r:2;;m:a:0:{}}'; $m = unserialize($a); $x = $m[2]; @@ -11,6 +18,10 @@ $x = $m[2]; } ?> DONE ---EXPECT-- +--EXPECTF-- Error at offset 10 of 19 bytes + +Notice: unserialize(): Error at offset 22 of 43 bytes in %s on line %d + +Warning: Trying to access array offset on value of type bool in %s on line %d DONE diff --git a/ext/standard/tests/serialize/bug73341.phpt b/ext/standard/tests/serialize/bug73341.phpt index 2f38949c1ae8f..3bdad06440be0 100644 --- a/ext/standard/tests/serialize/bug73341.phpt +++ b/ext/standard/tests/serialize/bug73341.phpt @@ -2,6 +2,13 @@ Bug #73144 (Use-afte-free in ArrayObject Deserialization) --FILE-- getMessage()."\n"; +} + try { $token = 'a:2:{i:0;O:1:"0":2:0s:1:"0";i:0;s:1:"0";a:1:{i:0;C:11:"ArrayObject":7:{x:i:0;r}'; $obj = unserialize($token); @@ -20,5 +27,7 @@ unserialize($exploit); --EXPECTF-- Error at offset 6 of 7 bytes +Notice: unserialize(): Error at offset 19 of 79 bytes in %s on line %d + Notice: ArrayObject::unserialize(): Unexpected end of serialized data in %sbug73341.php on line %d Error at offset 24 of 34 bytes diff --git a/ext/standard/tests/serialize/bug74111.phpt b/ext/standard/tests/serialize/bug74111.phpt index 62922bea55ae0..2062687aa271e 100644 --- a/ext/standard/tests/serialize/bug74111.phpt +++ b/ext/standard/tests/serialize/bug74111.phpt @@ -6,5 +6,5 @@ $s = 'O:8:"stdClass":00000000'; var_dump(unserialize($s)); ?> --EXPECTF-- -Notice: unserialize(): Error at offset 25 of 23 bytes in %s on line %d +Notice: unserialize(): Error at offset 23 of 23 bytes in %s on line %d bool(false) diff --git a/ext/standard/tests/serialize/serialization_objects_017.phpt b/ext/standard/tests/serialize/serialization_objects_017.phpt new file mode 100644 index 0000000000000..901d73f2b24aa --- /dev/null +++ b/ext/standard/tests/serialize/serialization_objects_017.phpt @@ -0,0 +1,17 @@ +--TEST-- +Object serialization / unserialization: Strict format +--FILE-- + +--EXPECTF-- +Notice: unserialize(): Error at offset 9 of 22 bytes in %s on line %d +bool(false) + +Notice: unserialize(): Error at offset 10 of 22 bytes in %s on line %d +bool(false) diff --git a/ext/standard/tests/serialize/serialization_objects_018.phpt b/ext/standard/tests/serialize/serialization_objects_018.phpt new file mode 100644 index 0000000000000..e05ff5ca04608 --- /dev/null +++ b/ext/standard/tests/serialize/serialization_objects_018.phpt @@ -0,0 +1,33 @@ +--TEST-- +Object serialization / unserialization: Strict format (2) +--FILE-- + +--EXPECTF-- +Notice: unserialize(): Error at offset 9 of 15 bytes in %s on line %d +bool(false) + +Notice: unserialize(): Error at offset 10 of 15 bytes in %s on line %d +bool(false) + +Notice: unserialize(): Error at offset 14 of 15 bytes in %s on line %d +bool(false) + +Notice: unserialize(): Error at offset 8 of 8 bytes in %s on line %d +bool(false) diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index bcf19002fc0a2..313d7fadeb394 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -743,6 +743,19 @@ static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce) datalen = parse_iv2((*p) + 2, p); + if (max - (*p) < 2) { + return 0; + } + + if ((*p)[0] != ':') { + return 0; + } + + if ((*p)[1] != '{') { + (*p) += 1; + return 0; + } + (*p) += 2; if (datalen < 0 || (max - (*p)) <= datalen) { @@ -754,6 +767,7 @@ static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce) * with unserialize reading past the end of the passed buffer if the string is not * appropriately terminated (usually NUL terminated, but '}' is also sufficient.) */ if ((*p)[datalen] != '}') { + (*p) += datalen; return 0; } @@ -1293,6 +1307,16 @@ object ":" uiv ":" ["] { return 0; } + YYCURSOR = *p; + + if (*(YYCURSOR) != ':') { + return 0; + } + if (*(YYCURSOR+1) != '{') { + *p = YYCURSOR+1; + return 0; + } + *p += 2; has_unserialize = !incomplete_class && ce->__unserialize; From 833b45ac4482dade13e3a25c0a46ac492ca1d54b Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 10 Jan 2023 22:55:20 +0100 Subject: [PATCH 63/83] Fix GH-10249: Assertion `size >= page_size + 1 * page_size' failed. Co-authored-by: Changochen Closes GH-10284 --- NEWS | 3 +++ Zend/tests/fibers/gh10249.phpt | 17 +++++++++++++++++ Zend/zend_fibers.c | 6 +++++- 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/fibers/gh10249.phpt diff --git a/NEWS b/NEWS index 0f8bbc310013e..9bcd519364550 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,9 @@ PHP NEWS . Fixed bug GH-10218 (DateTimeZone fails to parse time zones that contain the "+" character). (Derick) +- Fiber: + . Fix assertion on stack allocation size. (nielsdos) + - FPM: . Fixed bug GH-9981 (FPM does not reset fastcgi.error_header). (Jakub Zelenka) diff --git a/Zend/tests/fibers/gh10249.phpt b/Zend/tests/fibers/gh10249.phpt new file mode 100644 index 0000000000000..efbef9c42a2ed --- /dev/null +++ b/Zend/tests/fibers/gh10249.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-10249 (Assertion `size >= page_size + 1 * page_size' failed.) +--FILE-- +start(); +} catch (Exception $e) { + echo $e->getMessage() . "\n"; +} + +?> +--EXPECTF-- +Fiber stack size is too small, it needs to be at least %d bytes diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 1fec85528fbb3..543da605bda44 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -174,8 +174,12 @@ static zend_fiber_stack *zend_fiber_stack_allocate(size_t size) { void *pointer; const size_t page_size = zend_fiber_get_page_size(); + const size_t minimum_stack_size = page_size + ZEND_FIBER_GUARD_PAGES * page_size; - ZEND_ASSERT(size >= page_size + ZEND_FIBER_GUARD_PAGES * page_size); + if (size < minimum_stack_size) { + zend_throw_exception_ex(NULL, 0, "Fiber stack size is too small, it needs to be at least %zu bytes", minimum_stack_size); + return NULL; + } const size_t stack_size = (size + page_size - 1) / page_size * page_size; const size_t alloc_size = stack_size + ZEND_FIBER_GUARD_PAGES * page_size; From fd7214436ab3e77fb9e509019974cd19d685b5a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 12 Jan 2023 23:30:36 +0100 Subject: [PATCH 64/83] Fix comment for php_safe_bcmp (#10306) * main: Fix comment for php_safe_bcmp * main: Include note about php_safe_bcmp being security sensitive This is taken from the implementation of `hash_equals()`. --- main/safe_bcmp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/safe_bcmp.c b/main/safe_bcmp.c index 27a1756d79b46..3e806de4ab6e3 100644 --- a/main/safe_bcmp.c +++ b/main/safe_bcmp.c @@ -19,7 +19,7 @@ #include /* - * Returns 0 if both inputs match, 1 if they don't. + * Returns 0 if both inputs match, non-zero if they don't. * Returns -1 early if inputs do not have the same lengths. * */ @@ -34,6 +34,7 @@ PHPAPI int php_safe_bcmp(const zend_string *a, const zend_string *b) return -1; } + /* This is security sensitive code. Do not optimize this for speed. */ while (i < ZSTR_LEN(a)) { r |= ua[i] ^ ub[i]; ++i; From 120aafcc42c0d24f17b61dec98efb91bba86483b Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 13 Jan 2023 10:31:01 +0000 Subject: [PATCH 65/83] Fix bug #67244: Wrong owner:group for listening unix socket Update FPM www.conf to reflect the actual logic --- NEWS | 2 ++ sapi/fpm/www.conf.in | 16 +++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 9bcd519364550..4145102b3388e 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,8 @@ PHP NEWS - FPM: . Fixed bug GH-9981 (FPM does not reset fastcgi.error_header). (Jakub Zelenka) + . Fixed bug #67244 (Wrong owner:group for listening unix socket). + (Jakub Zelenka) - LDAP: . Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()). diff --git a/sapi/fpm/www.conf.in b/sapi/fpm/www.conf.in index d13b60067fb38..64da6bce1f0e9 100644 --- a/sapi/fpm/www.conf.in +++ b/sapi/fpm/www.conf.in @@ -17,9 +17,14 @@ ; Default Value: none ;prefix = /path/to/pools/$pool -; Unix user/group of processes -; Note: The user is mandatory. If the group is not set, the default user's group -; will be used. +; Unix user/group of the child processes. This can be used only if the master +; process running user is root. It is set after the child process is created. +; The user and group can be specified either by their name or by their numeric +; IDs. +; Note: If the user is root, the executable needs to be started with + --allow-to-run-as-root option to work. +; Default Values: The user is set to master process running user by default. +; If the group is not set, the user's group is used. user = @php_fpm_user@ group = @php_fpm_group@ @@ -43,11 +48,12 @@ listen = 127.0.0.1:9000 ; permissions must be set in order to allow connections from a web server. Many ; BSD-derived systems allow connections regardless of permissions. The owner ; and group can be specified either by name or by their numeric IDs. -; Default Values: user and group are set as the running user -; mode is set to 0660 +; Default Values: Owner is set to the master process running user. If the group +; is not set, the owner's group is used. Mode is set to 0660. ;listen.owner = @php_fpm_user@ ;listen.group = @php_fpm_group@ ;listen.mode = 0660 + ; When POSIX Access Control Lists are supported you can set them using ; these options, value is a comma separated list of user/group names. ; When set, listen.owner and listen.group are ignored From 4fb149390ac54abd3717bb783b1738ec31d0fbee Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 13 Jan 2023 12:04:28 +0100 Subject: [PATCH 66/83] GC fiber unfinished executions (#9810) --- Zend/tests/fibers/gh9735-001.phpt | 37 ++++++++++++++++++ Zend/tests/fibers/gh9735-002.phpt | 41 +++++++++++++++++++ Zend/tests/fibers/gh9735-003.phpt | 40 +++++++++++++++++++ Zend/tests/fibers/gh9735-004.phpt | 40 +++++++++++++++++++ Zend/tests/fibers/gh9735-005.phpt | 44 +++++++++++++++++++++ Zend/tests/fibers/gh9735-006.phpt | 47 ++++++++++++++++++++++ Zend/tests/fibers/gh9735-007.phpt | 47 ++++++++++++++++++++++ Zend/tests/fibers/gh9735-008.phpt | 42 ++++++++++++++++++++ Zend/tests/fibers/gh9735-009.phpt | 42 ++++++++++++++++++++ Zend/zend_execute.c | 65 +++++++++++++++++++++++++++++++ Zend/zend_execute.h | 1 + Zend/zend_fibers.c | 25 +++++++++++- Zend/zend_generators.c | 53 +++---------------------- 13 files changed, 475 insertions(+), 49 deletions(-) create mode 100644 Zend/tests/fibers/gh9735-001.phpt create mode 100644 Zend/tests/fibers/gh9735-002.phpt create mode 100644 Zend/tests/fibers/gh9735-003.phpt create mode 100644 Zend/tests/fibers/gh9735-004.phpt create mode 100644 Zend/tests/fibers/gh9735-005.phpt create mode 100644 Zend/tests/fibers/gh9735-006.phpt create mode 100644 Zend/tests/fibers/gh9735-007.phpt create mode 100644 Zend/tests/fibers/gh9735-008.phpt create mode 100644 Zend/tests/fibers/gh9735-009.phpt diff --git a/Zend/tests/fibers/gh9735-001.phpt b/Zend/tests/fibers/gh9735-001.phpt new file mode 100644 index 0000000000000..327e74323924a --- /dev/null +++ b/Zend/tests/fibers/gh9735-001.phpt @@ -0,0 +1,37 @@ +--TEST-- +Bug GH-9735 001 (Fiber stack variables do not participate in cycle collector) +--FILE-- +start(); +gc_collect_cycles(); + +print "2\n"; + +$fiber = null; +gc_collect_cycles(); + +print "3\n"; + +?> +--EXPECT-- +1 +2 +C::__destruct +3 diff --git a/Zend/tests/fibers/gh9735-002.phpt b/Zend/tests/fibers/gh9735-002.phpt new file mode 100644 index 0000000000000..9a56c65f0abd9 --- /dev/null +++ b/Zend/tests/fibers/gh9735-002.phpt @@ -0,0 +1,41 @@ +--TEST-- +Bug GH-9735 002 (Fiber stack variables do not participate in cycle collector) +--FILE-- +start(); +gc_collect_cycles(); + +print "2\n"; + +$fiber = null; +gc_collect_cycles(); + +print "3\n"; + +?> +--EXPECT-- +1 +2 +C::__destruct +3 diff --git a/Zend/tests/fibers/gh9735-003.phpt b/Zend/tests/fibers/gh9735-003.phpt new file mode 100644 index 0000000000000..03ea973b61dd4 --- /dev/null +++ b/Zend/tests/fibers/gh9735-003.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug GH-9735 003 (Fiber stack variables do not participate in cycle collector) +--FILE-- +start(); +gc_collect_cycles(); + +print "2\n"; + +$fiber = null; +gc_collect_cycles(); + +print "3\n"; + +?> +--EXPECT-- +1 +2 +C::__destruct +3 diff --git a/Zend/tests/fibers/gh9735-004.phpt b/Zend/tests/fibers/gh9735-004.phpt new file mode 100644 index 0000000000000..cfcf381d83d08 --- /dev/null +++ b/Zend/tests/fibers/gh9735-004.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug GH-9735 004 (Fiber stack variables do not participate in cycle collector) +--FILE-- +start(); +gc_collect_cycles(); + +print "2\n"; + +$fiber = null; +gc_collect_cycles(); + +print "3\n"; + +?> +--EXPECT-- +1 +2 +C::__destruct +3 diff --git a/Zend/tests/fibers/gh9735-005.phpt b/Zend/tests/fibers/gh9735-005.phpt new file mode 100644 index 0000000000000..c18a42fc37082 --- /dev/null +++ b/Zend/tests/fibers/gh9735-005.phpt @@ -0,0 +1,44 @@ +--TEST-- +Bug GH-9735 005 (Fiber stack variables do not participate in cycle collector) +--FILE-- +start(); +gc_collect_cycles(); + +print "2\n"; + +$fiber = null; +gc_collect_cycles(); + +print "3\n"; + +?> +--EXPECTF-- +1 +2 +C::__destruct +3 diff --git a/Zend/tests/fibers/gh9735-006.phpt b/Zend/tests/fibers/gh9735-006.phpt new file mode 100644 index 0000000000000..59bb79d2404bc --- /dev/null +++ b/Zend/tests/fibers/gh9735-006.phpt @@ -0,0 +1,47 @@ +--TEST-- +Bug GH-9735 006 (Fiber stack variables do not participate in cycle collector) +--FILE-- +start(); +gc_collect_cycles(); + +print "2\n"; + +$fiber = null; +gc_collect_cycles(); + +print "3\n"; + +?> +--EXPECTF-- +1 +2 +C::__destruct +3 diff --git a/Zend/tests/fibers/gh9735-007.phpt b/Zend/tests/fibers/gh9735-007.phpt new file mode 100644 index 0000000000000..dbb6a33821119 --- /dev/null +++ b/Zend/tests/fibers/gh9735-007.phpt @@ -0,0 +1,47 @@ +--TEST-- +Bug GH-9735 007 (Fiber stack variables do not participate in cycle collector) +--FILE-- +start(); +gc_collect_cycles(); + +print "2\n"; + +$fiber = null; +gc_collect_cycles(); + +print "3\n"; + +?> +--EXPECTF-- +1 +2 +C::__destruct +3 diff --git a/Zend/tests/fibers/gh9735-008.phpt b/Zend/tests/fibers/gh9735-008.phpt new file mode 100644 index 0000000000000..ec6f29fb79de4 --- /dev/null +++ b/Zend/tests/fibers/gh9735-008.phpt @@ -0,0 +1,42 @@ +--TEST-- +Bug GH-9735 008 (Fiber stack variables do not participate in cycle collector) +--FILE-- +start(); +gc_collect_cycles(); + +print "2\n"; + +$fiber = null; +gc_collect_cycles(); + +print "3\n"; + +?> +--EXPECTF-- +1 +2 +C::__destruct +3 diff --git a/Zend/tests/fibers/gh9735-009.phpt b/Zend/tests/fibers/gh9735-009.phpt new file mode 100644 index 0000000000000..c471499443bd4 --- /dev/null +++ b/Zend/tests/fibers/gh9735-009.phpt @@ -0,0 +1,42 @@ +--TEST-- +Bug GH-9735 009 (Fiber stack variables do not participate in cycle collector) +--FILE-- +start(); +gc_collect_cycles(); + +print "2\n"; + +$fiber = null; +gc_collect_cycles(); + +print "3\n"; + +?> +--EXPECTF-- +1 +2 +C::__destruct +3 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 40b89e062e758..fc555bfce1184 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -4450,6 +4450,71 @@ ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, cleanup_live_vars(execute_data, op_num, catch_op_num); } +ZEND_API HashTable *zend_unfinished_execution_gc(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer) +{ + if (!EX(func) || !ZEND_USER_CODE(EX(func)->common.type)) { + return NULL; + } + + zend_op_array *op_array = &EX(func)->op_array; + + if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) { + uint32_t i, num_cvs = EX(func)->op_array.last_var; + for (i = 0; i < num_cvs; i++) { + zend_get_gc_buffer_add_zval(gc_buffer, EX_VAR_NUM(i)); + } + } + + if (EX_CALL_INFO() & ZEND_CALL_FREE_EXTRA_ARGS) { + zval *zv = EX_VAR_NUM(op_array->last_var + op_array->T); + zval *end = zv + (EX_NUM_ARGS() - op_array->num_args); + while (zv != end) { + zend_get_gc_buffer_add_zval(gc_buffer, zv++); + } + } + + if (EX_CALL_INFO() & ZEND_CALL_RELEASE_THIS) { + zend_get_gc_buffer_add_obj(gc_buffer, Z_OBJ(execute_data->This)); + } + if (EX_CALL_INFO() & ZEND_CALL_CLOSURE) { + zend_get_gc_buffer_add_obj(gc_buffer, ZEND_CLOSURE_OBJECT(EX(func))); + } + if (EX_CALL_INFO() & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + zval extra_named_params; + ZVAL_ARR(&extra_named_params, EX(extra_named_params)); + zend_get_gc_buffer_add_zval(gc_buffer, &extra_named_params); + } + + if (call) { + /* -1 required because we want the last run opcode, not the next to-be-run one. */ + uint32_t op_num = execute_data->opline - op_array->opcodes - 1; + zend_unfinished_calls_gc(execute_data, call, op_num, gc_buffer); + } + + if (execute_data->opline != op_array->opcodes) { + uint32_t i, op_num = execute_data->opline - op_array->opcodes - 1; + for (i = 0; i < op_array->last_live_range; i++) { + const zend_live_range *range = &op_array->live_range[i]; + if (range->start > op_num) { + break; + } else if (op_num < range->end) { + uint32_t kind = range->var & ZEND_LIVE_MASK; + uint32_t var_num = range->var & ~ZEND_LIVE_MASK; + zval *var = EX_VAR(var_num); + if (kind == ZEND_LIVE_TMPVAR || kind == ZEND_LIVE_LOOP) { + zend_get_gc_buffer_add_zval(gc_buffer, var); + } + } + } + } + + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { + return execute_data->symbol_table; + } else { + return NULL; + } +} + #if ZEND_VM_SPEC static void zend_swap_operands(zend_op *op) /* {{{ */ { diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index f09a8fe769417..3e61967cb2bea 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -378,6 +378,7 @@ ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table); ZEND_API void ZEND_FASTCALL zend_free_compiled_variables(zend_execute_data *execute_data); ZEND_API void zend_unfinished_calls_gc(zend_execute_data *execute_data, zend_execute_data *call, uint32_t op_num, zend_get_gc_buffer *buf); ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num); +ZEND_API HashTable *zend_unfinished_execution_gc(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer); zval * ZEND_FASTCALL zend_handle_named_arg( zend_execute_data **call_ptr, zend_string *arg_name, diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 543da605bda44..432be61e652b9 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -24,6 +24,8 @@ #include "zend_exceptions.h" #include "zend_builtin_functions.h" #include "zend_observer.h" +#include "zend_compile.h" +#include "zend_closures.h" #include "zend_fibers.h" #include "zend_fibers_arginfo.h" @@ -641,9 +643,30 @@ static HashTable *zend_fiber_object_gc(zend_object *object, zval **table, int *n zend_get_gc_buffer_add_zval(buf, &fiber->fci.function_name); zend_get_gc_buffer_add_zval(buf, &fiber->result); + if (fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED) { + zend_get_gc_buffer_use(buf, table, num); + return NULL; + } + + HashTable *lastSymTable = NULL; + zend_execute_data *ex = fiber->execute_data; + for (; ex; ex = ex->prev_execute_data) { + HashTable *symTable = zend_unfinished_execution_gc(ex, ex->call, buf); + if (symTable) { + if (lastSymTable) { + zval *val; + ZEND_HASH_FOREACH_VAL(lastSymTable, val) { + ZEND_ASSERT(Z_TYPE_P(val) == IS_INDIRECT); + zend_get_gc_buffer_add_zval(buf, Z_INDIRECT_P(val)); + } ZEND_HASH_FOREACH_END(); + } + lastSymTable = symTable; + } + } + zend_get_gc_buffer_use(buf, table, num); - return NULL; + return lastSymTable; } ZEND_METHOD(Fiber, __construct) diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 71bf2f092debd..d5253e46eddf2 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -332,7 +332,7 @@ static HashTable *zend_generator_get_gc(zend_object *object, zval **table, int * { zend_generator *generator = (zend_generator*)object; zend_execute_data *execute_data = generator->execute_data; - zend_op_array *op_array; + zend_execute_data *call = NULL; if (!execute_data) { /* If the generator has been closed, it can only hold on to three values: The value, key @@ -352,7 +352,6 @@ static HashTable *zend_generator_get_gc(zend_object *object, zval **table, int * return NULL; } - op_array = &EX(func)->op_array; zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); zend_get_gc_buffer_add_zval(gc_buffer, &generator->value); @@ -360,59 +359,17 @@ static HashTable *zend_generator_get_gc(zend_object *object, zval **table, int * zend_get_gc_buffer_add_zval(gc_buffer, &generator->retval); zend_get_gc_buffer_add_zval(gc_buffer, &generator->values); - if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) { - uint32_t i, num_cvs = EX(func)->op_array.last_var; - for (i = 0; i < num_cvs; i++) { - zend_get_gc_buffer_add_zval(gc_buffer, EX_VAR_NUM(i)); - } - } - - if (EX_CALL_INFO() & ZEND_CALL_FREE_EXTRA_ARGS) { - zval *zv = EX_VAR_NUM(op_array->last_var + op_array->T); - zval *end = zv + (EX_NUM_ARGS() - op_array->num_args); - while (zv != end) { - zend_get_gc_buffer_add_zval(gc_buffer, zv++); - } + if (UNEXPECTED(generator->frozen_call_stack)) { + /* The frozen stack is linked in reverse order */ + call = zend_generator_revert_call_stack(generator->frozen_call_stack); } - if (EX_CALL_INFO() & ZEND_CALL_RELEASE_THIS) { - zend_get_gc_buffer_add_obj(gc_buffer, Z_OBJ(execute_data->This)); - } - if (EX_CALL_INFO() & ZEND_CALL_CLOSURE) { - zend_get_gc_buffer_add_obj(gc_buffer, ZEND_CLOSURE_OBJECT(EX(func))); - } - if (EX_CALL_INFO() & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { - zval extra_named_params; - ZVAL_ARR(&extra_named_params, EX(extra_named_params)); - zend_get_gc_buffer_add_zval(gc_buffer, &extra_named_params); - } + zend_unfinished_execution_gc(execute_data, call, gc_buffer); if (UNEXPECTED(generator->frozen_call_stack)) { - /* The frozen stack is linked in reverse order */ - zend_execute_data *call = zend_generator_revert_call_stack(generator->frozen_call_stack); - /* -1 required because we want the last run opcode, not the next to-be-run one. */ - uint32_t op_num = execute_data->opline - op_array->opcodes - 1; - zend_unfinished_calls_gc(execute_data, call, op_num, gc_buffer); zend_generator_revert_call_stack(call); } - if (execute_data->opline != op_array->opcodes) { - uint32_t i, op_num = execute_data->opline - op_array->opcodes - 1; - for (i = 0; i < op_array->last_live_range; i++) { - const zend_live_range *range = &op_array->live_range[i]; - if (range->start > op_num) { - break; - } else if (op_num < range->end) { - uint32_t kind = range->var & ZEND_LIVE_MASK; - uint32_t var_num = range->var & ~ZEND_LIVE_MASK; - zval *var = EX_VAR(var_num); - if (kind == ZEND_LIVE_TMPVAR || kind == ZEND_LIVE_LOOP) { - zend_get_gc_buffer_add_zval(gc_buffer, var); - } - } - } - } - if (generator->node.parent) { zend_get_gc_buffer_add_obj(gc_buffer, &generator->node.parent->std); } From 0f7625c47c18bbb3c44ab30d7c5505fc53d8c62f Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 13 Jan 2023 12:05:51 +0100 Subject: [PATCH 67/83] Reduce HT_MAX_SIZE to account for the max load factor of 0.5 (#10242) zend_hash allocates a hash table twice as big as nTableSize (HT_HASH_SIZE(HT_SIZE_TO_MASK(nTableSize)) == nTableSize*2), so HT_MAX_SIZE must be half the max table size or less. Fixes GH-10240 --- Zend/zend_hash.c | 10 ++++++++++ Zend/zend_types.h | 13 ++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index cf0f9e5b332c4..a13bb196924e6 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -166,6 +166,8 @@ static zend_always_inline void zend_hash_real_init_mixed_ex(HashTable *ht) void *data; uint32_t nSize = ht->nTableSize; + ZEND_ASSERT(HT_SIZE_TO_MASK(nSize)); + if (UNEXPECTED(GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)) { data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), 1); } else if (EXPECTED(nSize == HT_MIN_SIZE)) { @@ -341,6 +343,8 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht) Bucket *old_buckets = ht->arData; uint32_t nSize = ht->nTableSize; + ZEND_ASSERT(HT_SIZE_TO_MASK(nSize)); + HT_ASSERT_RC1(ht); HT_FLAGS(ht) &= ~HASH_FLAG_PACKED; new_data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); @@ -369,7 +373,11 @@ ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht) ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, bool packed) { HT_ASSERT_RC1(ht); + if (nSize == 0) return; + + ZEND_ASSERT(HT_SIZE_TO_MASK(nSize)); + if (UNEXPECTED(HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED)) { if (nSize > ht->nTableSize) { ht->nTableSize = zend_hash_check_size(nSize); @@ -1207,6 +1215,8 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht) uint32_t nSize = ht->nTableSize + ht->nTableSize; Bucket *old_buckets = ht->arData; + ZEND_ASSERT(HT_SIZE_TO_MASK(nSize)); + ht->nTableSize = nSize; new_data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); ht->nTableMask = HT_SIZE_TO_MASK(ht->nTableSize); diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 3d42d481a6530..5bc47dd31934e 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -400,8 +400,15 @@ struct _zend_array { #define HT_MIN_MASK ((uint32_t) -2) #define HT_MIN_SIZE 8 +/* HT_MAX_SIZE is chosen to satisfy the following constraints: + * - HT_SIZE_TO_MASK(HT_MAX_SIZE) != 0 + * - HT_SIZE_EX(HT_MAX_SIZE, HT_SIZE_TO_MASK(HT_MAX_SIZE)) does not overflow or + * wrapparound, and is <= the addressable space size + * - HT_MAX_SIZE must be a power of two: + * (nTableSize Date: Fri, 13 Jan 2023 12:29:51 +0100 Subject: [PATCH 68/83] [ci skip] NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index edb0ca3d11f78..bb9d4ec331b7a 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ PHP NEWS . Fixed bug GH-10200 (zif_get_object_vars: Assertion `!(((__ht)->u.flags & (1<<2)) != 0)' failed). (nielsdos) . Fix GH-10251 (Assertion `(flag & (1<<3)) == 0' failed). (nielsdos) + . Fix GH-10240 (Assertion failure when adding more than 2**30 elements to an + unpacked array). (Arnaud) + . Fix GH-9735 (Fiber stack variables do not participate in cycle collector). + (Arnaud) - FPM: . Fixed bug #77106 (Missing separator in FPM FastCGI errors). (Jakub Zelenka) From 8c0698f66bbaa87de56e38ace03466c9e0c2f2bd Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 13 Jan 2023 17:43:17 +0100 Subject: [PATCH 69/83] Fix run-tests.php hanging when a worker process dies without notice (#9931) run-tests.php with `-jN` can hang if a parallel worker dies without notice. This can happen due to fatal errors in the worker, or if the worker is killed. - run-tests.php (main process) \_ run-tests.php (worker #0) // main process hangs if this one crashes \_ test-001.php (test-001.phpt) --- run-tests.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/run-tests.php b/run-tests.php index 16241c08cc6cc..edfab1f57adcd 100755 --- a/run-tests.php +++ b/run-tests.php @@ -1583,6 +1583,10 @@ function run_all_tests_parallel(array $test_files, array $env, $redir_tested): v kill_children($workerProcs); error("Could not find worker stdout in array of worker stdouts, THIS SHOULD NOT HAPPEN."); } + if (feof($workerSock)) { + kill_children($workerProcs); + error("Worker $i died unexpectedly"); + } while (false !== ($rawMessage = fgets($workerSock))) { // work around fgets truncating things if (($rawMessageBuffers[$i] ?? '') !== '') { From 7d98e3e40c12dacd882835bce76e4f235ef4bba7 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sat, 14 Jan 2023 15:13:43 +0000 Subject: [PATCH 70/83] Fix missing comment in FPM www.conf.in --- sapi/fpm/www.conf.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapi/fpm/www.conf.in b/sapi/fpm/www.conf.in index 64da6bce1f0e9..4b8eb7caa3a37 100644 --- a/sapi/fpm/www.conf.in +++ b/sapi/fpm/www.conf.in @@ -22,7 +22,7 @@ ; The user and group can be specified either by their name or by their numeric ; IDs. ; Note: If the user is root, the executable needs to be started with - --allow-to-run-as-root option to work. +; --allow-to-run-as-root option to work. ; Default Values: The user is set to master process running user by default. ; If the group is not set, the user's group is used. user = @php_fpm_user@ From 4bbbe6d6525165f6fd74b7ae59fdf5ec08278816 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 14 Jan 2023 21:01:22 +0100 Subject: [PATCH 71/83] Fix substr_replace with slots in repl_ht being UNDEF The check that was supposed to check whether the array slot was UNDEF was wrong and never triggered. This resulted in a replacement with the empty string or the wrong string instead of the correct one. The correct check pattern can be observed higher up in the function's code. Closes GH-10323 Signed-off-by: George Peter Banyard --- NEWS | 1 + ext/standard/string.c | 2 +- .../strings/substr_replace_array_unset.phpt | 27 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/strings/substr_replace_array_unset.phpt diff --git a/NEWS b/NEWS index 4145102b3388e..9b57198a8db4f 100644 --- a/NEWS +++ b/NEWS @@ -48,6 +48,7 @@ PHP NEWS - Standard: . Fix GH-10187 (Segfault in stripslashes() with arm64). (nielsdos) + . Fix substr_replace with slots in repl_ht being UNDEF. (nielsdos) - TSRM: . Fixed Windows shmget() wrt. IPC_PRIVATE. (Tyson Andre) diff --git a/ext/standard/string.c b/ext/standard/string.c index e171448f243e1..643094263bfcb 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -2472,7 +2472,7 @@ PHP_FUNCTION(substr_replace) if (repl_ht) { while (repl_idx < repl_ht->nNumUsed) { tmp_repl = &repl_ht->arData[repl_idx].val; - if (repl_ht != IS_UNDEF) { + if (Z_TYPE_P(tmp_repl) != IS_UNDEF) { break; } repl_idx++; diff --git a/ext/standard/tests/strings/substr_replace_array_unset.phpt b/ext/standard/tests/strings/substr_replace_array_unset.phpt new file mode 100644 index 0000000000000..ff253d3984476 --- /dev/null +++ b/ext/standard/tests/strings/substr_replace_array_unset.phpt @@ -0,0 +1,27 @@ +--TEST-- +substr_replace() function - array with unset +--FILE-- + 'bar', 'baz']; +unset($replacement[42]); +$newarr = substr_replace(['1 string', '2 string'], $replacement, 0); +print_r($newarr); + +?> +--EXPECT-- +Array +( + [0] => A + [1] => B +) +Array +( + [0] => foo + [1] => baz +) From 11a1feb0d767ecd3946fcf361185fe04c1b7a135 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 14 Jan 2023 23:38:38 +0100 Subject: [PATCH 72/83] Fix missing check for xmlTextWriterEndElement xmlTextWriterEndElement returns -1 if the call fails. There was already a check for retval, but the return value wasn't assigned to retval. The other caller of xmlTextWriterEndElement is in xmlwriter_write_element_ns, which does the check correctly. Closes GH-10324 Signed-off-by: George Peter Banyard --- NEWS | 3 +++ ext/xmlwriter/php_xmlwriter.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 9b57198a8db4f..88c58842899b3 100644 --- a/NEWS +++ b/NEWS @@ -53,6 +53,9 @@ PHP NEWS - TSRM: . Fixed Windows shmget() wrt. IPC_PRIVATE. (Tyson Andre) +- XMLWriter + . Fix missing check for xmlTextWriterEndElement (nielsdos) + 05 Jan 2023, PHP 8.1.14 - Core: diff --git a/ext/xmlwriter/php_xmlwriter.c b/ext/xmlwriter/php_xmlwriter.c index e9a3dff2781f5..24ce414034af5 100644 --- a/ext/xmlwriter/php_xmlwriter.c +++ b/ext/xmlwriter/php_xmlwriter.c @@ -449,7 +449,7 @@ PHP_FUNCTION(xmlwriter_write_element) if (retval == -1) { RETURN_FALSE; } - xmlTextWriterEndElement(ptr); + retval = xmlTextWriterEndElement(ptr); if (retval == -1) { RETURN_FALSE; } From 347b7c3628e0d2be87a05d8760124c9c71f29d51 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 15 Jan 2023 15:05:36 +0100 Subject: [PATCH 73/83] Fix wrong flags check for compression method in phar_object.c I found this issue using static analysis tools, it reported that the condition was always false. We can see that flags is assigned in the switch statement above, but a mistake was made in the comparison. Closes GH-10328 Signed-off-by: George Peter Banyard --- NEWS | 3 +++ ext/phar/phar_object.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 88c58842899b3..5c5cd7e73a1dc 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,9 @@ PHP NEWS . Fix zend_jit_find_trace() crashes. (Max Kellermann) . Added missing lock for EXIT_INVALIDATE in zend_jit_trace_exit. (Max Kellermann) +- Phar: + . Fix wrong flags check for compression method in phar_object.c (nielsdos) + - PHPDBG: . Fix undefined behaviour in phpdbg_load_module_or_extension(). (nielsdos) . Fix NULL pointer dereference in phpdbg_create_conditional_breal(). (nielsdos) diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 448d03b7cc75e..e32b530b82297 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -3312,7 +3312,7 @@ PHP_METHOD(Phar, compressFiles) } if (!pharobj_cancompress(&phar_obj->archive->manifest)) { - if (flags == PHAR_FILE_COMPRESSED_GZ) { + if (flags == PHAR_ENT_COMPRESSED_GZ) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot compress all files as Gzip, some are compressed as bzip2 and cannot be decompressed"); } else { From 0d011e4626249e4d2aa252eeedf524e18c7c50c6 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 16 Jan 2023 11:15:30 +0300 Subject: [PATCH 74/83] Revert "Merge branch 'PHP-8.0' into PHP-8.1" This reverts commit 0116864cd312f9756f38a0ee0f83bb302a7e367b, reversing changes made to 1f715f5658f5909a9346f56812fa605744d23880. --- ext/openssl/openssl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 0f2a0838d3f08..7bfa4be58763a 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1320,7 +1320,9 @@ PHP_MINIT_FUNCTION(openssl) REGISTER_LONG_CONSTANT("OPENSSL_CMS_NOSIGS", CMS_NOSIGS, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_PADDING", RSA_PKCS1_PADDING, CONST_CS|CONST_PERSISTENT); +#ifdef RSA_SSLV23_PADDING REGISTER_LONG_CONSTANT("OPENSSL_SSLV23_PADDING", RSA_SSLV23_PADDING, CONST_CS|CONST_PERSISTENT); +#endif REGISTER_LONG_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_CS|CONST_PERSISTENT); From 42eed7bb4e63399f2e79ee6735d04a4398b838dc Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 16 Jan 2023 14:51:26 +0300 Subject: [PATCH 75/83] Fix GH-10271: Incorrect arithmetic calculations when using JIT --- ext/opcache/jit/zend_jit_x86.dasc | 6 ++++ ext/opcache/tests/jit/gh10271.phpt | 47 ++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 ext/opcache/tests/jit/gh10271.phpt diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 6bc7d53a16fe1..57a2cc9b28c96 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -16209,11 +16209,17 @@ static zend_regset zend_jit_get_scratch_regset(const zend_op *opline, const zend } } if ((op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_DOUBLE)) { + if (opline->op1_type == IS_CONST) { + ZEND_REGSET_INCL(regset, ZREG_R0); + } if (ssa_op->result_def != current_var) { ZEND_REGSET_INCL(regset, ZREG_XMM0); } } if ((op1_info & MAY_BE_DOUBLE) && (op2_info & MAY_BE_LONG)) { + if (opline->op2_type == IS_CONST) { + ZEND_REGSET_INCL(regset, ZREG_R0); + } if (zend_is_commutative(opline->opcode)) { if (ssa_op->result_def != current_var) { ZEND_REGSET_INCL(regset, ZREG_XMM0); diff --git a/ext/opcache/tests/jit/gh10271.phpt b/ext/opcache/tests/jit/gh10271.phpt new file mode 100644 index 0000000000000..77c43e3d50a0d --- /dev/null +++ b/ext/opcache/tests/jit/gh10271.phpt @@ -0,0 +1,47 @@ +--TEST-- +GH-10271: Incorrect arithmetic calculations when using JIT +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +opcache.jit_hot_loop=1 +--FILE-- +$x,'y'=>$y]; +} +?> +--EXPECT-- +0: In;-0.000516528926;-0.000912408759;968.000000000000;548.000000000000;Out;967.500000000004;547.500000000009 +1: In;-0.000516528926;-0.000912408759;968.000000000000;548.000000000000;Out;967.500000000004;547.500000000009 +2: In;-0.000516528926;-0.000912408759;968.000000000000;548.000000000000;Out;967.500000000004;547.500000000009 From e560592a61c01b8a5df5256ac18361803fae252e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petar=20Obradovi=C4=87?= Date: Wed, 21 Dec 2022 12:23:58 +0100 Subject: [PATCH 76/83] Fix GH-9675: Re-adjust run_time_cache init for internal enum methods Closes GH-10143. --- NEWS | 2 ++ Zend/zend_API.c | 2 +- Zend/zend_enum.c | 7 +++++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 827d2e211374c..2f0783bade4b7 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS unpacked array). (Arnaud) . Fix GH-9735 (Fiber stack variables do not participate in cycle collector). (Arnaud) + . Fix GH-9675 (Broken run_time_cache init for internal enum methods). + (Petar Obradović, Bob) - FPM: . Fixed bug #77106 (Missing separator in FPM FastCGI errors). (Jakub Zelenka) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index f613121ee4ad0..5ba91249bd8e2 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2714,7 +2714,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend internal_function->prototype = NULL; internal_function->attributes = NULL; if (EG(active)) { // at run-time: this ought to only happen if registered with dl() or somehow temporarily at runtime - ZEND_MAP_PTR_INIT(internal_function->run_time_cache, zend_arena_alloc(&CG(arena), zend_internal_run_time_cache_reserved_size())); + ZEND_MAP_PTR_INIT(internal_function->run_time_cache, zend_arena_calloc(&CG(arena), 1, zend_internal_run_time_cache_reserved_size())); } else { ZEND_MAP_PTR_NEW(internal_function->run_time_cache); } diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index 59befde732194..25261cf53f880 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -409,8 +409,11 @@ static void zend_enum_register_func(zend_class_entry *ce, zend_known_string_id n zif->module = EG(current_module); zif->scope = ce; zif->T = ZEND_OBSERVER_ENABLED; - ZEND_MAP_PTR_NEW(zif->run_time_cache); - ZEND_MAP_PTR_SET(zif->run_time_cache, zend_arena_alloc(&CG(arena), zend_internal_run_time_cache_reserved_size())); + if (EG(active)) { // at run-time + ZEND_MAP_PTR_INIT(zif->run_time_cache, zend_arena_calloc(&CG(arena), 1, zend_internal_run_time_cache_reserved_size())); + } else { + ZEND_MAP_PTR_NEW(zif->run_time_cache); + } if (!zend_hash_add_ptr(&ce->function_table, name, zif)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(name)); From dfe9c2af19a0e7621dacbd44c83ea0b94af8b113 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 15 Jan 2023 15:29:03 +0100 Subject: [PATCH 77/83] Fix incorrect comparison in block optimization pass We're in the case of ZEND_JMPZ_EX or ZEND_JMPNZ_EX. The opcode gets overwritten and only after the overwriting gets checked if we're in a JMPZ or JMPNZ case. This results in a wrong optimization. Close GH-10329 --- NEWS | 1 + Zend/Optimizer/block_pass.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 5c5cd7e73a1dc..a8a72492a968a 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ PHP NEWS . Fixed bug GH-10072 (PHP crashes when execute_ex is overridden and a __call trampoline is used from internal code). (Derick) . Fix GH-10251 (Assertion `(flag & (1<<3)) == 0' failed). (nielsdos) + . Fix wrong comparison in block optimisation pass after opcode update. (nieldsdos) - Date: . Fixed bug GH-9891 (DateTime modify with unixtimestamp (@) must work like diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index 79207edb3d8b9..72ae012066094 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -671,13 +671,13 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array case ZEND_JMPNZ_EX: while (1) { if (opline->op1_type == IS_CONST) { - if (zend_is_true(&ZEND_OP1_LITERAL(opline)) == - (opline->opcode == ZEND_JMPZ_EX)) { + bool is_jmpz_ex = opline->opcode == ZEND_JMPZ_EX; + if (zend_is_true(&ZEND_OP1_LITERAL(opline)) == is_jmpz_ex) { ++(*opt_count); opline->opcode = ZEND_QM_ASSIGN; zval_ptr_dtor_nogc(&ZEND_OP1_LITERAL(opline)); - ZVAL_BOOL(&ZEND_OP1_LITERAL(opline), opline->opcode == ZEND_JMPZ_EX); + ZVAL_BOOL(&ZEND_OP1_LITERAL(opline), is_jmpz_ex); opline->op2.num = 0; block->successors_count = 1; block->successors[0] = block->successors[1]; From a6a20c9e1770457790cabde0d88bca742b593c1b Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Tue, 17 Jan 2023 11:14:00 +0100 Subject: [PATCH 78/83] Add regression test for e560592a61c01b8a5df5256ac18361803fae252e Reproduces only under ASAN. Signed-off-by: Bob Weinand --- Zend/tests/gh10346.phpt | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Zend/tests/gh10346.phpt diff --git a/Zend/tests/gh10346.phpt b/Zend/tests/gh10346.phpt new file mode 100644 index 0000000000000..74fce28e2307c --- /dev/null +++ b/Zend/tests/gh10346.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-10346 (Observer: enum tryFrom() run_time_cache properly assigned) +--CREDITS-- +Florian Sowade +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +--FILE-- + +--EXPECTF-- + + + + + + + +enum(Card::HEART) + + From 398a10a58a764a18723bea394afdeac92f881e10 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 16 Jan 2023 23:09:58 +0100 Subject: [PATCH 79/83] Fix phpdbg segmentation fault in case of malformed input If you were to enter "w $>" the function would crash with a segmentation fault because last_index is still NULL at that point. Fix it by checking for NULL and erroring out if it is. Closes GH-10353 Signed-off-by: George Peter Banyard --- NEWS | 1 + sapi/phpdbg/phpdbg_utils.c | 3 +++ sapi/phpdbg/tests/watch_007.phpt | 25 +++++++++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 sapi/phpdbg/tests/watch_007.phpt diff --git a/NEWS b/NEWS index a8a72492a968a..069ae40f597f9 100644 --- a/NEWS +++ b/NEWS @@ -46,6 +46,7 @@ PHP NEWS . Fix undefined behaviour in phpdbg_load_module_or_extension(). (nielsdos) . Fix NULL pointer dereference in phpdbg_create_conditional_breal(). (nielsdos) . Fix GH-9710: phpdbg memory leaks by option "-h" (nielsdos) + . Fix phpdbg segmentation fault in case of malformed input (nielsdos) - Posix: . Fix memory leak in posix_ttyname() (girgias) diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c index 344b9c73e476d..f638d608905ba 100644 --- a/sapi/phpdbg/phpdbg_utils.c +++ b/sapi/phpdbg/phpdbg_utils.c @@ -466,6 +466,9 @@ PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable case ']': break; case '>': + if (!last_index) { + goto error; + } if (last_index[index_len - 1] == '-') { new_index = 1; index_len--; diff --git a/sapi/phpdbg/tests/watch_007.phpt b/sapi/phpdbg/tests/watch_007.phpt new file mode 100644 index 0000000000000..f1980d60dd9de --- /dev/null +++ b/sapi/phpdbg/tests/watch_007.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test malformed watchpoint name +--INI-- +opcache.optimization_level=0 +--PHPDBG-- +b test +r +w $> +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at test] +prompt> [Breakpoint #0 in test() at %s:%d, hits: 1] +>00004: } + 00005: test(); + 00006: $a = 2; +prompt> [Malformed input] +prompt> +--FILE-- + Date: Mon, 16 Jan 2023 22:33:06 +0100 Subject: [PATCH 80/83] Handle exceptions from __toString in XXH3's initialization The initialization routine for XXH3 was not prepared for exceptions from seed. Fix this by using try_convert_to_string. For discussion, please see: GH-10305 Closes GH-10352 Signed-off-by: George Peter Banyard --- NEWS | 3 +++ ext/hash/hash_xxhash.c | 4 +++- ext/hash/tests/xxhash_secret.phpt | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 069ae40f597f9..6d206f825234f 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,9 @@ PHP NEWS . Fixed bug #67244 (Wrong owner:group for listening unix socket). (Jakub Zelenka) +- Hash: + . Handle exceptions from __toString in XXH3's initialization (nielsdos) + - LDAP: . Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()). (cmb) diff --git a/ext/hash/hash_xxhash.c b/ext/hash/hash_xxhash.c index 7ecedd81287ce..8a155c9862271 100644 --- a/ext/hash/hash_xxhash.c +++ b/ext/hash/hash_xxhash.c @@ -174,7 +174,9 @@ zend_always_inline static void _PHP_XXH3_Init(PHP_XXH3_64_CTX *ctx, HashTable *a func_init_seed(&ctx->s, (XXH64_hash_t)Z_LVAL_P(_seed)); return; } else if (_secret) { - convert_to_string(_secret); + if (!try_convert_to_string(_secret)) { + return; + } size_t len = Z_STRLEN_P(_secret); if (len < PHP_XXH3_SECRET_SIZE_MIN) { zend_throw_error(NULL, "%s: Secret length must be >= %u bytes, %zu bytes passed", algo_name, XXH3_SECRET_SIZE_MIN, len); diff --git a/ext/hash/tests/xxhash_secret.phpt b/ext/hash/tests/xxhash_secret.phpt index 91e7d929d323d..6f1efbe6c90a6 100644 --- a/ext/hash/tests/xxhash_secret.phpt +++ b/ext/hash/tests/xxhash_secret.phpt @@ -3,6 +3,13 @@ Hash: xxHash secret --FILE-- getMessage()); } + try { + $ctx = hash_init($a, options: ["secret" => new StringableThrowingClass()]); + } catch (Throwable $e) { + var_dump($e->getMessage()); + } + try { $ctx = hash_init($a, options: ["secret" => str_repeat('a', 17)]); } catch (Throwable $e) { @@ -35,8 +48,10 @@ foreach (["xxh3", "xxh128"] as $a) { ?> --EXPECT-- string(67) "xxh3: Only one of seed or secret is to be passed for initialization" +string(23) "exception in __toString" string(57) "xxh3: Secret length must be >= 136 bytes, 17 bytes passed" 8028aa834c03557a == 8028aa834c03557a == true string(69) "xxh128: Only one of seed or secret is to be passed for initialization" +string(23) "exception in __toString" string(59) "xxh128: Secret length must be >= 136 bytes, 17 bytes passed" 54279097795e7218093a05d4d781cbb9 == 54279097795e7218093a05d4d781cbb9 == true From c47a1a260d67d1991081a6050a4460feaa73dcad Mon Sep 17 00:00:00 2001 From: Patrick Allaert Date: Tue, 17 Jan 2023 17:24:25 +0100 Subject: [PATCH 81/83] PHP-8.1 is now for PHP 8.1.16-dev --- NEWS | 5 ++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 6d206f825234f..3911a49570222 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.15 +?? ??? ????, PHP 8.1.16 + + +02 Feb 2023, PHP 8.1.15 - Apache: . Fixed bug GH-9949 (Partial content on incomplete POST request). (cmb) diff --git a/Zend/zend.h b/Zend/zend.h index ac3a826a4813b..16b0ce6a1bd82 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.15-dev" +#define ZEND_VERSION "4.1.16-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index f7e15261412b1..6bf3274d2705b 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.15-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.16-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 165364047e310..4231920700d72 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 15 +#define PHP_RELEASE_VERSION 16 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.15-dev" -#define PHP_VERSION_ID 80115 +#define PHP_VERSION "8.1.16-dev" +#define PHP_VERSION_ID 80116 From 36d55f8918fc57912e9c8c5721ddcaf1be4f6b9c Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 27 Jan 2023 10:52:42 +0100 Subject: [PATCH 82/83] Handle non-INDIRECT symbol table entries in zend_fiber_object_gc() (#10386) Fixes GH-10340 --- Zend/tests/fibers/gh10340-001.phpt | 19 +++++++++++++++ Zend/tests/fibers/gh10340-002.phpt | 19 +++++++++++++++ Zend/tests/fibers/gh10340-003.phpt | 38 ++++++++++++++++++++++++++++++ Zend/zend_fibers.c | 6 +++-- 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/fibers/gh10340-001.phpt create mode 100644 Zend/tests/fibers/gh10340-002.phpt create mode 100644 Zend/tests/fibers/gh10340-003.phpt diff --git a/Zend/tests/fibers/gh10340-001.phpt b/Zend/tests/fibers/gh10340-001.phpt new file mode 100644 index 0000000000000..0c34b4a787bce --- /dev/null +++ b/Zend/tests/fibers/gh10340-001.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug GH-10340 001 (Assertion in zend_fiber_object_gc()) +--FILE-- +start(); +gc_collect_cycles(); +?> +==DONE== +--EXPECTF-- +Warning: Undefined variable $y in %s on line %d +==DONE== diff --git a/Zend/tests/fibers/gh10340-002.phpt b/Zend/tests/fibers/gh10340-002.phpt new file mode 100644 index 0000000000000..6c8f8016cbf12 --- /dev/null +++ b/Zend/tests/fibers/gh10340-002.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug GH-10340 002 (Assertion in zend_fiber_object_gc()) +--FILE-- +start(); +gc_collect_cycles(); +?> +==DONE== +--EXPECT-- +==DONE== diff --git a/Zend/tests/fibers/gh10340-003.phpt b/Zend/tests/fibers/gh10340-003.phpt new file mode 100644 index 0000000000000..6e59223a2a9c9 --- /dev/null +++ b/Zend/tests/fibers/gh10340-003.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug GH-10340 003 (Assertion in zend_fiber_object_gc()) +--FILE-- +start(); + +print "1\n"; + +$fiber = null; +gc_collect_cycles(); + +print "2\n"; +?> +==DONE== +--EXPECT-- +1 +C::__destruct +2 +==DONE== diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index ed85834b81b57..93502fa00c3a0 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -674,8 +674,10 @@ static HashTable *zend_fiber_object_gc(zend_object *object, zval **table, int *n if (lastSymTable) { zval *val; ZEND_HASH_FOREACH_VAL(lastSymTable, val) { - ZEND_ASSERT(Z_TYPE_P(val) == IS_INDIRECT); - zend_get_gc_buffer_add_zval(buf, Z_INDIRECT_P(val)); + if (EXPECTED(Z_TYPE_P(val) == IS_INDIRECT)) { + val = Z_INDIRECT_P(val); + } + zend_get_gc_buffer_add_zval(buf, val); } ZEND_HASH_FOREACH_END(); } lastSymTable = symTable; From b20c0e925fe401a44a99b0d34b438797be865bb0 Mon Sep 17 00:00:00 2001 From: Sergey Panteleev Date: Tue, 31 Jan 2023 16:29:31 +0300 Subject: [PATCH 83/83] Update versions for PHP 8.2.2 --- NEWS | 2 +- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index ca7dd848fce7a..661be47ada6e3 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.2 +02 Feb 2023, PHP 8.2.2 - Core: . Fixed bug GH-10200 (zif_get_object_vars: diff --git a/Zend/zend.h b/Zend/zend.h index 5e613207ae142..535b6cb15d55d 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.2.2-dev" +#define ZEND_VERSION "4.2.2" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index efc2c2d6899a7..5696e562d2110 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.2.2-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.2],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 42c94eeece9bb..05099d8764096 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -3,6 +3,6 @@ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 2 #define PHP_RELEASE_VERSION 2 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.2.2-dev" +#define PHP_EXTRA_VERSION "" +#define PHP_VERSION "8.2.2" #define PHP_VERSION_ID 80202