diff --git a/src/wp-includes/rest-api/class-wp-rest-request.php b/src/wp-includes/rest-api/class-wp-rest-request.php index 3257194e547d2..96e9468175eda 100644 --- a/src/wp-includes/rest-api/class-wp-rest-request.php +++ b/src/wp-includes/rest-api/class-wp-rest-request.php @@ -458,13 +458,23 @@ public function set_param( $key, $value ) { $found_key = false; foreach ( $order as $type ) { - if ( 'defaults' !== $type && is_array( $this->params[ $type ] ) && array_key_exists( $key, $this->params[ $type ] ) ) { - $this->params[ $type ][ $key ] = $value; - $found_key = true; + if ( 'defaults' !== $type && isset( $this->params[ $type ] ) ) { + + if ( ! is_array( $this->params[ $type ] ) ) { + $this->params[ $type ] = array(); + } + + if ( array_key_exists( $key, $this->params[ $type ] ) ) { + $this->params[ $type ][ $key ] = $value; + $found_key = true; + } } } if ( ! $found_key ) { + if ( ! isset( $this->params[ $order[0] ] ) || ! is_array( $this->params[ $order[0] ] ) ) { + $this->params[ $order[0] ] = array(); + } $this->params[ $order[0] ][ $key ] = $value; } } @@ -821,7 +831,7 @@ public function sanitize_params() { $invalid_details = array(); foreach ( $order as $type ) { - if ( empty( $this->params[ $type ] ) ) { + if ( empty( $this->params[ $type ] ) || ! is_array( $this->params[ $type ] ) ) { continue; } diff --git a/tests/phpunit/tests/rest-api/rest-request.php b/tests/phpunit/tests/rest-api/rest-request.php index 1067739ed2469..fcc6089ecf5b4 100644 --- a/tests/phpunit/tests/rest-api/rest-request.php +++ b/tests/phpunit/tests/rest-api/rest-request.php @@ -1082,6 +1082,92 @@ public function test_route_level_validate_callback_is_not_executed_if_parameter_ $this->assertSame( 'rest_invalid_param', $valid->get_error_code() ); } + /** + * @ticket 61061 + */ + public function test_set_param_with_non_array_parameter_types() { + $request = new WP_REST_Request(); + $request->add_header( 'Content-Type', 'application/json' ); + $request->set_method( 'POST' ); + $request->set_body( '"invalid json string"' ); + + $request->set_param( 'test_param', 'test_value' ); + + $this->assertTrue( $request->has_param( 'test_param' ) ); + $this->assertSame( 'test_value', $request->get_param( 'test_param' ) ); + } + + /** + * @ticket 61061 + */ + public function test_set_param_with_malformed_json_from_curl_request() { + $request = new WP_REST_Request(); + $request->add_header( 'Content-Type', 'application/json' ); + $request->set_method( 'POST' ); + $request->set_body( '"+response.write(document.domain)+"' ); + + $request->set_param( 'test_param', 'test_value' ); + + $this->assertTrue( $request->has_param( 'test_param' ) ); + $this->assertSame( 'test_value', $request->get_param( 'test_param' ) ); + } + + /** + * @ticket 61061 + */ + public function test_sanitize_and_validate_params_with_non_array_parameter_types() { + $request = new WP_REST_Request(); + $request->add_header( 'Content-Type', 'application/json' ); + $request->set_method( 'POST' ); + $request->set_body( '"invalid json string"' ); + + $request->set_attributes( + array( + 'args' => array( + 'someinteger' => array( + 'sanitize_callback' => 'absint', + ), + 'required_param' => array( + 'required' => true, + ), + ), + ) + ); + + $sanitize_result = $request->sanitize_params(); + $this->assertTrue( $sanitize_result ); + + $validation_result = $request->has_valid_params(); + $this->assertWPError( $validation_result ); + $this->assertSame( 'rest_missing_callback_param', $validation_result->get_error_code() ); + } + + /** + * @ticket 61061 + */ + public function test_scalar_request_body_should_not_throw_fatal_errors() { + + $user_id = self::factory()->user->create( + array( + 'role' => 'editor', + ) + ); + + wp_set_current_user( $user_id ); + + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', $user_id ) ); + $request->set_header( 'Content-Type', 'application/json' ); + $request->set_body( '"+response.write(document.domain)+"' ); + + try { + $response = rest_get_server()->dispatch( $request ); + $this->assertNotNull( $response, 'Response should not be null' ); + $this->assertInstanceOf( 'WP_REST_Response', $response, 'Response should be a WP_REST_Response object' ); + } catch ( Exception $e ) { + $this->fail( 'Fatal error thrown when parsing scalar request body.' ); + } + } + /** * Tests that WP_REST_Request::is_method() correctly detects the request method, * regardless of case sensitivity.