Skip to content

Commit fa16a75

Browse files
brijkapadiablurb-it[bot]vstinner
authored
[3.13] gh-146011: Fix use-after-free in signaldict_repr after deletion (GH-153784) (#154607)
* [3.13] gh-146011: Fix use-after-free in `signaldict_repr` after deletion (GH-153784) (cherry picked from commit 41a087a) Co-authored-by: Brij Kapadia <97006829+brijkapadia@users.noreply.github.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent 3871923 commit fa16a75

3 files changed

Lines changed: 25 additions & 0 deletions

File tree

Lib/test/test_decimal.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4098,6 +4098,15 @@ def test_float_operation_default(self):
40984098
@requires_cdecimal
40994099
class CContextFlags(ContextFlags, unittest.TestCase):
41004100
decimal = C
4101+
4102+
def test_signaldict_repr(self):
4103+
Context = self.decimal.Context
4104+
ctx = Context(prec=7)
4105+
mapping = ctx.flags
4106+
del ctx
4107+
with self.assertRaisesRegex(ValueError, 'invalid signal dict'):
4108+
repr(mapping)
4109+
41014110
class PyContextFlags(ContextFlags, unittest.TestCase):
41024111
decimal = P
41034112

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a heap-use-after-free in the C implementation of :mod:`decimal`
2+
when calling :func:`repr` after deleting the :class:`~decimal.Context`.

Modules/_decimal/_decimal.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,6 +1419,20 @@ context_traverse(PyDecContextObject *self, visitproc visit, void *arg)
14191419
static int
14201420
context_clear(PyDecContextObject *self)
14211421
{
1422+
/* Since traps and flags hold a borrowed reference to the
1423+
flags stored in the context object, these references need
1424+
to be cleared when the context object is deallocated
1425+
because traps and flags can survive. See gh-146011. */
1426+
PyDecSignalDictObject *traps = (PyDecSignalDictObject *)self->traps;
1427+
PyDecSignalDictObject *flags = (PyDecSignalDictObject *)self->flags;
1428+
1429+
if (traps != NULL) {
1430+
traps->flags = NULL;
1431+
}
1432+
if (flags != NULL) {
1433+
flags->flags = NULL;
1434+
}
1435+
14221436
Py_CLEAR(self->traps);
14231437
Py_CLEAR(self->flags);
14241438
return 0;

0 commit comments

Comments
 (0)