From 5c6cc0f6ce81fe0574b004bf202f95a462c56523 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers Date: Mon, 17 Dec 2018 18:38:13 +0000 Subject: [PATCH] WPDB: Check that `$wpdb->last_result` is countable before counting with it. `wpdb::get_col()` iterates over `$wpdb->last_result`, which can be a non-countable value, should the preceding query have failed. Props spacedmonkey, desrosj, pento. Merges [43934] into trunk. See #45299. git-svn-id: https://develop.svn.wordpress.org/trunk@44272 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/wp-db.php | 18 +++++--- tests/phpunit/tests/db.php | 90 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 7 deletions(-) diff --git a/src/wp-includes/wp-db.php b/src/wp-includes/wp-db.php index ae08158f64..af42aaf841 100644 --- a/src/wp-includes/wp-db.php +++ b/src/wp-includes/wp-db.php @@ -2544,8 +2544,10 @@ class wpdb { $new_array = array(); // Extract the column values - for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) { - $new_array[ $i ] = $this->get_var( null, $x, $i ); + if ( $this->last_result ) { + for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) { + $new_array[ $i ] = $this->get_var( null, $x, $i ); + } } return $new_array; } @@ -2585,11 +2587,13 @@ class wpdb { } elseif ( $output == OBJECT_K ) { // Return an array of row objects with keys from column 1 // (Duplicates are discarded) - foreach ( $this->last_result as $row ) { - $var_by_ref = get_object_vars( $row ); - $key = array_shift( $var_by_ref ); - if ( ! isset( $new_array[ $key ] ) ) { - $new_array[ $key ] = $row; + if ( $this->last_result ) { + foreach ( $this->last_result as $row ) { + $var_by_ref = get_object_vars( $row ); + $key = array_shift( $var_by_ref ); + if ( ! isset( $new_array[ $key ] ) ) { + $new_array[ $key ] = $row; + } } } return $new_array; diff --git a/tests/phpunit/tests/db.php b/tests/phpunit/tests/db.php index 2fe9df1d47..dbe70b8a6e 100644 --- a/tests/phpunit/tests/db.php +++ b/tests/phpunit/tests/db.php @@ -570,6 +570,96 @@ class Tests_DB extends WP_UnitTestCase { $this->assertEquals( 'Walter Sobchak', $row->display_name ); } + /** + * Test the `get_col()` method. + * + * @param string|null $query The query to run. + * @param string|array $expected The expected resulting value. + * @param arrray|string|null $last_result The value to assign to `$wpdb->last_result`. + * @param int|string $column The column index to retrieve. + * + * @dataProvider data_test_get_col + * + * @ticket 45299 + */ + function test_get_col( $query, $expected, $last_result, $column ) { + global $wpdb; + + $wpdb->last_result = $last_result; + + $result = $wpdb->get_col( $query, $column ); + + if ( $query ) { + $this->assertSame( $query, $wpdb->last_query ); + } + + if ( is_array( $expected ) ) { + $this->assertSame( $expected, $result ); + } else { + $this->assertContains( $expected, $result ); + } + } + + /** + * Data provider for testing `get_col()`. + * + * @return array { + * Arguments for testing `get_col()`. + * + * @type string|null $query The query to run. + * @type string|array $expected The resulting expected value. + * @type arrray|string|null $last_result The value to assign to `$wpdb->last_result`. + * @type int|string $column The column index to retrieve. + */ + function data_test_get_col() { + global $wpdb; + + return array( + array( + "SELECT display_name FROM $wpdb->users", + 'admin', + array(), + 0, + ), + array( + "SELECT user_login, user_email FROM $wpdb->users", + 'admin', + array(), + 0, + ), + array( + "SELECT user_login, user_email FROM $wpdb->users", + 'admin@example.org', + array(), + 1, + ), + array( + "SELECT user_login, user_email FROM $wpdb->users", + 'admin@example.org', + array(), + '1', + ), + array( + "SELECT user_login, user_email FROM $wpdb->users", + array( null ), + array(), + 3, + ), + array( + '', + array(), + null, + 0, + ), + array( + null, + array(), + '', + 0, + ), + ); + } + function test_replace() { global $wpdb; $rows1 = $wpdb->insert( $wpdb->users, array( 'display_name' => 'Walter Sobchak' ) );