Commit 9eeb1e8f7e9 for php
commit 9eeb1e8f7e944e77597831568aea8c78e4198405
Author: NickSdot <32384907+NickSdot@users.noreply.github.com>
Date: Mon Sep 28 02:12:06 2026 +0700
ext/uri: fixed url path resolution (#23817)
diff --git a/ext/uri/tests/whatwg/builder/path_success_hashmark_with_base.phpt b/ext/uri/tests/whatwg/builder/path_success_hashmark_with_base.phpt
new file mode 100644
index 00000000000..0f385b2d73f
--- /dev/null
+++ b/ext/uri/tests/whatwg/builder/path_success_hashmark_with_base.phpt
@@ -0,0 +1,53 @@
+--TEST--
+Test Uri\WhatWg\UrlBuilder::setPath() - success - hashmark with base URL
+--FILE--
+<?php
+
+$base = new Uri\WhatWg\Url('https://user:pass@example.com:123/base/path?oldQuery#oldFragment');
+
+$errors = [];
+
+$url = new Uri\WhatWg\UrlBuilder()
+ ->setPath('newPath#value')
+ ->build($base, $errors);
+
+var_dump($url->toAsciiString());
+var_dump($url);
+var_dump($errors);
+var_dump($url->equals(new Uri\WhatWg\Url($url->toAsciiString())));
+var_dump($url->equals(new Uri\WhatWg\Url('newPath%23value', $base), Uri\UriComparisonMode::IncludeFragment));
+
+?>
+--EXPECTF--
+string(54) "https://user:pass@example.com:123/base/newPath%23value"
+object(Uri\WhatWg\Url)#%d (%d) {
+ ["scheme"]=>
+ string(5) "https"
+ ["username"]=>
+ string(4) "user"
+ ["password"]=>
+ string(4) "pass"
+ ["host"]=>
+ string(11) "example.com"
+ ["port"]=>
+ int(123)
+ ["path"]=>
+ string(21) "/base/newPath%23value"
+ ["query"]=>
+ NULL
+ ["fragment"]=>
+ NULL
+}
+array(1) {
+ [0]=>
+ object(Uri\WhatWg\UrlValidationError)#%d (%d) {
+ ["context"]=>
+ string(6) "#value"
+ ["type"]=>
+ enum(Uri\WhatWg\UrlValidationErrorType::InvalidUrlUnit)
+ ["failure"]=>
+ bool(false)
+ }
+}
+bool(true)
+bool(true)
diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c
index 3e1e587da75..5170849e328 100644
--- a/ext/uri/uri_parser_whatwg.c
+++ b/ext/uri/uri_parser_whatwg.c
@@ -1137,6 +1137,10 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser
smart_str_appends(&reference, "%3F");
} else if (*p == '#') {
smart_str_appends(&reference, "%23");
+ const char *reason;
+ append_validation_error(
+ Z_ARRVAL(errors), LXB_URL_ERROR_TYPE_INVALID_URL_UNIT, p, &reason
+ );
} else {
smart_str_appendc(&reference, *p);
}