Skip to content

[3.7] bpo-35504: Fix segfaults and SystemErrors when deleting certain attrs. (GH-11175) #11197

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

Merged
merged 1 commit into from
Dec 17, 2018
Merged
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
7 changes: 7 additions & 0 deletions Lib/ctypes/test/test_strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ def test_param_2(self):
## print BUF.from_param(c_char_p("python"))
## print BUF.from_param(BUF(*"pyth"))

def test_del_segfault(self):
BUF = c_char * 4
buf = BUF()
with self.assertRaises(AttributeError):
del buf.raw


@need_symbol('c_wchar')
class WStringArrayTestCase(unittest.TestCase):
def test(self):
Expand Down
4 changes: 4 additions & 0 deletions Lib/sqlite3/test/regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,10 @@ def callback(*args):
del ref
support.gc_collect()

def CheckDelIsolation_levelSegfault(self):
with self.assertRaises(AttributeError):
del self.con.isolation_level


class UnhashableFunc:
__hash__ = None
Expand Down
5 changes: 5 additions & 0 deletions Lib/test/multibytecodec_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,11 @@ def test_streamwriter_reset_no_pending(self):
writer = self.writer(stream)
writer.reset()

def test_incrementalencoder_del_segfault(self):
e = self.incrementalencoder()
with self.assertRaises(AttributeError):
del e.errors


class TestBase_Mapping(unittest.TestCase):
pass_enctest = []
Expand Down
7 changes: 7 additions & 0 deletions Lib/test/test_asyncio/test_futures.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,13 @@ class CFutureTests(BaseFutureTests, test_utils.TestCase):
except AttributeError:
cls = None

def test_future_del_segfault(self):
fut = self._new_future(loop=self.loop)
with self.assertRaises(AttributeError):
del fut._asyncio_future_blocking
with self.assertRaises(AttributeError):
del fut._log_traceback


@unittest.skipUnless(hasattr(futures, '_CFuture'),
'requires the C _asyncio module')
Expand Down
9 changes: 9 additions & 0 deletions Lib/test/test_asyncio/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2512,6 +2512,15 @@ def coro():
self.loop.run_until_complete(task)
self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10)

def test_del__log_destroy_pending_segfault(self):
@asyncio.coroutine
def coro():
pass
task = self.new_task(self.loop, coro())
self.loop.run_until_complete(task)
with self.assertRaises(AttributeError):
del task._log_destroy_pending


@unittest.skipUnless(hasattr(futures, '_CFuture') and
hasattr(tasks, '_CTask'),
Expand Down
10 changes: 6 additions & 4 deletions Lib/test/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,7 @@ class C:
self.assertIs(None, wr())


class FrameLocalsTest(unittest.TestCase):
"""
Tests for the .f_locals attribute.
"""
class FrameAttrsTest(unittest.TestCase):

def make_frames(self):
def outer():
Expand Down Expand Up @@ -159,6 +156,11 @@ def test_locals_clear_locals(self):
self.assertEqual(outer.f_locals, {})
self.assertEqual(inner.f_locals, {})

def test_f_lineno_del_segfault(self):
f, _, _ = self.make_frames()
with self.assertRaises(AttributeError):
del f.f_lineno


class ReprTest(unittest.TestCase):
"""
Expand Down
5 changes: 5 additions & 0 deletions Lib/test/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -3635,6 +3635,11 @@ def test_rwpair_cleared_before_textio(self):
t2.buddy = t1
support.gc_collect()

def test_del__CHUNK_SIZE_SystemError(self):
t = self.TextIOWrapper(self.BytesIO(), encoding='ascii')
with self.assertRaises(AttributeError):
del t._CHUNK_SIZE


class PyTextIOWrapperTest(TextIOWrapperTest):
io = pyio
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix segfaults and :exc:`SystemError`\ s when deleting certain attributes.
Patch by Zackery Spytz.
12 changes: 12 additions & 0 deletions Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,10 @@ FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
if (future_ensure_alive(fut)) {
return -1;
}
if (val == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}

int is_true = PyObject_IsTrue(val);
if (is_true < 0) {
Expand All @@ -1134,6 +1138,10 @@ FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
static int
FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
{
if (val == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
int is_true = PyObject_IsTrue(val);
if (is_true < 0) {
return -1;
Expand Down Expand Up @@ -2008,6 +2016,10 @@ TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
static int
TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
{
if (val == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
int is_true = PyObject_IsTrue(val);
if (is_true < 0) {
return -1;
Expand Down
4 changes: 4 additions & 0 deletions Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1171,6 +1171,10 @@ CharArray_set_raw(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored))
Py_ssize_t size;
Py_buffer view;

if (value == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
if (PyObject_GetBuffer(value, &view, PyBUF_SIMPLE) < 0)
return -1;
size = view.len;
Expand Down
4 changes: 4 additions & 0 deletions Modules/_io/textio.c
Original file line number Diff line number Diff line change
Expand Up @@ -3049,6 +3049,10 @@ textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context)
{
Py_ssize_t n;
CHECK_ATTACHED_INT(self);
if (arg == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
n = PyNumber_AsSsize_t(arg, PyExc_ValueError);
if (n == -1 && PyErr_Occurred())
return -1;
Expand Down
4 changes: 4 additions & 0 deletions Modules/_sqlite/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,10 @@ static PyObject* pysqlite_connection_get_in_transaction(pysqlite_Connection* sel
static int
pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level, void *Py_UNUSED(ignored))
{
if (isolation_level == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
if (isolation_level == Py_None) {
PyObject *res = pysqlite_connection_commit(self, NULL);
if (!res) {
Expand Down
4 changes: 4 additions & 0 deletions Modules/_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -3626,6 +3626,10 @@ static int
set_post_handshake_auth(PySSLContext *self, PyObject *arg, void *c) {
int (*verify_cb)(int, X509_STORE_CTX *) = NULL;
int mode = SSL_CTX_get_verify_mode(self->ctx);
if (arg == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
int pha = PyObject_IsTrue(arg);

if (pha == -1) {
Expand Down
4 changes: 4 additions & 0 deletions Modules/cjkcodecs/multibytecodec.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ codecctx_errors_set(MultibyteStatefulCodecContext *self, PyObject *value,
PyObject *cb;
const char *str;

if (value == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
if (!PyUnicode_Check(value)) {
PyErr_SetString(PyExc_TypeError, "errors must be a string");
return -1;
Expand Down
4 changes: 4 additions & 0 deletions Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
int blockstack_top = 0; /* (ditto) */
unsigned char setup_op = 0; /* (ditto) */

if (p_new_lineno == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
/* f_lineno must be an integer. */
if (!PyLong_CheckExact(p_new_lineno)) {
PyErr_SetString(PyExc_ValueError,
Expand Down