Skip to content

Commit cb27284

Browse files
bpo-35504: Fix segfaults and SystemErrors when deleting certain attrs. (GH-11175)
(cherry picked from commit 842acaa) Co-authored-by: Zackery Spytz <[email protected]>
1 parent c367d52 commit cb27284

File tree

15 files changed

+81
-4
lines changed

15 files changed

+81
-4
lines changed

Lib/ctypes/test/test_strings.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ def test_param_2(self):
5454
## print BUF.from_param(c_char_p("python"))
5555
## print BUF.from_param(BUF(*"pyth"))
5656

57+
def test_del_segfault(self):
58+
BUF = c_char * 4
59+
buf = BUF()
60+
with self.assertRaises(AttributeError):
61+
del buf.raw
62+
63+
5764
@need_symbol('c_wchar')
5865
class WStringArrayTestCase(unittest.TestCase):
5966
def test(self):

Lib/sqlite3/test/regression.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,10 @@ def callback(*args):
379379
del ref
380380
support.gc_collect()
381381

382+
def CheckDelIsolation_levelSegfault(self):
383+
with self.assertRaises(AttributeError):
384+
del self.con.isolation_level
385+
382386

383387
class UnhashableFunc:
384388
__hash__ = None

Lib/test/multibytecodec_support.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,11 @@ def test_streamwriter_reset_no_pending(self):
277277
writer = self.writer(stream)
278278
writer.reset()
279279

280+
def test_incrementalencoder_del_segfault(self):
281+
e = self.incrementalencoder()
282+
with self.assertRaises(AttributeError):
283+
del e.errors
284+
280285

281286
class TestBase_Mapping(unittest.TestCase):
282287
pass_enctest = []

Lib/test/test_asyncio/test_futures.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,13 @@ class CFutureTests(BaseFutureTests, test_utils.TestCase):
566566
except AttributeError:
567567
cls = None
568568

569+
def test_future_del_segfault(self):
570+
fut = self._new_future(loop=self.loop)
571+
with self.assertRaises(AttributeError):
572+
del fut._asyncio_future_blocking
573+
with self.assertRaises(AttributeError):
574+
del fut._log_traceback
575+
569576

570577
@unittest.skipUnless(hasattr(futures, '_CFuture'),
571578
'requires the C _asyncio module')

Lib/test/test_asyncio/test_tasks.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,6 +2512,15 @@ def coro():
25122512
self.loop.run_until_complete(task)
25132513
self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10)
25142514

2515+
def test_del__log_destroy_pending_segfault(self):
2516+
@asyncio.coroutine
2517+
def coro():
2518+
pass
2519+
task = self.new_task(self.loop, coro())
2520+
self.loop.run_until_complete(task)
2521+
with self.assertRaises(AttributeError):
2522+
del task._log_destroy_pending
2523+
25152524

25162525
@unittest.skipUnless(hasattr(futures, '_CFuture') and
25172526
hasattr(tasks, '_CTask'),

Lib/test/test_frame.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,7 @@ class C:
109109
self.assertIs(None, wr())
110110

111111

112-
class FrameLocalsTest(unittest.TestCase):
113-
"""
114-
Tests for the .f_locals attribute.
115-
"""
112+
class FrameAttrsTest(unittest.TestCase):
116113

117114
def make_frames(self):
118115
def outer():
@@ -159,6 +156,11 @@ def test_locals_clear_locals(self):
159156
self.assertEqual(outer.f_locals, {})
160157
self.assertEqual(inner.f_locals, {})
161158

159+
def test_f_lineno_del_segfault(self):
160+
f, _, _ = self.make_frames()
161+
with self.assertRaises(AttributeError):
162+
del f.f_lineno
163+
162164

163165
class ReprTest(unittest.TestCase):
164166
"""

Lib/test/test_io.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3635,6 +3635,11 @@ def test_rwpair_cleared_before_textio(self):
36353635
t2.buddy = t1
36363636
support.gc_collect()
36373637

3638+
def test_del__CHUNK_SIZE_SystemError(self):
3639+
t = self.TextIOWrapper(self.BytesIO(), encoding='ascii')
3640+
with self.assertRaises(AttributeError):
3641+
del t._CHUNK_SIZE
3642+
36383643

36393644
class PyTextIOWrapperTest(TextIOWrapperTest):
36403645
io = pyio
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix segfaults and :exc:`SystemError`\ s when deleting certain attributes.
2+
Patch by Zackery Spytz.

Modules/_asynciomodule.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,10 @@ FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
11101110
if (future_ensure_alive(fut)) {
11111111
return -1;
11121112
}
1113+
if (val == NULL) {
1114+
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1115+
return -1;
1116+
}
11131117

11141118
int is_true = PyObject_IsTrue(val);
11151119
if (is_true < 0) {
@@ -1134,6 +1138,10 @@ FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
11341138
static int
11351139
FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
11361140
{
1141+
if (val == NULL) {
1142+
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1143+
return -1;
1144+
}
11371145
int is_true = PyObject_IsTrue(val);
11381146
if (is_true < 0) {
11391147
return -1;
@@ -2008,6 +2016,10 @@ TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
20082016
static int
20092017
TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
20102018
{
2019+
if (val == NULL) {
2020+
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2021+
return -1;
2022+
}
20112023
int is_true = PyObject_IsTrue(val);
20122024
if (is_true < 0) {
20132025
return -1;

Modules/_ctypes/_ctypes.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,10 @@ CharArray_set_raw(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored))
11711171
Py_ssize_t size;
11721172
Py_buffer view;
11731173

1174+
if (value == NULL) {
1175+
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1176+
return -1;
1177+
}
11741178
if (PyObject_GetBuffer(value, &view, PyBUF_SIMPLE) < 0)
11751179
return -1;
11761180
size = view.len;

0 commit comments

Comments
 (0)