Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion src/wp-includes/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -3428,7 +3428,7 @@ function rest_convert_error_to_response( $error ) {
$status = array_reduce(
$error->get_all_error_data(),
static function ( $status, $error_data ) {
return $error_data['status'] ?? $status;
return is_array( $error_data ) && isset( $error_data['status'] ) ? $error_data['status'] : $status;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an opportunity to further harden this, however. Namely, there is no guarantee that $error_data['status'] is an integer. If it is something else, then the $status will get passed to new WP_REST_Response( $data, $status ) which will then get passed into \WP_HTTP_Response::set_status() and ultmately passed here:

public function set_status( $code ) {
$this->status = absint( $code );
}

Passing a non-numeric value to absint() results in a value of 1 being set as the status. This is not a fatal error, but it is wrong. Therefore, this would be even safer:

Suggested change
return is_array( $error_data ) && isset( $error_data['status'] ) ? $error_data['status'] : $status;
if ( is_array( $error_data ) && isset( $error_data['status'] ) && is_numeric( $error_data['status'] ) ) {
$status = (int) $error_data['status'];
}
return $status;

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Great suggestion. I've added the is_numeric() check and (int) cast, along with a test for non-numeric status values.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nate-allen Great! I also followed up with ea57364 to add explicit types, to use phpdoc instead of the inline comment, and I updated the test to account for the possibility that there could be more than one data item added that has status. Please take a look.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! The type hints and expanded multi-status test are nice additions

},
500
);
Expand Down
13 changes: 13 additions & 0 deletions tests/phpunit/tests/rest-api/rest-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,19 @@ public function test_error_to_response_with_additional_data() {
$this->assertSame( array( array( 'status' => 400 ) ), $response->get_data()['additional_data'] );
}

/**
* @ticket 64901
*/
public function test_error_to_response_with_stdclass_data() {
$error = new WP_Error( 'test', 'test', (object) array( 'status' => 400 ) );

$response = rest_convert_error_to_response( $error );
$this->assertInstanceOf( 'WP_REST_Response', $response );

// stdClass data should not cause a fatal, status should default to 500.
$this->assertSame( 500, $response->get_status() );
}

public function test_rest_error() {
$data = array(
'code' => 'wp-api-test-error',
Expand Down
Loading