Mantis Bugtracker
  

Viewing Issue Simple Details Jump to Notes ] View Advanced ] Issue History ] Print ]
ID Category Severity Reproducibility Date Submitted Last Update
0003249 [Quercus] major always 01-14-09 01:11 01-14-09 23:49
Reporter haplo View Status public  
Assigned To
Priority normal Resolution open  
Status new   Product Version
Summary 0003249: Serializable not supported
Description If an php class implements Serializable the serialization of an instance should be delegated to the instances serialize function. This does not happend.

Here is a test:

class foo implements Serializable {

    public $bar = "foobar";

    public function unserialize($serialized){
        echo "unserialize
\n";

        $array = unserialize($serialized);

        foreach ($array as $name => $values) {
            $this->$name = "unserialized " .$values;
        }
    }

    public function serialize(){
        echo "serialize
\n";
        return serialize(get_object_vars($this));
    }
}

$foo = new foo();

$data = serialize($foo);

echo $data;

$foo2 = unserialize($data);

echo $foo2->bar;



Quercus result:
O:3:"foo":1:{s:3:"bar";s:6:"foobar";}foobar


Apache result:
serialize
C:3:"foo":29:{a:1:{s:3:"bar";s:6:"foobar";}}unserialize
unserialized foobar
Additional Information
Attached Files

- Relationships

- Notes
(0003733)
haplo
01-14-09 23:49

Hi,

i have a fix for this Bug:

1. Replaced the serialize method in ObjectExtValue by this method.

    public void serialize(Env env,
                          StringBuilder sb, SerializeMap serializeMap) {
        Integer index = serializeMap.get(this);

        if (index != null) {
            sb.append("r:");
            sb.append(index);
            sb.append(";");

            return;
        }

        serializeMap.put(this);
        serializeMap.incrementIndex();

        if (! this.isA("Serializable")) {
            sb.append("O:");
        }else {
            sb.append("C:");
        }
        sb.append(_className.length());
        sb.append(":\"");
        sb.append(_className);
        sb.append("\":");

        if (! this.isA("Serializable")) {
            sb.append(getSize());
            sb.append(":{");

            Iterator<Entry> iter = new EntryIterator(_entries);

            while (iter.hasNext()) {
                Entry entry = iter.next();

                sb.append("s:");

                Value key = entry.getKey();
                int len = key.length();

                if (entry._visibility == FieldVisibility.PROTECTED) {
                    sb.append(len + 3);

                    sb.append(":\"");
                    sb.append("\u0000*\u0000");
                } else if (entry._visibility == FieldVisibility.PRIVATE) {
                    sb.append(len + 3);

                    sb.append(":\"");
                    sb.append("\u0000A\u0000");
                } else {
                    sb.append(len);

                    sb.append(":\"");
                }

                sb.append(key);
                sb.append("\";");

                Value value = ((Entry) entry).getRawValue();

                value.serialize(env, sb, serializeMap);
            }
        } else { // ok .. this object implements Serializable
            AbstractFunction fun = this._methodMap.get("serialize");
            if(fun == null){
                throw new RuntimeException("Serialize objects must implement serialize function");
            }
            StringValue result = (StringValue) this.callClassMethod(env, fun, new Value[0]);
            sb.append(result.length());
            sb.append(":{");
            sb.append(result);
        }
        sb.append("}");
    }


2. I extended the switch statement in UnserializeReader.unserialize with this case:

            case 'C': {
                expect(':');
                int len = (int) readInt();
                expect(':');
                expect('"');

                String className = readString(len);

                expect('"');
                expect(':');
                int count = (int) readInt();
                expect(':');
                expect('{');

                QuercusClass qClass = env.findClass(className);
                Value obj;

                if (qClass != null)
                    obj = qClass.createObject(env);
                else {
                    log.fine(L.l("{0} is an undefined class in unserialize",
                            className));

                    obj = env.createIncompleteObject(className);
                }

                Value ref = null;

                if (_useReference)
                    ref = createReference(obj);

                Value serialized = readStringValue(env, count);
                AbstractFunction unserialize = obj.findFunction("unserialize");
                if (unserialize == null) {
                    throw new RuntimeException("Class "+className+" has no unserializer");
                }
                obj.callClassMethod(env, unserialize, new Value[]{serialized});

                expect('}');

                if (ref != null)
                    return ref;
                else
                    return obj;
            }


In case the value implements the Serializable interface the type indentifier is is 'C' instead of 'O'
 

- Issue History
Date Modified Username Field Change
01-14-09 01:11 haplo New Issue
01-14-09 23:49 haplo Note Added: 0003733
05-02-10 03:17 sblommers Issue Monitored: sblommers


Mantis 1.0.0rc3[^]
Copyright © 2000 - 2005 Mantis Group
30 total queries executed.
26 unique queries executed.
Powered by Mantis Bugtracker