Skip to content

Commit a577ca8

Browse files
committed
Database: Hardening for wpdb::prepare()
Previously if you passed an array of values for placeholders, additional values could be passed as well. Now additional values will be ignored. Merges [41470] to 4.4 branch. git-svn-id: https://develop.svn.wordpress.org/branches/4.4@41475 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 16be4ff commit a577ca8

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/wp-includes/wp-db.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1254,9 +1254,18 @@ public function prepare( $query, $args ) {
12541254

12551255
$args = func_get_args();
12561256
array_shift( $args );
1257+
12571258
// If args were passed as an array (as in vsprintf), move them up
1258-
if ( isset( $args[0] ) && is_array($args[0]) )
1259+
if ( is_array( $args[0] ) && count( $args ) == 1 ) {
12591260
$args = $args[0];
1261+
}
1262+
1263+
foreach ( $args as $arg ) {
1264+
if ( ! is_scalar( $arg ) ) {
1265+
_doing_it_wrong( 'wpdb::prepare', sprintf( 'Unsupported value type (%s).', gettype( $arg ) ), '4.4.11' );
1266+
}
1267+
}
1268+
12601269
$query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it
12611270
$query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting
12621271
$query = preg_replace( '|(?<!%)%f|' , '%F', $query ); // Force floats to be locale unaware

tests/phpunit/tests/db.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,46 @@ function test_prepare_without_arguments() {
353353
$this->assertEquals( "SELECT * FROM $wpdb->users WHERE id = 0", $prepared );
354354
}
355355

356+
function test_prepare_sprintf() {
357+
global $wpdb;
358+
359+
$prepared = $wpdb->prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s", 1, "admin" );
360+
$this->assertEquals( "SELECT * FROM $wpdb->users WHERE id = 1 AND user_login = 'admin'", $prepared );
361+
}
362+
363+
/**
364+
* @expectedIncorrectUsage wpdb::prepare
365+
*/
366+
function test_prepare_sprintf_invalid_args() {
367+
global $wpdb;
368+
369+
$prepared = @$wpdb->prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s", 1, array( "admin" ) );
370+
$this->assertEquals( "SELECT * FROM $wpdb->users WHERE id = 1 AND user_login = ''", $prepared );
371+
372+
$prepared = @$wpdb->prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s", array( 1 ), "admin" );
373+
$this->assertEquals( "SELECT * FROM $wpdb->users WHERE id = 0 AND user_login = 'admin'", $prepared );
374+
}
375+
376+
function test_prepare_vsprintf() {
377+
global $wpdb;
378+
379+
$prepared = $wpdb->prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s", array( 1, "admin" ) );
380+
$this->assertEquals( "SELECT * FROM $wpdb->users WHERE id = 1 AND user_login = 'admin'", $prepared );
381+
}
382+
383+
/**
384+
* @expectedIncorrectUsage wpdb::prepare
385+
*/
386+
function test_prepare_vsprintf_invalid_args() {
387+
global $wpdb;
388+
389+
$prepared = @$wpdb->prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s", array( 1, array( "admin" ) ) );
390+
$this->assertEquals( "SELECT * FROM $wpdb->users WHERE id = 1 AND user_login = ''", $prepared );
391+
392+
$prepared = @$wpdb->prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s", array( array( 1 ), "admin" ) );
393+
$this->assertEquals( "SELECT * FROM $wpdb->users WHERE id = 0 AND user_login = 'admin'", $prepared );
394+
}
395+
356396
function test_db_version() {
357397
global $wpdb;
358398

0 commit comments

Comments
 (0)