WordPress.org

Make WordPress Core

Opened 5 years ago

Closed 5 years ago

#7928 closed defect (bug) (invalid)

WP fails if object data is stored in the usermeta table

Reported by: markedwards Owned by:
Milestone: Priority: high
Severity: normal Version: 2.6.1
Component: Administration Keywords: reporter-feedback needs-patch
Focuses: Cc:

Description

Tested on WP 2.6.2:

When adding custom fields to a user profile page via a plugin, the plugiin cannot store the data as an object in the usermeta table.

The first time a profile is updated all goes well because the plugin's object data is not in the database yet when WP loads all the user's data during an update. But, after updating the profile the first time WP then fails to during the update process on subsequent profile update attempts. The reason is that before WP calls any actions attached to the profile page via plugin WP first loads all the user data from the usermeta table. That includes any data stored by plugins for the given user. After loading the data WP then tries to either add magic quotes or add slashes to the data in the add_magic_quotes function in wp-includes/functions.php as seen below:

function add_magic_quotes( $array ) {

global $wpdb;
foreach ( $array as $k => $v ) {

if ( is_array( $v ) ) {

$array[$k] = add_magic_quotes( $v );

} else {

$array[$k] = $wpdb->escape( $v );

}

}
return $array;

}

The function is missing a vital check for objects [ which of course cannot be passed into addslashes via $wpdb->escape() ] oand therefore that function always causes an error in PHP if a plugin has stored user data as an object in the usermeta table. The corrected function is seen below, which works fine and allows plugins to attach object data to a profile and store the object in the usermeta table.

function add_magic_quotes( $array ) {

global $wpdb;
foreach ( $array as $k => $v ) {

if (is_object($v)) return $array;
if ( is_array( $v ) ) {

$array[$k] = add_magic_quotes( $v );

} else {

$array[$k] = $wpdb->escape( $v );

}

}
return $array;

}

Please fix this in the next version of WP. The code below will probably demonstrate the problem. Make it a plugin, activate it, then update the user profile at least twice and WP should fail.

<?php

class myclass() {

var $a;
var $b;
var $c;

}

function so_update_usermeta() {

$d = get_usermeta(1,'so_user_data');
if (!$d) $d = new myclass();
$d->a = 1;
$d->b = 1;
$d->c = 1;
update_usermeta(1,$d);

}

add_action('profile_update','so_update_usermeta');

?>

This bug hampers plugin development since developers have to use strings or arrays, which leads to more code and processing overhead... one line of code fixes that problem and saves countless CPU cycles.

Change History (8)

comment:1 jacobsantos5 years ago

What revision are you using?

comment:2 jacobsantos5 years ago

  • Keywords reporter-feedback added; profiles users edit removed

This is incorrect:

function so_update_usermeta() {

    $d = get_usermeta(1,'so_user_data');

    if (!$d)
        $d = new myclass();
        $d->a = 1;
        $d->b = 1;
        $d->c = 1;

        update_usermeta(1, $d);

}

update_usermeta(1, $d); should be update_usermeta(1, 'so_user_data', $d);.

comment:3 jacobsantos5 years ago

  • Milestone changed from 2.7 to 2.8

Okay, you said this is tested on 2.6.2, but you need to try it on Trunk to reproduce.

There are also multiple issues with the ticket. The code in trunk appears to be fine from a single look over.

  1. Your example plugin code is incorrect.
  2. The cause is incorrect and has nothing to do with the user meta data code.

comment:4 markedwards5 years ago

Right about update_usermeta - sorry about that. It was late.

Anyway, I found a workaround. I add a function to the class and now it works. But, really, WP should handle this check for plugin devs since some might not be able to find out how to work around it. Here's the new class that works without a WP fix:

!#php
class myclass() {

    var $a; 
    var $b; 
    var $c;

    public function __toString() {
         return serialize($this);
    }
}

That function works with no need to call it directly anywhere in the code - it's handled automagically by little green PHP goblins drinking beer in the remote recesses of the CPU - Lol

comment:5 DD325 years ago

That function works with no need to call it directly anywhere in the code - it's handled automagically by little green PHP goblins drinking beer in the remote recesses of the CPU - Lol

Well, At least when running with PHP 5.2.x

It is worth noting that before PHP 5.2.0 the __toString method was only called when it was directly combined with echo() or print(). PHP5 Magic methods

comment:6 jacobsantos5 years ago

So you are saying the workaround is for 2.6.2 or for trunk? I think you should try trunk.

comment:7 jacobsantos5 years ago

  • Keywords needs-patch added

comment:8 Denis-de-Bernardy5 years ago

  • Milestone 2.8 deleted
  • Resolution set to invalid
  • Status changed from new to closed

storing objects in those tables (options, post meta, or user meta) is not safe no matter what.

the objects do not get initialized when recreated, and there are all sorts of problems related to them getting stored. sleep() and wakeup() are additionally not supported in php4.

please use the relevant php5 functions in your class, and mark it as requiring php 5, or whatever the version it was that they were introduced in.

Note: See TracTickets for help on using tickets.