Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/wp-includes/IXR/class-IXR-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ function call($methodname, $args)
}
$method = $this->callbacks[$methodname];

// Ensure $args is an array. Callers such as system.multicall can pass
// non-array params derived from untrusted client input.
if (!is_array($args)) {
$args = array($args);
}

// Perform the callback and send the response
if (count($args) == 1) {
// If only one parameter just send that instead of the whole array
Expand Down Expand Up @@ -198,7 +204,17 @@ function multiCall($methodcalls)
{
// See http://www.xmlrpc.com/discuss/msgReader$1208
$return = array();
if (!is_array($methodcalls)) {
return new IXR_Error(-32600, 'server error. invalid xml-rpc. methodcalls is not an array');
}
foreach ($methodcalls as $call) {
if (!is_array($call) || !isset($call['methodName']) || !isset($call['params']) || !is_array($call['params'])) {
$return[] = array(
'faultCode' => -32602,
'faultString' => 'server error. invalid method call structure',
);
continue;
}
$method = $call['methodName'];
$params = $call['params'];
if ($method == 'system.multicall') {
Expand Down
83 changes: 83 additions & 0 deletions tests/phpunit/tests/xmlrpc/basic.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,89 @@ public function test_multicall_invalidates_all_calls_after_invalid_call() {
$this->assertArrayHasKey( 'faultCode', $result[2] );
}

/**
* Ensures IXR_Server::call() does not fatal when $args is not an array.
*
* @ticket 65124
*/
public function test_call_with_non_array_args_does_not_fatal() {
$this->myxmlrpcserver->callbacks = $this->myxmlrpcserver->methods;

// Passing a string instead of an array must not produce a TypeError on PHP 8+.
$result = $this->myxmlrpcserver->call( 'system.listMethods', 'not-an-array' );

// The dispatch may return an IXR_Error or a value, but it must not fatal.
$this->assertNotNull( $result );
}

/**
* Ensures system.multicall returns a fault for malformed per-call entries
* rather than triggering a fatal error.
*
* @ticket 65124
*
* @dataProvider data_malformed_multicall_payloads
*
* @param array $method_calls Method calls payload supplied to multiCall().
* @param int $expected_index Index in the response expected to contain a fault.
*/
public function test_multicall_rejects_malformed_calls( $method_calls, $expected_index ) {
$this->myxmlrpcserver->callbacks = $this->myxmlrpcserver->methods;

$result = $this->myxmlrpcserver->multiCall( $method_calls );

$this->assertArrayHasKey( 'faultCode', $result[ $expected_index ] );
$this->assertSame( -32602, $result[ $expected_index ]['faultCode'] );
}

public function data_malformed_multicall_payloads() {
return array(
'params is a string' => array(
array(
array(
'methodName' => 'system.listMethods',
'params' => 'evil',
),
),
0,
),
'params is null' => array(
array(
array(
'methodName' => 'system.listMethods',
'params' => null,
),
),
0,
),
'missing params key' => array(
array(
array( 'methodName' => 'system.listMethods' ),
),
0,
),
'call is a scalar' => array(
array( 'just-a-string' ),
0,
),
);
}

/**
* Ensures system.multicall returns a top-level error when the methodcalls
* payload itself is not an array.
*
* @ticket 65124
*/
public function test_multicall_with_non_array_methodcalls_returns_error() {
$this->myxmlrpcserver->callbacks = $this->myxmlrpcserver->methods;

$result = $this->myxmlrpcserver->multiCall( 'not-an-array' );

$this->assertInstanceOf( 'IXR_Error', $result );
$this->assertSame( -32600, $result->code );
}

/**
* @ticket 36586
*/
Expand Down
Loading