Skip to content

Commit 6cdacd8

Browse files
committed
gh-123083: Fix STORE_ATTR_WITH_HINT has potential use-after-free
1 parent 35d8ac7 commit 6cdacd8

File tree

5 files changed

+22
-3
lines changed

5 files changed

+22
-3
lines changed

Lib/test/test_dict.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,6 +1476,24 @@ def test_dict_items_result_gc_reversed(self):
14761476
gc.collect()
14771477
self.assertTrue(gc.is_tracked(next(it)))
14781478

1479+
def test_store_evilattr(self):
1480+
class EvilAttr:
1481+
def __init__(self, d):
1482+
self.d = d
1483+
1484+
def __del__(self):
1485+
if 'attr' in self.d:
1486+
del self.d['attr']
1487+
gc.collect()
1488+
1489+
class Obj:
1490+
pass
1491+
1492+
obj = Obj()
1493+
obj.__dict__ = {}
1494+
for _ in range(10):
1495+
obj.attr = EvilAttr(obj.__dict__)
1496+
14791497
def test_str_nonstr(self):
14801498
# cpython uses a different lookup function if the dict only contains
14811499
# `str` keys. Make sure the unoptimized path is used when a non-`str`
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix STORE_ATTR_WITH_HINT has potential use-after-free.

Python/bytecodes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2234,12 +2234,12 @@ dummy_func(
22342234
PyDict_WatchEvent event = old_value == NULL ? PyDict_EVENT_ADDED : PyDict_EVENT_MODIFIED;
22352235
new_version = _PyDict_NotifyEvent(tstate->interp, event, dict, name, PyStackRef_AsPyObjectBorrow(value));
22362236
ep->me_value = PyStackRef_AsPyObjectSteal(value);
2237-
Py_XDECREF(old_value);
22382237
STAT_INC(STORE_ATTR, hit);
22392238
/* Ensure dict is GC tracked if it needs to be */
22402239
if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(PyStackRef_AsPyObjectBorrow(value))) {
22412240
_PyObject_GC_TRACK(dict);
22422241
}
2242+
Py_XDECREF(old_value);
22432243
/* PEP 509 */
22442244
dict->ma_version_tag = new_version;
22452245
PyStackRef_CLOSE(owner);

Python/executor_cases.c.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)