![Announcement icon Announcement icon](https://www.drupal.org/files/styles/grid-2-2x-square/public/announcements/drupal-evergreen-logo-280X280px%20%281%29_0.jpg?itok=PHpn6rCb)
When a new user is being created, if the $array passed to user_save() contains an integer key, it will cause a SQL error in the default: case on line 334 in user.module before the user is inserted into the database.
user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO users (name, mail, 0, pass, init, status, created) VALUES ('test_user','test@domain.com'
(user.module on line 342)
INSERT INTO users (name, mail, 0, pass, init, status, created) VALUES ('test_user','test@domain.com','9f0e992cd30cc4c71f5834fba455c33','da4166dc50dd7e48390bfdede578eeaa','test@domain.com',1,13511719442)
This is because the default case contains the following conditional, which is used to determine whether insert the array's $key=>value combination into the SQL statement (which inserts into the user table.)
if (substr($key, 0, 4) !== 'auth' && in_array($key, $user_fields)) {
$user_fields is an array with values matching all of the column names in the user table. This means it usually has integers of 0-11 or so as array keys, which will cause any integer values in the user $array to be matched and then added to the user INSERT SQL statement.
I fixed this bug by changing in_array() to array_search(), so that only the values in $user_fields would be compared against the keys in $array.
However, there is yet another issue in the specific case that the integer '0' shows up as a $key in the user $array. When a '0' integer value is passed to a PHP switch() statement, all string case statements are type-casted to integers when compared with the zero. Type-casting a string to an integer results in a value of 0 (if the string is not composed of integer characters.)
An example:
$value = 0;
switch($value) {
case 'dog':
print $value . ' is a dog.';
}
// "0 is a dog" is printed
To solve this, I had the foreach() loop on line 319 skip over the array key if it is an integer value.
See the attached image for an xdebug snapshot of the code in question (some fields have been blanked out, but they were all normal string values.)
Patch pending in next comment.
Comment | File | Size | Author |
---|---|---|---|
#2 | user-user_save_int_keys_crash-1841256-2.patch | 1.08 KB | Quest Yarbrough |
usermodule_inarray_intkey_bug.png | 138.79 KB | Quest Yarbrough |
![Acquia logo](/files/ads/acquia-issue-sponsorship.png)
Comments
Comment #1
Quest Yarbrough CreditAttribution: Quest Yarbrough commentedPatch attached to next comment.
Comment #2
Quest Yarbrough CreditAttribution: Quest Yarbrough commentedPatch attached to this comment.