From b4a6de999728c0dfa66e4bc9abf2983d5b385c8f Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Mon, 2 Oct 2017 02:10:14 +0000 Subject: [PATCH] Database: Throw a notice if `wpdb::prepare()` is called with an incorrect number of arguments `wpdb::prepare()` currently gives no information if the number of arguments passed doesn't match the number of placeholders in the query. This change gives an explicit notice that the call was incorrect. Also fixes an enrelated term meta test that was triggering this new notice. Props thekt12 for the initial patch. Fixes #42040. git-svn-id: https://develop.svn.wordpress.org/trunk@41662 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/wp-db.php | 17 ++++++- tests/phpunit/tests/db.php | 73 +++++++++++++++++++++++++++++-- tests/phpunit/tests/term/meta.php | 2 +- 3 files changed, 86 insertions(+), 6 deletions(-) diff --git a/src/wp-includes/wp-db.php b/src/wp-includes/wp-db.php index 5ed0673bee..76b6574453 100644 --- a/src/wp-includes/wp-db.php +++ b/src/wp-includes/wp-db.php @@ -1251,7 +1251,20 @@ class wpdb { $query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting $query = preg_replace( '|(?check_current_query = false; return $this->query( $this->prepare( $sql, $values ) ); } diff --git a/tests/phpunit/tests/db.php b/tests/phpunit/tests/db.php index 01dd3688d3..208c70ed5b 100644 --- a/tests/phpunit/tests/db.php +++ b/tests/phpunit/tests/db.php @@ -375,8 +375,8 @@ class Tests_DB extends WP_UnitTestCase { $this->assertEquals( "SELECT * FROM $wpdb->users WHERE id = 0 AND user_login = 'admin'", $prepared ); } - function test_prepare_vsprintf() { - global $wpdb; + function test_prepare_vsprintf() { + global $wpdb; $prepared = $wpdb->prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s", array( 1, "admin" ) ); $this->assertEquals( "SELECT * FROM $wpdb->users WHERE id = 1 AND user_login = 'admin'", $prepared ); @@ -393,7 +393,74 @@ class Tests_DB extends WP_UnitTestCase { $prepared = @$wpdb->prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s", array( array( 1 ), "admin" ) ); $this->assertEquals( "SELECT * FROM $wpdb->users WHERE id = 0 AND user_login = 'admin'", $prepared ); - } + } + + /** + * @ticket 42040 + * @dataProvider data_prepare_incorrect_arg_count + * @expectedIncorrectUsage wpdb::prepare + */ + public function test_prepare_incorrect_arg_count( $query, $args, $expected ) { + global $wpdb; + + // $query is the first argument to be passed to wpdb::prepare() + array_unshift( $args, $query ); + + $prepared = @call_user_func_array( array( $wpdb, 'prepare' ), $args ); + $this->assertEquals( $expected, $prepared ); + } + + public function data_prepare_incorrect_arg_count() { + global $wpdb; + + return array( + array( + "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s", // Query + array( 1, "admin", "extra-arg" ), // ::prepare() args, to be passed via call_user_func_array + "SELECT * FROM $wpdb->users WHERE id = 1 AND user_login = 'admin'", // Expected output + ), + array( + "SELECT * FROM $wpdb->users WHERE id = %%%d AND user_login = %s", + array( 1 ), + false, + ), + array( + "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s", + array( array( 1, "admin", "extra-arg" ) ), + "SELECT * FROM $wpdb->users WHERE id = 1 AND user_login = 'admin'", + ), + array( + "SELECT * FROM $wpdb->users WHERE id = %d AND %% AND user_login = %s", + array( 1, "admin", "extra-arg" ), + "SELECT * FROM $wpdb->users WHERE id = 1 AND % AND user_login = 'admin'", + ), + array( + "SELECT * FROM $wpdb->users WHERE id = %%%d AND %F AND %f AND user_login = %s", + array( 1, 2.3, "4.5", "admin", "extra-arg" ), + "SELECT * FROM $wpdb->users WHERE id = %1 AND 2.300000 AND 4.500000 AND user_login = 'admin'", + ), + array( + "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s", + array( array( 1 ), "admin", "extra-arg" ), + "SELECT * FROM $wpdb->users WHERE id = 0 AND user_login = 'admin'", + ), + array( + "SELECT * FROM $wpdb->users WHERE id = %d and user_nicename = %s and user_status = %d and user_login = %s", + array( 1, "admin", 0 ), + '', + ), + array( + "SELECT * FROM $wpdb->users WHERE id = %d and user_nicename = %s and user_status = %d and user_login = %s", + array( array( 1, "admin", 0 ) ), + '', + ), + array( + "SELECT * FROM $wpdb->users WHERE id = %d and %% and user_login = %s and user_status = %d and user_login = %s", + array( 1, "admin", "extra-arg" ), + '', + ), + ); + } function test_db_version() { global $wpdb; diff --git a/tests/phpunit/tests/term/meta.php b/tests/phpunit/tests/term/meta.php index 0676c82bc0..e3410d57aa 100644 --- a/tests/phpunit/tests/term/meta.php +++ b/tests/phpunit/tests/term/meta.php @@ -358,7 +358,7 @@ class Tests_Term_Meta extends WP_UnitTestCase { register_taxonomy( 'wptests_tax', 'post' ); $t1 = wp_insert_term( 'Foo', 'wptests_tax' ); - add_term_meta( $t1, 'foo', 'bar' ); + add_term_meta( $t1['term_id'], 'foo', 'bar' ); register_taxonomy( 'wptests_tax_2', 'post' ); register_taxonomy( 'wptests_tax_3', 'post' );