WordPress.org

Make WordPress Core

Opened 7 years ago

Closed 3 years ago

#16731 closed defect (bug) (fixed)

Unchecked array_merge() returns NULL in wp_update_user();

Reported by: milan.chotai Owned by:
Milestone: 3.5.1 Priority: normal
Severity: normal Version: 3.1
Component: Users Keywords: has-patch
Focuses: Cc:

Description

I am running PHP version 5.3.3-1ubuntu9.3 and encountered a bug in a simple plug-in I wrote that worked up to Wordpress v3.0.5 but not in 3.1. It uses wp_update_user(), which is causing the issue. I traced the bug to line 1563 of wp-includes/user.php:

$userdata = array_merge($user, $userdata);

If $user is NULL, then array_merge returns NULL, making $userdata useless to other functions that follow like wp_insert_user().

Attachments (3)

user.php.diff (624 bytes) - added by adambackstrom 7 years ago.
Ensure $user is an array
16731.diff (1.4 KB) - added by garyc40 7 years ago.
properly account for empty ID in $userdata
16731.2.diff (1.6 KB) - added by garyc40 7 years ago.
also return a WP_Error object if an invalid user ID is passed

Download all attachments as: .zip

Change History (17)

#1 follow-up: @nacin
7 years ago

  • Keywords 2nd-opinion reporter-feedback added; needs-patch needs-testing removed

I don't see how $user would be null. wp_update_user() should only be fired on existing users.

If $userdata['ID'] isn't set or if get_userdata() on that ID fails, then ideally wp_update_user() should fail.

Also, get_userdata() fails with false, not null (but the same symptoms would occur with the array_merge()).

#2 in reply to: ↑ 1 @adambackstrom
7 years ago

Replying to nacin:

I don't see how $user would be null. wp_update_user() should only be fired on existing users.

From the function docblock: "If $userdata does not contain an 'ID' key, then a new user will be created and the new user's ID will be returned." So, we should be able to call wp_update_user() regardless of whether we mean "update" or "create." Just like milan.chotai, I have code that does this for convenience.

#3 @adambackstrom
7 years ago

Here's some code that generates these errors:

function test_wp_update_user() {
	$userdata = array(
		'user_login' => 'user' . md5( microtime(true) ),                            
		'user_pass' => 'foo',
	);

	var_dump( wp_update_user( $userdata ) );                                        
}

And the output:

Notice: Undefined index: ID in /web/wp-trunk/wp-includes/user.php on line 1546

Warning: get_object_vars() expects parameter 1 to be object, boolean given in /web/wp-trunk/wp-includes/user.php on line 1552

Warning: array_merge(): Argument #1 is not an array in /web/wp-trunk/wp-includes/user.php on line 1563

Warning: extract() expects parameter 1 to be array, null given in /web/wp-trunk/wp-includes/user.php on line 1385

Notice: Undefined variable: user_pass in /web/wp-trunk/wp-includes/user.php on line 1395

Notice: Undefined variable: user_login in /web/wp-trunk/wp-includes/user.php on line 1398
object(WP_Error)#184 (2) {
  ["errors"]=>
  array(1) {
    ["empty_user_login"]=>
    array(1) {
      [0]=>
      string(46) "Cannot create a user with an empty login name."
    }
  }
  ["error_data"]=>
  array(0) {
  }
}

@adambackstrom
7 years ago

Ensure $user is an array

#4 @adambackstrom
7 years ago

  • Cc adambackstrom added

@garyc40
7 years ago

properly account for empty ID in $userdata

#5 @garyc40
7 years ago

  • Keywords has-patch added; 2nd-opinion reporter-feedback removed

adambackstrom's patch still doesn't account for empty $user_data['ID'], some notices are still there. Another patch attached that addresses this.

And yes, the docblock does indeed mention that if an ID key is not specified, a new user would be created.

@garyc40
7 years ago

also return a WP_Error object if an invalid user ID is passed

#6 @karacsi_maci
5 years ago

  • Cc karacsi_maci added

This problem still not solved (after 21 month?)

$userdata = array(
		'ID' => get_current_user_id(),
		'first_name' => $this->postVars['firstName'],
		'last_name' => $this->postVars['lastName']);
	    if (!empty($this->postVars['pass'])) {
		$userdata['user_pass'] = $this->postVars['pass'];
	    }
	    wp_update_user($userdata);

(The $this->postVars exactly the same as $_POST, don't care about it).

If you just comment out the ID line, you will get the get_object_vars error.

So codex lies:
"If $userdata does not contain an 'ID' key, then a new user will be created and the new user's ID will be returned."

(There are first name and last name in my array). So you should rewrite the codex, to tell to users that, they SHOULD use a loginname at least.

#7 @SergeyBiryukov
5 years ago

#17009 was marked as a duplicate.

#8 @helen
5 years ago

#17009 was marked as a duplicate.

#9 @cartpauj
5 years ago

Posting here since #17009 was closed again. Thanks.

http://core.trac.wordpress.org/browser/tags/3.5.1/wp-includes/user.php#L1455 That line is throwing an Exception, which prevents wp_insert_user from ever being called. The function description clearly states it will insert a new user if ID is not set.

So I propose that either wp_insert_user get stripped completely out of wp_update_user or wp_update_user needs fixed to allow wp_insert_user to actually get used before the Exception is thrown.

#10 @SergeyBiryukov
5 years ago

  • Milestone changed from Awaiting Review to 3.6

#11 @ryan
4 years ago

  • Milestone changed from 3.6 to Future Release

#12 @nacin
4 years ago

In 24345:

Remove docs suggesting that wp_update_user() creates a user if no ID is provided. See #16731, that is incorrect at this time.

#14 @SergeyBiryukov
3 years ago

  • Milestone changed from Future Release to 3.5.1
  • Resolution set to fixed
  • Status changed from new to closed

Fixed in [23210].

Note: See TracTickets for help on using tickets.