-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Infinite Recursion during Unpickling a codecs Object #50644
Comments
I recently ran into an infinite recursion trying to unpickle a Here is the end of the stack trace: File "/sw/lib/python2.5/codecs.py", line 330, in __getattr__ The issue is the same under Python2.6 but the error output has changed The problem is that the codecs module tries to delegate member lookup to Using tools from the Pickle protocol, like __getstate__/setstate, |
I don't understand the use case for this. If the StreamWriter/Reader cannot pickle the underlying stream (which is What we could do is implement .__get/setstate__() and have it raise an |
Sounds good to me. The main intention of this bug is not to make codecs |
Implementing only .__get/setstate__() doesn't fix all problem. We have implement also __getnewargs_ex__(). But implemented __getnewargs_ex__() has priority over __getnewargs__() implemented in subclasses. And may be there are problems with other optional special methods that are incorrectly delegated to the stream in codecs IO classes. I think more reliable way is to disallow delegating all special (or may be even private) methods. Here is a patch. |
io.BytesIO() and io.StringIO() are pickleable. |
On 02.12.2015 20:16, Serhiy Storchaka wrote:
Ok, but I still don't see the use case :-) I think all we need to do is add a .__reduce__() Example: >>> import sys, codecs, pickle
>>> r = codecs.getreader('latin-1')
>>> class MyReader(r):
... def __reduce__(self, *args):
... raise pickle.PickleError
...
>>> s = MyReader(sys.stdin)
>>> pickle.dumps(s)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __reduce__
_pickle.PickleError
> <stdin>(3)__reduce__() |
Added tests for pickling and deepcopying. |
Rather TypeError. Yes, it is the least that we should to do in maintained releases. If codecs_stream_delegating_2.patch is considered too drastic for bugfix. But this can be only a part of problem. May be there are issues with other optional special methods. And adding __reduce_ex__ breaks subclass pickleability if it was implemented with __getstate__ and __getnewargs__. Here is a patch for this way. |
On 02.12.2015 21:29, Serhiy Storchaka wrote:
Thanks. I think using __reduce__ instead of __reduce_ex__ is The other approach will have too many backwards incompatible side |
There is also a problem with deepcopying: >>> class MemReader:
... def __init__(self, data):
... self.buf = memoryview(data).cast('B')
... def read(self, size=-1):
... if size < 0:
... size = len(self.buf)
... res = bytes(self.buf[:size])
... self.buf = self.buf[size:]
... return res
... def close():
... pass
... def __deepcopy__(self, memo):
... return MemReader(self.buf)
... def __reduce__(self):
... return MemReader, (bytes(self.buf),)
...
>>> import codecs, copy
>>> s1 = codecs.getreader('utf-8')(MemReader(b'abcd'))
>>> s2 = copy.deepcopy(s1)
>>> s1.read()
'abcd'
>>> s2.read()
b'abcd'
>>> s2
<__main__.MemReader object at 0xb701988c> |
Attempts to pickle or create a shallow or deep copy of codecs streams now raise a TypeError. Previously, stream pickling produced invalid data, which attempts to read resulted in a RecursionError, as well as attempts to create a copy of the stream.
Attempts to pickle or create a shallow or deep copy of codecs streams now raise a TypeError. Previously, stream pickling produced invalid data, which attempts to read resulted in a RecursionError, as well as attempts to create a copy of the stream.
Attempts to pickle or create a shallow or deep copy of codecs streams now raise a TypeError. Previously, copying failed with a RecursionError, while pickling produced wrong results that eventually caused unpickling to fail with a RecursionError. (cherry picked from commit d6892c2) Co-authored-by: Serhiy Storchaka <[email protected]>
Attempts to pickle or create a shallow or deep copy of codecs streams now raise a TypeError. Previously, copying failed with a RecursionError, while pickling produced wrong results that eventually caused unpickling to fail with a RecursionError.
Attempts to pickle or create a shallow or deep copy of codecs streams now raise a TypeError. Previously, copying failed with a RecursionError, while pickling produced wrong results that eventually caused unpickling to fail with a RecursionError. (cherry picked from commit d6892c2) Co-authored-by: Serhiy Storchaka <[email protected]>
…9232) Attempts to pickle or create a shallow or deep copy of codecs streams now raise a TypeError. Previously, copying failed with a RecursionError, while pickling produced wrong results that eventually caused unpickling to fail with a RecursionError. (cherry picked from commit d6892c2) Co-authored-by: Serhiy Storchaka <[email protected]>
gh-50644: Forbid pickling of codecs streams (GH-109180) Attempts to pickle or create a shallow or deep copy of codecs streams now raise a TypeError. Previously, copying failed with a RecursionError, while pickling produced wrong results that eventually caused unpickling to fail with a RecursionError. (cherry picked from commit d6892c2) Co-authored-by: Serhiy Storchaka <[email protected]>
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
Linked PRs
The text was updated successfully, but these errors were encountered: