Skip to content

Commit 3a04c62

Browse files
committed
Merge branch '3.13' of https://github.com/python/cpython into 3.13
2 parents d3e29c1 + 60123e6 commit 3a04c62

4 files changed

Lines changed: 25 additions & 9 deletions

File tree

Doc/c-api/memory.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ memory footprint as a whole. Consequently, under certain circumstances, the
8181
Python memory manager may or may not trigger appropriate actions, like garbage
8282
collection, memory compaction or other preventive procedures. Note that by using
8383
the C library allocator as shown in the previous example, the allocated memory
84-
for the I/O buffer escapes completely the Python memory manager.
84+
for the I/O buffer completely escapes the Python memory manager.
8585

8686
.. seealso::
8787

@@ -161,7 +161,7 @@ zero bytes.
161161
162162
.. c:function:: void* PyMem_RawCalloc(size_t nelem, size_t elsize)
163163
164-
Allocates *nelem* elements each whose size in bytes is *elsize* and returns
164+
Allocates *nelem* elements each of size *elsize* bytes and returns
165165
a pointer of type :c:expr:`void*` to the allocated memory, or ``NULL`` if the
166166
request fails. The memory is initialized to zeros.
167167
@@ -232,7 +232,7 @@ The :ref:`default memory allocator <default-memory-allocators>` uses the
232232
233233
.. c:function:: void* PyMem_Calloc(size_t nelem, size_t elsize)
234234
235-
Allocates *nelem* elements each whose size in bytes is *elsize* and returns
235+
Allocates *nelem* elements each of size *elsize* bytes and returns
236236
a pointer of type :c:expr:`void*` to the allocated memory, or ``NULL`` if the
237237
request fails. The memory is initialized to zeros.
238238
@@ -364,7 +364,7 @@ The :ref:`default object allocator <default-memory-allocators>` uses the
364364
365365
.. c:function:: void* PyObject_Calloc(size_t nelem, size_t elsize)
366366
367-
Allocates *nelem* elements each whose size in bytes is *elsize* and returns
367+
Allocates *nelem* elements each of size *elsize* bytes and returns
368368
a pointer of type :c:expr:`void*` to the allocated memory, or ``NULL`` if the
369369
request fails. The memory is initialized to zeros.
370370

Lib/test/test_exceptions.py

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

1665+
def test_oserror_reinit_leak(self):
1666+
# gh-150988: Check for memory leak when re-initializing OSError.
1667+
# Previously, setting OSError attributes in a subclass
1668+
# before calling super().__init__() leaked memory.
1669+
class LeakingOSError(OSError):
1670+
def __init__(self, code, message, filename, filename2):
1671+
self.strerror = message
1672+
self.filename = filename
1673+
self.filename2 = filename2
1674+
super().__init__(code, message, filename, None, filename2)
1675+
1676+
exc = LeakingOSError(1, "some message", "filename.py", "filename2.py")
1677+
exc.__init__(2, "another message", "filename3.py", "filename4.py")
1678+
16651679
def test_errno_ENOTDIR(self):
16661680
# Issue #12802: "not a directory" errors are ENOTDIR even on Windows
16671681
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
@@ -1846,10 +1846,10 @@ oserror_init(PyOSErrorObject *self, PyObject **p_args,
18461846
return -1;
18471847
}
18481848
else {
1849-
self->filename = Py_NewRef(filename);
1849+
Py_XSETREF(self->filename, Py_NewRef(filename));
18501850

18511851
if (filename2 && filename2 != Py_None) {
1852-
self->filename2 = Py_NewRef(filename2);
1852+
Py_XSETREF(self->filename2, Py_NewRef(filename2));
18531853
}
18541854

18551855
if (nargs >= 2 && nargs <= 5) {
@@ -1864,10 +1864,10 @@ oserror_init(PyOSErrorObject *self, PyObject **p_args,
18641864
}
18651865
}
18661866
}
1867-
self->myerrno = Py_XNewRef(myerrno);
1868-
self->strerror = Py_XNewRef(strerror);
1867+
Py_XSETREF(self->myerrno, Py_XNewRef(myerrno));
1868+
Py_XSETREF(self->strerror, Py_XNewRef(strerror));
18691869
#ifdef MS_WINDOWS
1870-
self->winerror = Py_XNewRef(winerror);
1870+
Py_XSETREF(self->winerror, Py_XNewRef(winerror));
18711871
#endif
18721872

18731873
/* Steals the reference to args */

0 commit comments

Comments
 (0)