Commit 842acaab authored by Zackery Spytz's avatar Zackery Spytz Committed by Serhiy Storchaka

bpo-35504: Fix segfaults and SystemErrors when deleting certain attrs. (GH-11175)

parent 4db62e11
...@@ -54,6 +54,13 @@ class StringArrayTestCase(unittest.TestCase): ...@@ -54,6 +54,13 @@ class StringArrayTestCase(unittest.TestCase):
## print BUF.from_param(c_char_p("python")) ## print BUF.from_param(c_char_p("python"))
## print BUF.from_param(BUF(*"pyth")) ## 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') @need_symbol('c_wchar')
class WStringArrayTestCase(unittest.TestCase): class WStringArrayTestCase(unittest.TestCase):
def test(self): def test(self):
......
...@@ -379,6 +379,10 @@ class RegressionTests(unittest.TestCase): ...@@ -379,6 +379,10 @@ class RegressionTests(unittest.TestCase):
del ref del ref
support.gc_collect() support.gc_collect()
def CheckDelIsolation_levelSegfault(self):
with self.assertRaises(AttributeError):
del self.con.isolation_level
class UnhashableFunc: class UnhashableFunc:
__hash__ = None __hash__ = None
......
...@@ -277,6 +277,11 @@ class TestBase: ...@@ -277,6 +277,11 @@ class TestBase:
writer = self.writer(stream) writer = self.writer(stream)
writer.reset() writer.reset()
def test_incrementalencoder_del_segfault(self):
e = self.incrementalencoder()
with self.assertRaises(AttributeError):
del e.errors
class TestBase_Mapping(unittest.TestCase): class TestBase_Mapping(unittest.TestCase):
pass_enctest = [] pass_enctest = []
......
...@@ -570,6 +570,13 @@ class CFutureTests(BaseFutureTests, test_utils.TestCase): ...@@ -570,6 +570,13 @@ class CFutureTests(BaseFutureTests, test_utils.TestCase):
except AttributeError: except AttributeError:
cls = None 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'), @unittest.skipUnless(hasattr(futures, '_CFuture'),
'requires the C _asyncio module') 'requires the C _asyncio module')
......
...@@ -2546,6 +2546,15 @@ class CTask_CFuture_Tests(BaseTaskTests, SetMethodsTest, ...@@ -2546,6 +2546,15 @@ class CTask_CFuture_Tests(BaseTaskTests, SetMethodsTest,
self.loop.run_until_complete(task) self.loop.run_until_complete(task)
self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) 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 @unittest.skipUnless(hasattr(futures, '_CFuture') and
hasattr(tasks, '_CTask'), hasattr(tasks, '_CTask'),
......
...@@ -109,10 +109,7 @@ class ClearTest(unittest.TestCase): ...@@ -109,10 +109,7 @@ class ClearTest(unittest.TestCase):
self.assertIs(None, wr()) self.assertIs(None, wr())
class FrameLocalsTest(unittest.TestCase): class FrameAttrsTest(unittest.TestCase):
"""
Tests for the .f_locals attribute.
"""
def make_frames(self): def make_frames(self):
def outer(): def outer():
...@@ -159,6 +156,11 @@ class FrameLocalsTest(unittest.TestCase): ...@@ -159,6 +156,11 @@ class FrameLocalsTest(unittest.TestCase):
self.assertEqual(outer.f_locals, {}) self.assertEqual(outer.f_locals, {})
self.assertEqual(inner.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): class ReprTest(unittest.TestCase):
""" """
......
...@@ -3663,6 +3663,11 @@ class CTextIOWrapperTest(TextIOWrapperTest): ...@@ -3663,6 +3663,11 @@ class CTextIOWrapperTest(TextIOWrapperTest):
t2.buddy = t1 t2.buddy = t1
support.gc_collect() 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): class PyTextIOWrapperTest(TextIOWrapperTest):
io = pyio io = pyio
......
Fix segfaults and :exc:`SystemError`\ s when deleting certain attributes.
Patch by Zackery Spytz.
...@@ -1113,6 +1113,10 @@ FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored)) ...@@ -1113,6 +1113,10 @@ FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
if (future_ensure_alive(fut)) { if (future_ensure_alive(fut)) {
return -1; return -1;
} }
if (val == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
int is_true = PyObject_IsTrue(val); int is_true = PyObject_IsTrue(val);
if (is_true < 0) { if (is_true < 0) {
...@@ -1137,6 +1141,10 @@ FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored)) ...@@ -1137,6 +1141,10 @@ FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
static int static int
FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored)) 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); int is_true = PyObject_IsTrue(val);
if (is_true < 0) { if (is_true < 0) {
return -1; return -1;
...@@ -2015,6 +2023,10 @@ TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored)) ...@@ -2015,6 +2023,10 @@ TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
static int static int
TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored)) 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); int is_true = PyObject_IsTrue(val);
if (is_true < 0) { if (is_true < 0) {
return -1; return -1;
......
...@@ -1191,6 +1191,10 @@ CharArray_set_raw(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) ...@@ -1191,6 +1191,10 @@ CharArray_set_raw(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored))
Py_ssize_t size; Py_ssize_t size;
Py_buffer view; Py_buffer view;
if (value == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
if (PyObject_GetBuffer(value, &view, PyBUF_SIMPLE) < 0) if (PyObject_GetBuffer(value, &view, PyBUF_SIMPLE) < 0)
return -1; return -1;
size = view.len; size = view.len;
......
...@@ -3042,6 +3042,10 @@ textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context) ...@@ -3042,6 +3042,10 @@ textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context)
{ {
Py_ssize_t n; Py_ssize_t n;
CHECK_ATTACHED_INT(self); CHECK_ATTACHED_INT(self);
if (arg == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
n = PyNumber_AsSsize_t(arg, PyExc_ValueError); n = PyNumber_AsSsize_t(arg, PyExc_ValueError);
if (n == -1 && PyErr_Occurred()) if (n == -1 && PyErr_Occurred())
return -1; return -1;
......
...@@ -1161,6 +1161,10 @@ static PyObject* pysqlite_connection_get_in_transaction(pysqlite_Connection* sel ...@@ -1161,6 +1161,10 @@ static PyObject* pysqlite_connection_get_in_transaction(pysqlite_Connection* sel
static int static int
pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level, void *Py_UNUSED(ignored)) 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) { if (isolation_level == Py_None) {
PyObject *res = pysqlite_connection_commit(self, NULL); PyObject *res = pysqlite_connection_commit(self, NULL);
if (!res) { if (!res) {
......
...@@ -3625,6 +3625,10 @@ static int ...@@ -3625,6 +3625,10 @@ static int
set_post_handshake_auth(PySSLContext *self, PyObject *arg, void *c) { set_post_handshake_auth(PySSLContext *self, PyObject *arg, void *c) {
int (*verify_cb)(int, X509_STORE_CTX *) = NULL; int (*verify_cb)(int, X509_STORE_CTX *) = NULL;
int mode = SSL_CTX_get_verify_mode(self->ctx); 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); int pha = PyObject_IsTrue(arg);
if (pha == -1) { if (pha == -1) {
......
...@@ -133,6 +133,10 @@ codecctx_errors_set(MultibyteStatefulCodecContext *self, PyObject *value, ...@@ -133,6 +133,10 @@ codecctx_errors_set(MultibyteStatefulCodecContext *self, PyObject *value,
PyObject *cb; PyObject *cb;
const char *str; const char *str;
if (value == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
if (!PyUnicode_Check(value)) { if (!PyUnicode_Check(value)) {
PyErr_SetString(PyExc_TypeError, "errors must be a string"); PyErr_SetString(PyExc_TypeError, "errors must be a string");
return -1; return -1;
......
...@@ -105,6 +105,10 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore ...@@ -105,6 +105,10 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */ int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */
int blockstack_top = 0; /* (ditto) */ int blockstack_top = 0; /* (ditto) */
if (p_new_lineno == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
/* f_lineno must be an integer. */ /* f_lineno must be an integer. */
if (!PyLong_CheckExact(p_new_lineno)) { if (!PyLong_CheckExact(p_new_lineno)) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment