WordPress.org

Make WordPress Core

Ticket #34659: 34659.2.diff

File 34659.2.diff, 4.4 KB (added by danielbachhuber, 4 years ago)

Whitelist specific validation and sanitization functions to only receive one argument

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

    diff --git src/wp-includes/rest-api/class-wp-rest-request.php src/wp-includes/rest-api/class-wp-rest-request.php
    index dee352c..550ca2e 100644
    class WP_REST_Request implements ArrayAccess { 
    794794                        foreach ( $this->params[ $type ] as $key => $value ) {
    795795                                // Check if this param has a sanitize_callback added.
    796796                                if ( isset( $attributes['args'][ $key ] ) && ! empty( $attributes['args'][ $key ]['sanitize_callback'] ) ) {
    797                                         $this->params[ $type ][ $key ] = call_user_func( $attributes['args'][ $key ]['sanitize_callback'], $value, $this, $key );
     797                                        /**
     798                                         * Filter sanitization callbacks which should only be supplied one argument
     799                                         *
     800                                         * Some functions used as sanitization callbacks (e.g. is_numeric()), throw
     801                                         * errors when supplied more than one argument.
     802                                         *
     803                                         * @since 4.4.0
     804                                         *
     805                                         * @param array    $single_argument_callbacks
     806                                         */
     807                                        $single_argument_callbacks = apply_filters( 'rest_request_sanitize_callbacks_single_argument', array( 'intval', 'sanitize_title' ) );
     808                                        if ( in_array( $attributes['args'][ $key ]['sanitize_callback'], $single_argument_callbacks ) ) {
     809                                                $this->params[ $type ][ $key ] = call_user_func( $attributes['args'][ $key ]['sanitize_callback'], $value );
     810                                        } else {
     811                                                $this->params[ $type ][ $key ] = call_user_func( $attributes['args'][ $key ]['sanitize_callback'], $value, $this, $key );
     812                                        }
    798813                                }
    799814                        }
    800815                }
    class WP_REST_Request implements ArrayAccess { 
    844859                        $param = $this->get_param( $key );
    845860
    846861                        if ( null !== $param && ! empty( $arg['validate_callback'] ) ) {
    847                                 $valid_check = call_user_func( $arg['validate_callback'], $param, $this, $key );
     862
     863                                /**
     864                                 * Filter validation callbacks which should only be supplied one argument
     865                                 *
     866                                 * Some functions used as validation callbacks (e.g. is_numeric()), throw
     867                                 * errors when supplied more than one argument.
     868                                 *
     869                                 * @since 4.4.0
     870                                 *
     871                                 * @param array    $single_argument_callbacks
     872                                 */
     873                                $single_argument_callbacks = apply_filters( 'rest_request_validate_callbacks_single_argument', array( 'is_numeric' ) );
     874                                if ( in_array( $arg['validate_callback'], $single_argument_callbacks ) ) {
     875                                        $valid_check = call_user_func( $arg['validate_callback'], $param );
     876                                } else {
     877                                        $valid_check = call_user_func( $arg['validate_callback'], $param, $this, $key );
     878                                }
    848879
    849880                                if ( false === $valid_check ) {
    850881                                        $invalid_params[ $key ] = __( 'Invalid param.' );
  • tests/phpunit/tests/rest-api/rest-request.php

    diff --git tests/phpunit/tests/rest-api/rest-request.php tests/phpunit/tests/rest-api/rest-request.php
    index ba40892..e853bec 100644
    class Tests_REST_Request extends WP_UnitTestCase { 
    307307                $this->assertEquals( 0, $this->request->get_param( 'somestring' ) );
    308308        }
    309309
     310        public function test_sanitize_callback_only_pass_value() {
     311                $this->request->set_url_params( array(
     312                        'foo'          => '3',
     313                        ) );
     314                $this->request->set_attributes( array(
     315                        'args' => array(
     316                                'foo' => array(
     317                                        'sanitize_callback' => 'intval',
     318                                ),
     319                        ),
     320                ));
     321
     322                $this->request->sanitize_params();
     323                $this->assertEquals( 3, $this->request->get_param( 'foo' ) );
     324
     325        }
     326
    310327        public function test_has_valid_params_required_flag() {
    311328                $this->request->set_attributes( array(
    312329                        'args' => array(
    class Tests_REST_Request extends WP_UnitTestCase { 
    391408                $this->assertArrayHasKey( 'someinteger', $data['params'] );
    392409                $this->assertArrayHasKey( 'someotherinteger', $data['params'] );
    393410        }
     411
     412        public function test_validate_callback_only_pass_value() {
     413                $this->request->set_url_params( array(
     414                        'numeric_value'         => '123',
     415                        'non_numeric_value'     => 'foo-bar',
     416                        ) );
     417                $this->request->set_attributes( array(
     418                        'args' => array(
     419                                'numeric_value' => array(
     420                                        'validate_callback' => 'is_numeric',
     421                                ),
     422                                'non_numeric_value' => array(
     423                                        'validate_callback' => 'is_numeric',
     424                                ),
     425                        ),
     426                ));
     427
     428                $valid = $this->request->has_valid_params();
     429
     430                $this->assertWPError( $valid );
     431                $this->assertEquals( 'rest_invalid_param', $valid->get_error_code() );
     432                $data = $valid->get_error_data( 'rest_invalid_param' );
     433                $this->assertArrayHasKey( 'non_numeric_value', $data['params'] );
     434                $this->assertFalse( array_key_exists( 'numeric_value', $data ) );
     435
     436        }
     437
    394438}