Commit c67088d46e8 for php.net

commit c67088d46e802e7e8576c52b76cd50f9ae77680b
Author: Máté Kocsis <kocsismate@woohoolabs.com>
Date:   Sun Sep 20 08:09:09 2026 +0200

    ext/uri: Fix the behavior for $softErrors (#23740)

    Uri\WhatWg\Url::__construct() and Uri\WhatWg\UrlBuilder::build() now set $softErrors to an empty array when URL processing throws an exception, instead of preserving its value.

diff --git a/UPGRADING b/UPGRADING
index f2a2ef8f5e7..a8ae2045f89 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -318,6 +318,12 @@ PHP 8.6 UPGRADE NOTES
     platform's key_t range instead of passing a truncated key to the operating
     system.

+- URI:
+  . Uri\WhatWg\Url::__construct() now sets $softErrors to an empty array when
+    URL processing throws an exception, instead of preserving its value.
+    URL validation errors remain available in the
+    Uri\WhatWg\InvalidUrlException::$errors property.
+
 - Zip:
   . ZipArchive::extractTo now raises a TypeError for the files argument if one
     or more of the entries is not a string.
diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c
index 9d6e58dc181..aab94e94618 100644
--- a/ext/uri/php_uri.c
+++ b/ext/uri/php_uri.c
@@ -387,6 +387,8 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri(
 	if (UNEXPECTED(uri == NULL)) {
 		if (should_throw) {
 			zval_ptr_dtor(&errors);
+			ZVAL_EMPTY_ARRAY(&errors);
+			pass_errors_by_ref_and_free(errors_zv, &errors);
 			RETURN_THROWS();
 		} else {
 			if (pass_errors_by_ref_and_free(errors_zv, &errors) == FAILURE) {
@@ -1433,6 +1435,9 @@ PHP_METHOD(Uri_WhatWg_UrlBuilder, build)
 		soft_errors
 	);
 	if (lexbor_url == NULL) {
+		zval errors;
+		ZVAL_EMPTY_ARRAY(&errors);
+		pass_errors_by_ref_and_free(soft_errors, &errors);
 		RETURN_THROWS();
 	}

diff --git a/ext/uri/tests/whatwg/builder/build_error_normalized_empty_host_password.phpt b/ext/uri/tests/whatwg/builder/build_error_normalized_empty_host_password.phpt
index 76a170f4e26..f81ba3a518b 100644
--- a/ext/uri/tests/whatwg/builder/build_error_normalized_empty_host_password.phpt
+++ b/ext/uri/tests/whatwg/builder/build_error_normalized_empty_host_password.phpt
@@ -7,17 +7,14 @@
 $builder->setScheme("foo");
 $builder->setHost("\t\n");
 $builder->setPassword("pass");
-$softErrors = ["unchanged"];

 try {
-    $builder->build(softErrors: $softErrors);
+    $builder->build();
 } catch (Throwable $e) {
     echo $e::class, ': ', $e->getMessage(), "\n";
     var_dump($e->errors);
 }

-var_dump($softErrors);
-
 ?>
 --EXPECTF--
 Uri\WhatWg\InvalidUrlException: The specified URL cannot have password
@@ -33,7 +30,3 @@ enum(Uri\WhatWg\UrlValidationErrorType::InvalidUrlUnit)
     bool(false)
   }
 }
-array(1) {
-  [0]=>
-  string(9) "unchanged"
-}
diff --git a/ext/uri/tests/whatwg/builder/build_error_normalized_empty_host_port.phpt b/ext/uri/tests/whatwg/builder/build_error_normalized_empty_host_port.phpt
index 6b63a86d2ee..903e14dd75b 100644
--- a/ext/uri/tests/whatwg/builder/build_error_normalized_empty_host_port.phpt
+++ b/ext/uri/tests/whatwg/builder/build_error_normalized_empty_host_port.phpt
@@ -7,17 +7,14 @@
 $builder->setScheme("foo");
 $builder->setHost("\t\n");
 $builder->setPort(123);
-$softErrors = ["unchanged"];

 try {
-    $builder->build(softErrors: $softErrors);
+    $builder->build();
 } catch (Throwable $e) {
     echo $e::class, ': ', $e->getMessage(), "\n";
     var_dump($e->errors);
 }

-var_dump($softErrors);
-
 ?>
 --EXPECTF--
 Uri\WhatWg\InvalidUrlException: The specified URL cannot have port
@@ -33,7 +30,3 @@ enum(Uri\WhatWg\UrlValidationErrorType::InvalidUrlUnit)
     bool(false)
   }
 }
-array(1) {
-  [0]=>
-  string(9) "unchanged"
-}
diff --git a/ext/uri/tests/whatwg/builder/build_error_normalized_empty_host_username.phpt b/ext/uri/tests/whatwg/builder/build_error_normalized_empty_host_username.phpt
index 534271bd29e..0189c8ff161 100644
--- a/ext/uri/tests/whatwg/builder/build_error_normalized_empty_host_username.phpt
+++ b/ext/uri/tests/whatwg/builder/build_error_normalized_empty_host_username.phpt
@@ -7,17 +7,14 @@
 $builder->setScheme("foo");
 $builder->setHost("\t\n");
 $builder->setUsername("user");
-$softErrors = ["unchanged"];

 try {
-    $builder->build(softErrors: $softErrors);
+    $builder->build();
 } catch (Throwable $e) {
     echo $e::class, ': ', $e->getMessage(), "\n";
     var_dump($e->errors);
 }

-var_dump($softErrors);
-
 ?>
 --EXPECTF--
 Uri\WhatWg\InvalidUrlException: The specified URL cannot have username
@@ -33,7 +30,3 @@ enum(Uri\WhatWg\UrlValidationErrorType::InvalidUrlUnit)
     bool(false)
   }
 }
-array(1) {
-  [0]=>
-  string(9) "unchanged"
-}
diff --git a/ext/uri/tests/whatwg/builder/build_error_soft_errors_unchanged.phpt b/ext/uri/tests/whatwg/builder/build_error_soft_errors_reset.phpt
similarity index 84%
rename from ext/uri/tests/whatwg/builder/build_error_soft_errors_unchanged.phpt
rename to ext/uri/tests/whatwg/builder/build_error_soft_errors_reset.phpt
index 5cba13e51c1..f43ab31164b 100644
--- a/ext/uri/tests/whatwg/builder/build_error_soft_errors_unchanged.phpt
+++ b/ext/uri/tests/whatwg/builder/build_error_soft_errors_reset.phpt
@@ -1,12 +1,12 @@
 --TEST--
-Test Uri\WhatWg\UrlBuilder::build() - error - leaves soft errors unchanged
+Test Uri\WhatWg\UrlBuilder::build() - error - clears soft errors when an exception is thrown
 --FILE--
 <?php

 $builder = new Uri\WhatWg\UrlBuilder();
 $builder->setScheme("ht\ttps");
 $builder->setHost(null);
-$softErrors = ["unchanged"];
+$softErrors = ["previous error"];

 try {
     $builder->build(softErrors: $softErrors);
@@ -40,7 +40,5 @@ enum(Uri\WhatWg\UrlValidationErrorType::HostMissing)
     bool(true)
   }
 }
-array(1) {
-  [0]=>
-  string(9) "unchanged"
+array(0) {
 }
diff --git a/ext/uri/tests/whatwg/parsing/basic_error_soft_errors_unchanged.phpt b/ext/uri/tests/whatwg/parsing/basic_error_soft_errors_reset.phpt
similarity index 79%
rename from ext/uri/tests/whatwg/parsing/basic_error_soft_errors_unchanged.phpt
rename to ext/uri/tests/whatwg/parsing/basic_error_soft_errors_reset.phpt
index 2f7549f4757..36eaaec426a 100644
--- a/ext/uri/tests/whatwg/parsing/basic_error_soft_errors_unchanged.phpt
+++ b/ext/uri/tests/whatwg/parsing/basic_error_soft_errors_reset.phpt
@@ -1,9 +1,9 @@
 --TEST--
-Test Uri\WhatWg\Url::__construct() - error - leaves soft errors unchanged
+Test Uri\WhatWg\Url::__construct() - error - clears soft errors when an exception is thrown
 --FILE--
 <?php

-$softErrors = ["unchanged"];
+$softErrors = ["previous error"];

 try {
     new Uri\WhatWg\Url("🐘", softErrors: $softErrors);
@@ -28,7 +28,5 @@ enum(Uri\WhatWg\UrlValidationErrorType::MissingSchemeNonRelativeUrl)
     bool(true)
   }
 }
-array(1) {
-  [0]=>
-  string(9) "unchanged"
+array(0) {
 }