Issue1768990

classification
Title: pickle fails on subclasses of builtin types
Type: Severity: normal
Components: Core Versions:
Milestone:
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: cgroves, mehendran, pjenvey
Priority: normal Keywords:

Created on 2007-08-07.05:43:05 by cgroves, last changed 2007-09-22.06:35:29 by pjenvey.

Messages
msg1828 (view) Author: Charlie Groves (cgroves) Date: 2007-08-07.05:43:05
pickle blows up with a StackOverflow when picking a subclass of a builtin like int or str.  This is tested by test_subclass, but that test is commented out for now as explained in http://wiki.python.org/jython/JythonDeveloperGuide/VersionTransitionTestExclusions
msg1829 (view) Author: Mehendran (mehendran) Date: 2007-08-13.13:47:14
Code snippet:
-------------
class mystr(str):
    def __init__(self, x):
        self.str = str(x)
a = mystr('x')
b = str(a) # This doesn't work

In this code, I am not able to pass the 'a' value to 'str' type.
It throws stack overflow error. The bug is not in the pickle module, 
but is only in this line. I am trying to figure out. 
msg1830 (view) Author: Mehendran (mehendran) Date: 2007-08-14.14:18:37
Patch is added with the patch number: [1773865]

Problem:
========

PyString.java
-------------
final static PyObject str_new(PyNewWrapper new_, boolean init, PyType subtype,
            PyObject[] args, String[] keywords) {
        ArgParser ap = new ArgParser("str", args, keywords, new String[] { "object" }, 0);
        PyObject S = ap.getPyObject(0, null);
        if(new_.for_type == subtype) {
            if(S == null) {
                return new PyString("");
            }
            return S.__str__();
---
---
---
}

Here S is an arg of type PyStringDerived. When you call S.__str__(),
it is returning a string of type PyStringDerived with the contents of arg.
But this leads to making calls to __init__ of mystr class as in the 
following.

PyType.java
------------
private static PyObject invoke_new_(PyObject new_,PyType type .....{
...
        newobj.dispatch__init__(type,args,keywords);
        return newobj;
    }

Here newobj is nothing but an obj of type PyStringDerived. This causes 
the invocation of the following code.

PyStringDerived.java
---------------------
public void dispatch__init__(PyType type,PyObject[]args,String[]keywords) {
        PyType self_type=getType();
        if (self_type.isSubType(type)) {
            PyObject impl=self_type.lookup("__init__");
            <<<  call to __init__ of mystr >>>
}}

So here, the constructor is called recursively and it causes stackoverflow.

Solution:
=========

PyString.java
-------------
final static PyObject str_new(PyNewWrapper new_, boolean init, PyType subtype,
            PyObject[] args, String[] keywords) {
---
            return new PyString(S.__str__().toString()); //CHANGE
---
}
msg1831 (view) Author: Philip Jenvey (pjenvey) Date: 2007-09-22.06:35:29
fixed in r3498/3499. thanks mehendran!
History
Date User Action Args
2007-08-07 05:43:05cgrovescreate