Skip to content

GH-82565: Fixed a possible assertion error #103206

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions Lib/test/pickletester.py
Original file line number Diff line number Diff line change
Expand Up @@ -3482,6 +3482,79 @@ def __init__(self): pass
self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)

def test_unpickler_bad_file(self):
# bpo-38384: Crash in _pickle if the read attribute raises an error.
def raises_oserror(self, *args, **kwargs):
raise OSError
@property
def bad_property(self):
1/0

# File without read
class F:
readline = raises_oserror
self.assertRaises((AttributeError, TypeError), self.Unpickler, F())

# File without readline
class F:
read = raises_oserror
self.assertRaises((AttributeError, TypeError), self.Unpickler, F())

# File with bad read
class F:
read = bad_property
readline = raises_oserror
self.assertRaises(ZeroDivisionError, self.Unpickler, F())

# File with bad readline
class F:
readline = bad_property
read = raises_oserror
self.assertRaises(ZeroDivisionError, self.Unpickler, F())

# File with bad read and without readline
class F:
read = bad_property
self.assertRaises(ZeroDivisionError, self.Unpickler, F())

# File with bad readline and without read
class F:
readline = bad_property
self.assertRaises(ZeroDivisionError, self.Unpickler, F())

# File with bad peek
class F:
peek = bad_property
read = raises_oserror
readline = raises_oserror
try:
self.Unpickler(F())
except ZeroDivisionError:
pass

# File with bad readinto
class F:
readinto = bad_property
read = raises_oserror
readline = raises_oserror
try:
self.Unpickler(F())
except ZeroDivisionError:
pass

def test_pickler_bad_file(self):
# File without write
class F:
pass
self.assertRaises(TypeError, self.Pickler, F())

# File with bad write
class F:
@property
def write(self):
1/0
self.assertRaises(ZeroDivisionError, self.Pickler, F())

def check_dumps_loads_oob_buffers(self, dumps, loads):
# No need to do the full gamut of tests here, just enough to
# check that dumps() and loads() redirect their arguments
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix a crash in the C implementation of :mod:`pickle` if an error occurred
while looking up the ``read`` and ``readline`` attribute of the file.
11 changes: 8 additions & 3 deletions Modules/_pickle.c
Original file line number Diff line number Diff line change
Expand Up @@ -1632,16 +1632,21 @@ _Unpickler_New(void)
static int
_Unpickler_SetInputStream(UnpicklerObject *self, PyObject *file)
{
_Py_IDENTIFIER(peek);
_Py_IDENTIFIER(read);
_Py_IDENTIFIER(readinto);
_Py_IDENTIFIER(readline);

/* Optional file methods */
if (_PyObject_LookupAttr(file, &_Py_ID(peek), &self->peek) < 0) {
return -1;
}
if (_PyObject_LookupAttr(file, &_Py_ID(readinto), &self->readinto) < 0) {
return -1;
}
(void)_PyObject_LookupAttr(file, &_Py_ID(read), &self->read);
(void)_PyObject_LookupAttr(file, &_Py_ID(readline), &self->readline);
if (!self->readline || !self->read) {
if (_PyObject_LookupAttrId(file, &PyId_read, &self->read) <= 0 ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems that you forgot to define a PyId_read and PyId_readline.
However, have you try to a built python with this patch manually?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have fixed this issue in the latest commit ✅

Please have a look , Thanks

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems that tests keep falling.
You sure that you made necessary changes?

Copy link
Author

@SahillMulani SahillMulani Apr 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below changes are made by me :

image

All other changes are imported as it is from #16606

Therefore, I am not sure where exactly the code is failing .

_PyObject_LookupAttrId(file, &PyId_readline, &self->readline) <= 0)
{
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"file must have 'read' and 'readline' attributes");
Expand Down