WordPress.org

Make WordPress Core

Changeset 29797


Ignore:
Timestamp:
09/30/2014 02:03:49 PM (7 years ago)
Author:
boonebgorges
Message:

Improve parameter sanitization in WP_Date_Query::build_query().

  • Don't run non-numeric values through intval() for sanitization; this transforms them into 1s and 0s, which can cause unintended results.
  • Be more generous about numeric array keys (don't require 0 and 1) in BETWEEN and NOT BETWEEN clauses.

Fixes #29801.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/date.php

    r29479 r29797  
    314314            case 'IN':
    315315            case 'NOT IN':
    316                 return '(' . implode( ',', array_map( 'intval', (array) $value ) ) . ')';
     316                $value = (array) $value;
     317
     318                // Remove non-numeric values.
     319                $value = array_filter( $value, 'is_numeric' );
     320
     321                if ( empty( $value ) ) {
     322                    return false;
     323                }
     324
     325                return '(' . implode( ',', array_map( 'intval', $value ) ) . ')';
    317326
    318327            case 'BETWEEN':
    319328            case 'NOT BETWEEN':
    320                 if ( ! is_array( $value ) || 2 != count( $value ) || ! isset( $value[0] ) || ! isset( $value[1] ) )
     329                if ( ! is_array( $value ) || 2 != count( $value ) ) {
    321330                    $value = array( $value, $value );
     331                } else {
     332                    $value = array_values( $value );
     333                }
     334
     335                // If either value is non-numeric, bail.
     336                foreach ( $value as $v ) {
     337                    if ( ! is_numeric( $v ) ) {
     338                        return false;
     339                    }
     340                }
    322341
    323342                $value = array_map( 'intval', $value );
     
    326345
    327346            default;
     347                if ( ! is_numeric( $value ) ) {
     348                    return false;
     349                }
     350
    328351                return (int) $value;
    329352        }
  • trunk/tests/phpunit/tests/date/query.php

    r29794 r29797  
    230230    }
    231231
     232    /**
     233     * @ticket 29801
     234     */
    232235    public function test_build_value_compare_in() {
    233236        $q = new WP_Date_Query( array() );
     
    239242        // Single non-integer
    240243        $found = $q->build_value( 'IN', 'foo' );
    241         $this->assertSame( '(0)', $found );
     244        $this->assertFalse( $found );
    242245
    243246        // Array of integers
     
    247250        // Array containing non-integers
    248251        $found = $q->build_value( 'IN', array( 1, 'foo', 7 ) );
    249         $this->assertSame( '(1,0,7)', $found );
    250     }
    251 
     252        $this->assertSame( '(1,7)', $found );
     253    }
     254
     255    /**
     256     * @ticket 29801
     257     */
    252258    public function test_build_value_compare_not_in() {
    253259        $q = new WP_Date_Query( array() );
     
    259265        // Single non-integer
    260266        $found = $q->build_value( 'NOT IN', 'foo' );
    261         $this->assertSame( '(0)', $found );
     267        $this->assertFalse( $found );
    262268
    263269        // Array of integers
     
    267273        // Array containing non-integers
    268274        $found = $q->build_value( 'NOT IN', array( 1, 'foo', 7 ) );
    269         $this->assertSame( '(1,0,7)', $found );
     275        $this->assertSame( '(1,7)', $found );
    270276    }
    271277
     
    278284
    279285    /**
    280      * @todo This is a bug. Should return false when non-numeric
     286     * @ticket 29801
    281287     */
    282288    public function test_build_value_compare_between_single_non_numeric() {
     
    284290
    285291        $found = $q->build_value( 'BETWEEN', 'foo' );
    286         $this->assertSame( '0 AND 0', $found );
    287     }
    288 
    289     /**
    290      * @todo This is a bug
     292        $this->assertFalse( $found );
     293    }
     294
     295    /**
     296     * @ticket 29801
    291297     */
    292298    public function test_build_value_compare_between_array_with_other_than_two_items() {
     
    294300
    295301        $found = $q->build_value( 'BETWEEN', array( 2, 3, 4 ) );
    296 
    297         // array_map( 'intval', array(
    298         //     array( 2, 3, 4 ),
    299         //     array( 2, 3, 4 ),
    300         // ) );
    301         $this->assertSame( '1 AND 1', $found );
    302     }
    303 
    304     /**
    305      * @todo This is a bug
     302        $this->assertFalse( $found );
     303    }
     304
     305    /**
     306     * @ticket 29801
    306307     */
    307308    public function test_build_value_compare_between_incorrect_array_key() {
     
    313314        ) );
    314315
    315         // array_map( 'intval', array(
    316         //     array( 2 => 4, 3 => 5 ),
    317         //     array( 2 => 4, 3 => 5 ),
    318         // ) );
    319         $this->assertSame( '1 AND 1', $found );
    320     }
    321 
     316        $this->assertSame( '4 AND 5', $found );
     317    }
     318
     319    /**
     320     * @ticket 29801
     321     */
    322322    public function test_build_value_compare_between_array_contains_non_numeric() {
    323323        $q = new WP_Date_Query( array() );
    324324
    325325        $found = $q->build_value( 'BETWEEN', array( 2, 'foo' ) );
    326         $this->assertSame( '2 AND 0', $found );
     326        $this->assertFalse( $found );
    327327    }
    328328
     
    341341    }
    342342
     343    /**
     344     * @ticket 29801
     345     */
    343346    public function test_build_value_compare_not_between_single_non_numeric() {
    344347        $q = new WP_Date_Query( array() );
    345348
    346349        $found = $q->build_value( 'NOT BETWEEN', 'foo' );
    347         $this->assertSame( '0 AND 0', $found );
    348     }
    349 
    350     /**
    351      * @todo This is a bug
     350        $this->assertFalse( $found );
     351    }
     352
     353    /**
     354     * @ticket 29801
    352355     */
    353356    public function test_build_value_compare_not_between_array_with_other_than_two_items() {
     
    355358
    356359        $found = $q->build_value( 'NOT BETWEEN', array( 2, 3, 4 ) );
    357 
    358         // array_map( 'intval', array(
    359         //     array( 2, 3, 4 ),
    360         //     array( 2, 3, 4 ),
    361         // ) );
    362         $this->assertSame( '1 AND 1', $found );
    363     }
    364 
    365     /**
    366      * @todo This is a bug
     360        $this->assertFalse( $found );
     361    }
     362
     363    /**
     364     * @ticket 29801
    367365     */
    368366    public function test_build_value_compare_not_between_incorrect_array_key() {
     
    374372        ) );
    375373
    376         // array_map( 'intval', array(
    377         //     array( 2 => 4, 3 => 5 ),
    378         //     array( 2 => 4, 3 => 5 ),
    379         // ) );
    380         $this->assertSame( '1 AND 1', $found );
    381     }
    382 
     374        $this->assertSame( '4 AND 5', $found );
     375    }
     376
     377    /**
     378     * @ticket 29801
     379     */
    383380    public function test_build_value_compare_not_between_array_contains_non_numeric() {
    384381        $q = new WP_Date_Query( array() );
    385382
    386383        $found = $q->build_value( 'NOT BETWEEN', array( 2, 'foo' ) );
    387         $this->assertSame( '2 AND 0', $found );
     384        $this->assertFalse( $found );
    388385    }
    389386
     
    403400
    404401    /**
    405      * @todo This is probably a bug - ought to return false
     402     * @ticket 29801
    406403     */
    407404    public function test_build_value_compare_default_value_non_numeric() {
     
    409406
    410407        $found = $q->build_value( 'foo', 'foo' );
    411         $this->assertSame( 0, $found );
     408        $this->assertFalse( $found );
    412409    }
    413410
Note: See TracChangeset for help on using the changeset viewer.