WordPress.org

Make WordPress Core

Ticket #38547: 38547.diff

File 38547.diff, 3.0 KB (added by rmccue, 4 years ago)

Check for JSON encoding errors in has_valid_params

  • src/wp-includes/rest-api/class-wp-rest-request.php

     
    651651         * Avoids parsing the JSON data until we need to access it.
    652652         *
    653653         * @since 4.4.0
     654         * @since 4.7.0 Returns error instance if value cannot be decoded.
    654655         * @access protected
     656         * @return true|WP_Error True if the JSON data was passed or no JSON data was provided, WP_Error if invalid JSON was passed.
    655657         */
    656658        protected function parse_json_params() {
    657659                if ( $this->parsed_json ) {
    658                         return;
     660                        return true;
    659661                }
    660662
    661663                $this->parsed_json = true;
     
    664666                $content_type = $this->get_content_type();
    665667
    666668                if ( empty( $content_type ) || 'application/json' !== $content_type['value'] ) {
    667                         return;
     669                        return true;
    668670                }
    669671
    670672                $params = json_decode( $this->get_body(), true );
     
    676678                 * might not be defined: https://core.trac.wordpress.org/ticket/27799
    677679                 */
    678680                if ( null === $params && ( ! function_exists( 'json_last_error' ) || JSON_ERROR_NONE !== json_last_error() ) ) {
    679                         return;
     681                        // Ensure subsequent calls receive error instance.
     682                        $this->parsed_json = false;
     683
     684                        $error_data = array(
     685                                'status' => WP_Http::BAD_REQUEST,
     686                                'json_error_code' => json_last_error(),
     687                                'json_error_message' => json_last_error_msg(),
     688                        );
     689                        return new WP_Error( 'rest_invalid_json', __( 'Invalid JSON body passed.' ), $error_data );
    680690                }
    681691
    682692                $this->params['JSON'] = $params;
     693                return true;
    683694        }
    684695
    685696        /**
     
    841852         *                       WP_Error if required parameters are missing.
    842853         */
    843854        public function has_valid_params() {
     855                // If JSON data was passed, check for errors.
     856                $json_error = $this->parse_json_params();
     857                if ( is_wp_error( $json_error ) ) {
     858                        return $json_error;
     859                }
     860
    844861                $attributes = $this->get_attributes();
    845862                $required = array();
    846863
  • tests/phpunit/tests/rest-api/rest-request.php

     
    399399                $this->assertEquals( 'rest_invalid_param', $valid->get_error_code() );
    400400        }
    401401
     402        public function test_has_valid_params_json_error() {
     403                if ( version_compare( PHP_VERSION, '5.3', '<' ) ) {
     404                        return $this->markTestSkipped( 'JSON validation is only available for PHP 5.3+' );
     405                }
     406
     407                $this->request->set_header( 'Content-Type', 'application/json' );
     408                $this->request->set_body( '{"invalid": JSON}' );
     409
     410                $valid = $this->request->has_valid_params();
     411                $this->assertWPError( $valid );
     412                $this->assertEquals( 'rest_invalid_json', $valid->get_error_code() );
     413                $data = $valid->get_error_data();
     414                $this->assertEquals( JSON_ERROR_SYNTAX, $data['json_error_code'] );
     415        }
     416
    402417        public function test_has_multiple_invalid_params_validate_callback() {
    403418                $this->request->set_url_params( array(
    404419                        'someinteger' => '123',