From baae4f2b30c6f515c6ee3f7d38167afd63849b42 Mon Sep 17 00:00:00 2001 From: Chris Rosser Date: Fri, 13 Feb 2026 12:25:02 +1300 Subject: [PATCH 1/4] IXR: check if host key exists before accessing it in IXR_Client `parse_url()` does not always return a `host` key (e.g. for relative paths). Use the null coalescing operator to fall back to an empty string, consistent with how `port` and `path` are already handled. Adds a unit test to verify no error is triggered when the host is missing. Trac: https://core.trac.wordpress.org/ticket/64635 --- src/wp-includes/IXR/class-IXR-client.php | 2 +- tests/phpunit/tests/xmlrpc/client.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/IXR/class-IXR-client.php b/src/wp-includes/IXR/class-IXR-client.php index 34c1f9337c461..3fa37576c2b61 100644 --- a/src/wp-includes/IXR/class-IXR-client.php +++ b/src/wp-includes/IXR/class-IXR-client.php @@ -30,7 +30,7 @@ function __construct( $server, $path = false, $port = 80, $timeout = 15 ) if (!$path) { // Assume we have been given a URL instead $bits = parse_url($server); - $this->server = $bits['host']; + $this->server = $bits['host'] ?? ''; $this->port = $bits['port'] ?? 80; $this->path = $bits['path'] ?? '/'; diff --git a/tests/phpunit/tests/xmlrpc/client.php b/tests/phpunit/tests/xmlrpc/client.php index a13980c17d174..a2cf37ae2e467 100644 --- a/tests/phpunit/tests/xmlrpc/client.php +++ b/tests/phpunit/tests/xmlrpc/client.php @@ -17,6 +17,11 @@ public function test_ixr_client_allows_query_strings() { $this->assertSame( '/server.php?this-is-needed=true', $client->path ); } + public function test_ixr_client_does_not_error_when_host_is_missing() { + $client = new IXR_Client( '/no-host-here' ); + $this->assertSame( '', $client->server ); + } + /** * @ticket 26947 */ From 83b39bdd35bd18095bd87bafa509ed1a337d131e Mon Sep 17 00:00:00 2001 From: Chris R Date: Fri, 13 Feb 2026 15:51:51 +1300 Subject: [PATCH 2/4] Add @ticket reference to unit test Co-authored-by: Weston Ruter --- tests/phpunit/tests/xmlrpc/client.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/phpunit/tests/xmlrpc/client.php b/tests/phpunit/tests/xmlrpc/client.php index a2cf37ae2e467..5e61dff5282e4 100644 --- a/tests/phpunit/tests/xmlrpc/client.php +++ b/tests/phpunit/tests/xmlrpc/client.php @@ -17,6 +17,9 @@ public function test_ixr_client_allows_query_strings() { $this->assertSame( '/server.php?this-is-needed=true', $client->path ); } + /** + * @ticket 64635 + */ public function test_ixr_client_does_not_error_when_host_is_missing() { $client = new IXR_Client( '/no-host-here' ); $this->assertSame( '', $client->server ); From 2413b12952b0fb9d96bac6b294f943d317e4f347 Mon Sep 17 00:00:00 2001 From: Chris Rosser Date: Mon, 16 Feb 2026 17:26:29 +1300 Subject: [PATCH 3/4] Incorporate WP_HTTP_IXR_Client fixes from #40784 --- src/wp-includes/class-wp-http-ixr-client.php | 4 +-- tests/phpunit/tests/xmlrpc/client.php | 31 +++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/class-wp-http-ixr-client.php b/src/wp-includes/class-wp-http-ixr-client.php index 71875d550fc2f..688083668f883 100644 --- a/src/wp-includes/class-wp-http-ixr-client.php +++ b/src/wp-includes/class-wp-http-ixr-client.php @@ -23,8 +23,8 @@ public function __construct( $server, $path = false, $port = false, $timeout = 1 if ( ! $path ) { // Assume we have been given a URL instead. $bits = parse_url( $server ); - $this->scheme = $bits['scheme']; - $this->server = $bits['host']; + $this->scheme = $bits['scheme'] ?? ''; + $this->server = $bits['host'] ?? ''; $this->port = $bits['port'] ?? $port; $this->path = ! empty( $bits['path'] ) ? $bits['path'] : '/'; diff --git a/tests/phpunit/tests/xmlrpc/client.php b/tests/phpunit/tests/xmlrpc/client.php index 5e61dff5282e4..75734d8e150b7 100644 --- a/tests/phpunit/tests/xmlrpc/client.php +++ b/tests/phpunit/tests/xmlrpc/client.php @@ -20,7 +20,7 @@ public function test_ixr_client_allows_query_strings() { /** * @ticket 64635 */ - public function test_ixr_client_does_not_error_when_host_is_missing() { + public function test_ixr_client_can_handle_missing_host() { $client = new IXR_Client( '/no-host-here' ); $this->assertSame( '', $client->server ); } @@ -34,4 +34,33 @@ public function test_wp_ixr_client_allows_query_strings() { $this->assertFalse( $client->port ); $this->assertSame( '/server.php?this-is-needed=true', $client->path ); } + + /** + * @ticket 40784 + */ + public function test_wp_ixr_client_can_handle_protocolless_urls() { + $client = new WP_HTTP_IXR_Client( '//example.com/server.php' ); + $this->assertSame( '', $client->scheme ); + $this->assertSame( 'example.com', $client->server ); + } + + /** + * @ticket 40784 + */ + public function test_wp_ixr_client_can_handle_relative_urls() { + $client = new WP_HTTP_IXR_Client( '/server.php' ); + $this->assertSame( '', $client->scheme ); + $this->assertSame( '', $client->server ); + $this->assertSame( '/server.php', $client->path ); + } + + /** + * @ticket 40784 + */ + public function test_wp_ixr_client_can_handle_invalid_urls() { + $client = new WP_HTTP_IXR_Client( '' ); + $this->assertSame( '', $client->scheme ); + $this->assertSame( '', $client->server ); + $this->assertSame( '/', $client->path ); + } } From abf51d7cb4612ace97eff804ae669024d1ac3ea7 Mon Sep 17 00:00:00 2001 From: Chris R Date: Tue, 17 Feb 2026 12:06:31 +1300 Subject: [PATCH 4/4] Use null coalescing operator on $this->path Co-authored-by: Weston Ruter --- src/wp-includes/class-wp-http-ixr-client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/class-wp-http-ixr-client.php b/src/wp-includes/class-wp-http-ixr-client.php index 688083668f883..f8b0b144f8b26 100644 --- a/src/wp-includes/class-wp-http-ixr-client.php +++ b/src/wp-includes/class-wp-http-ixr-client.php @@ -26,7 +26,7 @@ public function __construct( $server, $path = false, $port = false, $timeout = 1 $this->scheme = $bits['scheme'] ?? ''; $this->server = $bits['host'] ?? ''; $this->port = $bits['port'] ?? $port; - $this->path = ! empty( $bits['path'] ) ? $bits['path'] : '/'; + $this->path = $bits['path'] ?? '/'; // Make absolutely sure we have a path. if ( ! $this->path ) {