Skip to content

Commit c5275d7

Browse files
committed
Merge branch '3.14' of https://github.com/python/cpython into 3.14
2 parents 20b6439 + a3d76e1 commit c5275d7

4 files changed

Lines changed: 25 additions & 9 deletions

File tree

Doc/c-api/weakref.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ as much as it can.
4242
callable object that receives notification when *ob* is garbage collected; it
4343
should accept a single parameter, which will be the weak reference object
4444
itself. *callback* may also be ``None`` or ``NULL``. If *ob* is not a
45-
weakly referenceable object, or if *callback* is not callable, ``None``, or
46-
``NULL``, this will return ``NULL`` and raise :exc:`TypeError`.
45+
weakly referenceable object, this will raise :exc:`TypeError` and return
46+
``NULL``.
4747
4848
.. seealso::
4949
:c:func:`PyType_SUPPORTS_WEAKREFS` for checking if *ob* is weakly
@@ -58,8 +58,8 @@ as much as it can.
5858
be a callable object that receives notification when *ob* is garbage
5959
collected; it should accept a single parameter, which will be the weak
6060
reference object itself. *callback* may also be ``None`` or ``NULL``. If *ob*
61-
is not a weakly referenceable object, or if *callback* is not callable,
62-
``None``, or ``NULL``, this will return ``NULL`` and raise :exc:`TypeError`.
61+
weakly referenceable object, this will raise :exc:`TypeError` and return
62+
``NULL``.
6363
6464
.. seealso::
6565
:c:func:`PyType_SUPPORTS_WEAKREFS` for checking if *ob* is weakly

Lib/test/test_exceptions.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,6 +1706,20 @@ def inner():
17061706
gc_collect() # For PyPy or other GCs.
17071707
self.assertEqual(wr(), None)
17081708

1709+
def test_oserror_reinit_leak(self):
1710+
# gh-150988: Check for memory leak when re-initializing OSError.
1711+
# Previously, setting OSError attributes in a subclass
1712+
# before calling super().__init__() leaked memory.
1713+
class LeakingOSError(OSError):
1714+
def __init__(self, code, message, filename, filename2):
1715+
self.strerror = message
1716+
self.filename = filename
1717+
self.filename2 = filename2
1718+
super().__init__(code, message, filename, None, filename2)
1719+
1720+
exc = LeakingOSError(1, "some message", "filename.py", "filename2.py")
1721+
exc.__init__(2, "another message", "filename3.py", "filename4.py")
1722+
17091723
def test_errno_ENOTDIR(self):
17101724
# Issue #12802: "not a directory" errors are ENOTDIR even on Windows
17111725
with self.assertRaises(OSError) as cm:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a reference leak in :exc:`OSError` when attributes are set before
2+
``super().__init__()``.

Objects/exceptions.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2074,10 +2074,10 @@ oserror_init(PyOSErrorObject *self, PyObject **p_args,
20742074
return -1;
20752075
}
20762076
else {
2077-
self->filename = Py_NewRef(filename);
2077+
Py_XSETREF(self->filename, Py_NewRef(filename));
20782078

20792079
if (filename2 && filename2 != Py_None) {
2080-
self->filename2 = Py_NewRef(filename2);
2080+
Py_XSETREF(self->filename2, Py_NewRef(filename2));
20812081
}
20822082

20832083
if (nargs >= 2 && nargs <= 5) {
@@ -2092,10 +2092,10 @@ oserror_init(PyOSErrorObject *self, PyObject **p_args,
20922092
}
20932093
}
20942094
}
2095-
self->myerrno = Py_XNewRef(myerrno);
2096-
self->strerror = Py_XNewRef(strerror);
2095+
Py_XSETREF(self->myerrno, Py_XNewRef(myerrno));
2096+
Py_XSETREF(self->strerror, Py_XNewRef(strerror));
20972097
#ifdef MS_WINDOWS
2098-
self->winerror = Py_XNewRef(winerror);
2098+
Py_XSETREF(self->winerror, Py_XNewRef(winerror));
20992099
#endif
21002100

21012101
/* Steals the reference to args */

0 commit comments

Comments
 (0)