Skip to content

Commit ed09466

Browse files
Add documentation
1 parent fd9c7ff commit ed09466

File tree

3 files changed

+42
-6
lines changed

3 files changed

+42
-6
lines changed

Doc/c-api/init.rst

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -386,11 +386,15 @@ Initializing and finalizing the interpreter
386386
Undo all initializations made by :c:func:`Py_Initialize` and subsequent use of
387387
Python/C API functions, and destroy all sub-interpreters (see
388388
:c:func:`Py_NewInterpreter` below) that were created and not yet destroyed since
389-
the last call to :c:func:`Py_Initialize`. Ideally, this frees all memory
390-
allocated by the Python interpreter. This is a no-op when called for a second
389+
the last call to :c:func:`Py_Initialize`. This is a no-op when called for a second
391390
time (without calling :c:func:`Py_Initialize` again first). Normally the
392391
return value is ``0``. If there were errors during finalization
393392
(flushing buffered data), ``-1`` is returned.
393+
394+
Note that Python will do a best effort at freeing all memory allocated by the Python
395+
interpreter. Therefore, any C-Extension should make sure to correctly clean up all
396+
of the preveiously allocated PyObjects before using them in subsequent calls to
397+
`Py_Initialize`. Otherwise it introduces vulnerabilities and incorrect behavior.
394398
395399
This function is provided for a number of reasons. An embedding application
396400
might want to restart Python without having to restart the application itself.
@@ -406,10 +410,11 @@ Initializing and finalizing the interpreter
406410
loaded extension modules loaded by Python are not unloaded. Small amounts of
407411
memory allocated by the Python interpreter may not be freed (if you find a leak,
408412
please report it). Memory tied up in circular references between objects is not
409-
freed. Some memory allocated by extension modules may not be freed. Some
410-
extensions may not work properly if their initialization routine is called more
411-
than once; this can happen if an application calls :c:func:`Py_Initialize` and
412-
:c:func:`Py_FinalizeEx` more than once.
413+
freed. Interned strings will all be deallocated regarldess of their reference count.
414+
Some memory allocated by extension modules may not be freed. Some extensions may not
415+
work properly if their initialization routine is called more than once; this can
416+
happen if an application calls :c:func:`Py_Initialize` and :c:func:`Py_FinalizeEx`
417+
more than once.
413418

414419
.. audit-event:: cpython._PySys_ClearAuditHooks "" c.Py_FinalizeEx
415420

Doc/whatsnew/3.13.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,17 @@ New Features
13631363
* Add :c:func:`Py_HashPointer` function to hash a pointer.
13641364
(Contributed by Victor Stinner in :gh:`111545`.)
13651365

1366+
* Modified :c:func:`_PyUnicode_ClearInterned` function to always delete all
1367+
interned strings during a call to :c:func:`Py_Finalize`. This makes all
1368+
is backwards incompatible to any C-Extension that holds onto an interned
1369+
string after a call to c:func:`Py_Finalize` and is then reused after a
1370+
call to c:func:`Py_Initialize`. Any issues arising from this behavior will
1371+
normally result in crashes during the exectuion of the subsequent call to
1372+
c:func:`Py_Initatilize` from accessing uninitialized memory. To fix, use
1373+
an address sanitizer (i.e. ASAN) to identify any use-after-free coming from
1374+
an interned string and deallocate it during module shutdown.
1375+
(Contribued by Eddie Elizondo in :gh:`113601`.)
1376+
13661377

13671378
Porting to Python 3.13
13681379
----------------------
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
This updates the interned string deallocation function
2+
`_PyUnicode_ClearInterned` to delete all interned strings during runtime
3+
finalization when calling `Py_Finalize`, regardless of their reference
4+
count.
5+
6+
Worth noting that if an extension accidentally holds onto a interned string,
7+
event after calling Py_Finalize, it will result in use-after-free error,
8+
leaving the user to a potential vulnerabilities. That said, the history of
9+
how these interned strings are handled have been changing during throughout
10+
different versions. For example:
11+
12+
* In Python 3.9 and older, interned strings were never deleted. Only special
13+
build for Valgrind and Purity cleared them at exit
14+
* In Python 3.10 and 3.11, interned strings are always deleted at exit
15+
* In Python 3.12, interned strings are deleted only if Python is built in
16+
debug mode: they are not deleted in release mode
17+
* In Python 3.13, interned strings will now be akll deleted
18+
19+
Given how we've changed guarantees throughout different versions, we do not
20+
expect that users actively rely on this behavior for their extensions.

0 commit comments

Comments
 (0)