[New-bugs-announce] [issue37997] Segfault when using pickle with exceptions and dynamic class inheritance
Gabriel C
report at bugs.python.org
Sat Aug 31 19:39:17 EDT 2019
New submission from Gabriel C <gabrielc at mit.edu>:
The following results in a segfault on 3.7.4 (running on macOS high sierra) and 3.5 (running on ubuntu 16.04). It does not happen in python 2.7.
The problem seems to involve two effects. The first is the creation of a class with a dynamic type that inherits from a MemoryError (but any exception will work). The second is pickling an instance of that MemoryError (note that the dynamic type is never pickled).
If a basic (non-exception) class is used instead of the MemoryError (see uncomment case 1), then the segfault does not occur in my testing. If the exception being pickled is a different type to the one used as the base class for the dynamic type, the segfault does not occur.
Note that unpickling the MemoryError actually raises another exception, this raised exception (see uncomment case 2) is raised by the dynamic type class __init__ method. It seems that in trying to unpickle the MemoryError, pickle attempts to create an instance of the unrelated dynamic type instead. Examining the stack trace (uncomment case 3), shows the raised exception is indeed originating from attempting to unpickle the MemoryError.
The segfault does not happen immediately, but instead after several attempts. It can happen after as few as 5 attempts or as many as 100.
```
import pickle
def CreateDynamicClass(basetype):
class DynamicClassImpl(basetype):
def __init__(self):
super(DynamicClassImpl, self).__init__()
return DynamicClassImpl()
class TestClass(object):
pass
N_attemps = 1000
pickle_list = []
def load_list():
for i in range(N_attemps):
test_exception = MemoryError("Test" + str(i))
#test_exception = TestClass() # Uncomment case 1
pickle_list.append(pickle.dumps(test_exception))
load_list()
def unload_list():
for i in range(N_attemps):
try:
test_object_instance = pickle.loads(pickle_list.pop())
test_dynamic_object = CreateDynamicClass(MemoryError)
#test_dynamic_object = CreateDynamicClass(TestClass) # Uncomment case 1
except Exception as e:
print("Exception at iteration {}: {}".format(i, e)) # Uncomment case 2
#raise # Uncomment case 3
pass
unload_list()
```
----------
components: Library (Lib)
messages: 350932
nosy: gabrielc
priority: normal
severity: normal
status: open
title: Segfault when using pickle with exceptions and dynamic class inheritance
type: crash
versions: Python 3.5, Python 3.7
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue37997>
_______________________________________
More information about the New-bugs-announce
mailing list