Make WordPress Core

Changeset 29797


Ignore:
Timestamp:
09/30/2014 02:03:49 PM (12 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.