diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 709b434b067958..bdf134254121e5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -586,10 +586,10 @@ Lib/test/test_string/test_templatelib.py @lysnikolaou @AA-Turner **/*sysconfig* @FFY00 # SQLite 3 -Doc/library/sqlite3.rst @berkerpeksag @erlend-aasland -Lib/sqlite3/ @berkerpeksag @erlend-aasland -Lib/test/test_sqlite3/ @berkerpeksag @erlend-aasland -Modules/_sqlite/ @berkerpeksag @erlend-aasland +Doc/library/sqlite3.rst @erlend-aasland +Lib/sqlite3/ @erlend-aasland +Lib/test/test_sqlite3/ @erlend-aasland +Modules/_sqlite/ @erlend-aasland # Subprocess Lib/subprocess.py @gpshead @@ -622,9 +622,6 @@ Modules/_typesmodule.c @AA-Turner Lib/unittest/mock.py @cjw296 Lib/test/test_unittest/testmock/ @cjw296 -# Urllib -**/*robotparser* @berkerpeksag - # Venv **/*venv* @vsajip @FFY00 diff --git a/Doc/deprecations/pending-removal-in-3.16.rst b/Doc/deprecations/pending-removal-in-3.16.rst index 50450658d31440..7606daba16dcf8 100644 --- a/Doc/deprecations/pending-removal-in-3.16.rst +++ b/Doc/deprecations/pending-removal-in-3.16.rst @@ -89,7 +89,7 @@ Pending removal in Python 3.16 * :mod:`sys`: - * The :func:`~sys._enablelegacywindowsfsencoding` function + * The :func:`!_enablelegacywindowsfsencoding` function has been deprecated since Python 3.13. Use the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment variable instead. diff --git a/Doc/library/mimetypes.rst b/Doc/library/mimetypes.rst index 0facacd50fd389..eed9acb92e0c95 100644 --- a/Doc/library/mimetypes.rst +++ b/Doc/library/mimetypes.rst @@ -129,10 +129,18 @@ behavior of the module. Add a mapping from the MIME type *type* to the extension *ext*. When the extension is already known, the new type will replace the old one. When the type is already known the extension will be added to the list of known extensions. + Valid extensions are empty or start with a ``'.'``. When *strict* is ``True`` (the default), the mapping will be added to the official MIME types, otherwise to the non-standard ones. + .. deprecated:: 3.14 + *ext* values that do not start with ``'.'`` are deprecated. + + .. versionchanged:: next + *ext* now must start with ``'.'``. Otherwise :exc:`ValueError` is raised. + + .. data:: inited diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 6946eb6eeaa5fa..21de31383d425b 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -879,7 +879,7 @@ always available. Unless explicitly noted otherwise, all variables are read-only .. versionchanged:: 3.6 Windows is no longer guaranteed to return ``'mbcs'``. See :pep:`529` - and :func:`_enablelegacywindowsfsencoding` for more information. + for more information. .. versionchanged:: 3.7 Return ``'utf-8'`` if the :ref:`Python UTF-8 Mode ` is @@ -2107,31 +2107,6 @@ always available. Unless explicitly noted otherwise, all variables are read-only See :pep:`768` for more details. -.. function:: _enablelegacywindowsfsencoding() - - Changes the :term:`filesystem encoding and error handler` to 'mbcs' and - 'replace' respectively, for consistency with versions of Python prior to - 3.6. - - This is equivalent to defining the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` - environment variable before launching Python. - - See also :func:`sys.getfilesystemencoding` and - :func:`sys.getfilesystemencodeerrors`. - - .. availability:: Windows. - - .. note:: - Changing the filesystem encoding after Python startup is risky because - the old fsencoding or paths encoded by the old fsencoding may be cached - somewhere. Use :envvar:`PYTHONLEGACYWINDOWSFSENCODING` instead. - - .. versionadded:: 3.6 - See :pep:`529` for more details. - - .. deprecated-removed:: 3.13 3.16 - Use :envvar:`PYTHONLEGACYWINDOWSFSENCODING` instead. - .. data:: stdin stdout stderr diff --git a/Doc/tools/removed-ids.txt b/Doc/tools/removed-ids.txt index adac1b993047bc..ebcd1874e24b3f 100644 --- a/Doc/tools/removed-ids.txt +++ b/Doc/tools/removed-ids.txt @@ -7,4 +7,5 @@ c-api/file.html: deprecated-api library/asyncio-task.html: terminating-a-task-group # Removed APIs -library/symtable.html: symtable.Class.get_methods \ No newline at end of file +library/symtable.html: symtable.Class.get_methods +library/sys.html: sys._enablelegacywindowsfsencoding \ No newline at end of file diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 59e8f4f9f5a3e4..c4a431a471a546 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -1154,9 +1154,6 @@ conflict. 'replace', respectively. Otherwise, the new defaults 'utf-8' and 'surrogatepass' are used. - This may also be enabled at runtime with - :func:`sys._enablelegacywindowsfsencoding`. - .. availability:: Windows. .. versionadded:: 3.6 diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index de5a37042a9203..f09b5c90232e33 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -1958,7 +1958,7 @@ New Deprecations * :mod:`sys`: - * Deprecate the :func:`~sys._enablelegacywindowsfsencoding` function, + * Deprecate the :func:`!_enablelegacywindowsfsencoding` function, to be removed in Python 3.16. Use the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment variable instead. (Contributed by Inada Naoki in :gh:`73427`.) diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 6d91d53f478d8e..2db8866da60e0d 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -114,6 +114,13 @@ annotationlib Use :meth:`annotationlib.ForwardRef.evaluate` or :func:`typing.evaluate_forward_ref` instead. +asyncio +------- + +* The :func:`!asyncio.iscoroutinefunction` + which has been deprecated since Python 3.14. + Use :func:`inspect.iscoroutinefunction` instead. + functools --------- @@ -127,12 +134,27 @@ logging and scheduled for removal in Python 3.16. Define handlers with the *stream* argument instead. +mimetypes +--------- + +* Valid extensions start with a '.' or are empty for + :meth:`mimetypes.MimeTypes.add_type`. + Undotted extensions now raise a :exc:`ValueError`. + symtable -------- * The :meth:`!symtable.Class.get_methods` method which has been deprecated since Python 3.14. +sys +--- + +* The :func:`!_enablelegacywindowsfsencoding` function + which has been deprecated since Python 3.13. + Use the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment variable instead. + (Contributed by Stan Ulbrych in :gh:`149595`.) + sysconfig --------- diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index bdd35d39e36194..b0382dd8215bc0 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -517,7 +517,7 @@ Applications that do not use str to represent paths should use :func:`os.fsencode` and :func:`os.fsdecode` to ensure their bytes are correctly encoded. To revert to the previous behaviour, set :envvar:`PYTHONLEGACYWINDOWSFSENCODING` or call -:func:`sys._enablelegacywindowsfsencoding`. +:func:`!sys._enablelegacywindowsfsencoding`. See :pep:`529` for more information and discussion of code modifications that may be required. diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 8faf7a4d403f84..12e1e78526db35 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -18,9 +18,6 @@ extern int _Py_SetFileSystemEncoding( const char *errors); extern void _Py_ClearFileSystemEncoding(void); extern PyStatus _PyUnicode_InitEncodings(PyThreadState *tstate); -#ifdef MS_WINDOWS -extern int _PyUnicode_EnableLegacyWindowsFSEncoding(void); -#endif extern int _Py_IsLocaleCoercionTarget(const char *ctype_loc); diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 7a6837546d930f..1fedb066f94c53 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -31,6 +31,7 @@ import traceback import warnings import weakref +import inspect try: import ssl @@ -840,7 +841,7 @@ def call_soon(self, callback, *args, context=None): def _check_callback(self, callback, method): if (coroutines.iscoroutine(callback) or - coroutines._iscoroutinefunction(callback)): + inspect.iscoroutinefunction(callback)): raise TypeError( f"coroutines cannot be used with {method}()") if not callable(callback): diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index a51319cb72a6a9..bfffb6da4b19a1 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -1,4 +1,4 @@ -__all__ = 'iscoroutinefunction', 'iscoroutine' +__all__ = ('iscoroutine',) import collections.abc import inspect @@ -13,25 +13,6 @@ def _is_debug_mode(): bool(os.environ.get('PYTHONASYNCIODEBUG'))) -# A marker for iscoroutinefunction. -_is_coroutine = object() - - -def iscoroutinefunction(func): - import warnings - """Return True if func is a decorated coroutine function.""" - warnings._deprecated("asyncio.iscoroutinefunction", - f"{warnings._DEPRECATED_MSG}; " - "use inspect.iscoroutinefunction() instead", - remove=(3,16)) - return _iscoroutinefunction(func) - - -def _iscoroutinefunction(func): - return (inspect.iscoroutinefunction(func) or - getattr(func, '_is_coroutine', None) is _is_coroutine) - - # Prioritize native coroutine check to speed-up # asyncio.iscoroutine. _COROUTINE_TYPES = (types.CoroutineType, collections.abc.Coroutine) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 49e8067ee7b4e5..915ff845249151 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -12,6 +12,7 @@ import sys import threading import warnings +import inspect from . import base_events from . import base_subprocess @@ -94,7 +95,7 @@ def add_signal_handler(self, sig, callback, *args): Raise RuntimeError if there is a problem setting up the handler. """ if (coroutines.iscoroutine(callback) or - coroutines._iscoroutinefunction(callback)): + inspect.iscoroutinefunction(callback)): raise TypeError("coroutines cannot be used " "with add_signal_handler()") self._check_signal(sig) diff --git a/Lib/mimetypes.py b/Lib/mimetypes.py index 6d9278bccf927e..15e8c0a437bfd9 100644 --- a/Lib/mimetypes.py +++ b/Lib/mimetypes.py @@ -93,14 +93,7 @@ def add_type(self, type, ext, strict=True): Valid extensions are empty or start with a '.'. """ if ext and not ext.startswith('.'): - from warnings import _deprecated - - _deprecated( - "Undotted extensions", - "Using undotted extensions is deprecated and " - "will raise a ValueError in Python {remove}", - remove=(3, 16), - ) + raise ValueError(f"Extension {ext!r} must start with '.'") if not type: return diff --git a/Lib/test/test_asyncio/test_graph.py b/Lib/test/test_asyncio/test_graph.py index 2f22fbccba42bc..cffb2b30ad9cff 100644 --- a/Lib/test/test_asyncio/test_graph.py +++ b/Lib/test/test_asyncio/test_graph.py @@ -1,6 +1,7 @@ import asyncio import io import unittest +from unittest import mock # To prevent a warning "test altered the execution environment" @@ -345,6 +346,139 @@ async def main(): self.assertTrue(stack_for_fut[1].startswith('* Future(id=')) + async def test_capture_call_graph_positive_limit(self): + captured = None + + async def c3(): + nonlocal captured + captured = asyncio.capture_call_graph(limit=2) + + async def c2(): + await c3() + + async def c1(): + await c2() + + await c1() + self.assertEqual(len(captured.call_stack), 2) + + async def test_capture_call_graph_negative_limit(self): + captured = None + + async def c3(): + nonlocal captured + captured = asyncio.capture_call_graph(limit=-2) + + async def c2(): + await c3() + + async def c1(): + await c2() + + await c1() + self.assertEqual(len(captured.call_stack), 2) + + async def test_capture_call_graph_zero_limit(self): + captured = None + + async def inner(): + nonlocal captured + captured = asyncio.capture_call_graph(limit=0) + + await inner() + self.assertEqual(captured.call_stack, ()) + + def test_capture_call_graph_outside_loop(self): + with self.assertRaises(RuntimeError): + asyncio.capture_call_graph() + + def test_capture_call_graph_non_future(self): + with self.assertRaises(TypeError): + asyncio.capture_call_graph("not a future") + + async def test_capture_call_graph_no_current_task(self): + results = [] + + def cb(): + results.append(asyncio.capture_call_graph()) + results.append(asyncio.format_call_graph()) + + loop = asyncio.get_running_loop() + loop.call_soon(cb) + await asyncio.sleep(0) + + self.assertEqual(results, [None, ""]) + + async def test_capture_call_graph_current_task_not_future(self): + sentinel = object() + with mock.patch('asyncio.tasks.current_task', return_value=sentinel): + with self.assertRaises(TypeError): + asyncio.capture_call_graph(sentinel) + + async def test_build_graph_for_future_positive_limit(self): + fut = asyncio.Future() + captured = None + + async def deep(): + await fut + + async def mid(): + await deep() + + async def runner(): + await mid() + + async def main(): + nonlocal captured + async with asyncio.TaskGroup() as g: + t = g.create_task(runner(), name='runner') + for _ in range(5): + await asyncio.sleep(0) + captured = asyncio.capture_call_graph(t, limit=2) + fut.set_result(None) + + await main() + self.assertEqual(len(captured.call_stack), 2) + + async def test_build_graph_for_future_negative_limit(self): + fut = asyncio.Future() + captured = None + + async def deep(): + await fut + + async def mid(): + await deep() + + async def runner(): + await mid() + + async def main(): + nonlocal captured + async with asyncio.TaskGroup() as g: + t = g.create_task(runner(), name='runner') + for _ in range(5): + await asyncio.sleep(0) + captured = asyncio.capture_call_graph(t, limit=-2) + fut.set_result(None) + + await main() + self.assertEqual(len(captured.call_stack), 2) + + async def test_format_call_graph_regular_generator(self): + output = [] + + def gen(): + output.append(asyncio.format_call_graph()) + yield + + async def main(): + for _ in gen(): + pass + + await main() + self.assertRegex(output[0], r'in generator [\w.<>]+\.gen\(\)') + @unittest.skipIf( not hasattr(asyncio.futures, "_c_future_add_to_awaited_by"), diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py index a0c8434c9457d2..95a9f3a9a7cf71 100644 --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -124,11 +124,6 @@ def foo(): yield self.assertFalse(asyncio.iscoroutine(foo())) - def test_iscoroutinefunction(self): - async def foo(): pass - with self.assertWarns(DeprecationWarning): - self.assertTrue(asyncio.iscoroutinefunction(foo)) - def test_async_def_coroutines(self): async def bar(): return 'spam' diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index dc179acd86e8a6..56b1494c8363ca 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -11,6 +11,7 @@ import traceback import types import unittest +import inspect from unittest import mock from types import GenericAlias @@ -20,7 +21,6 @@ from test.test_asyncio import utils as test_utils from test import support from test.support.script_helper import assert_python_ok -from test.support.warnings_helper import ignore_warnings def tearDownModule(): @@ -1940,30 +1940,11 @@ async def notmutch(): self.assertFalse(task.cancelled()) self.assertIs(task.exception(), base_exc) - @ignore_warnings(category=DeprecationWarning) - def test_iscoroutinefunction(self): - def fn(): - pass - - self.assertFalse(asyncio.iscoroutinefunction(fn)) - - def fn1(): - yield - self.assertFalse(asyncio.iscoroutinefunction(fn1)) - - async def fn2(): - pass - self.assertTrue(asyncio.iscoroutinefunction(fn2)) - - self.assertFalse(asyncio.iscoroutinefunction(mock.Mock())) - self.assertTrue(asyncio.iscoroutinefunction(mock.AsyncMock())) - - @ignore_warnings(category=DeprecationWarning) def test_coroutine_non_gen_function(self): async def func(): return 'test' - self.assertTrue(asyncio.iscoroutinefunction(func)) + self.assertTrue(inspect.iscoroutinefunction(func)) coro = func() self.assertTrue(asyncio.iscoroutine(coro)) diff --git a/Lib/test/test_mimetypes.py b/Lib/test/test_mimetypes.py index 2d618081521e10..607aff8418edcf 100644 --- a/Lib/test/test_mimetypes.py +++ b/Lib/test/test_mimetypes.py @@ -389,9 +389,12 @@ def test_added_types_are_used(self): mime_type, _ = mimetypes.guess_type('test.myext') self.assertEqual(mime_type, 'testing/type') - def test_add_type_with_undotted_extension_deprecated(self): - with self.assertWarns(DeprecationWarning): + def test_add_type_with_undotted_extension_not_supported(self): + msg = "Extension 'undotted' must start with '.'" + with self.assertRaisesRegex(ValueError, msg): mimetypes.add_type("testing/type", "undotted") + with self.assertRaisesRegex(ValueError, msg): + mimetypes.add_type("", "undotted") @unittest.skipUnless(sys.platform.startswith("win"), "Windows only") diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 3002fa528eab17..02c70403185f60 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1283,16 +1283,6 @@ def check(tracebacklimit, expected): def test_no_duplicates_in_meta_path(self): self.assertEqual(len(sys.meta_path), len(set(sys.meta_path))) - @unittest.skipUnless(hasattr(sys, "_enablelegacywindowsfsencoding"), - 'needs sys._enablelegacywindowsfsencoding()') - def test__enablelegacywindowsfsencoding(self): - code = ('import sys', - 'sys._enablelegacywindowsfsencoding()', - 'print(sys.getfilesystemencoding(), sys.getfilesystemencodeerrors())') - rc, out, err = assert_python_ok('-c', '; '.join(code)) - out = out.decode('ascii', 'replace').rstrip() - self.assertEqual(out, 'mbcs replace') - @support.requires_subprocess() def test_orig_argv(self): code = textwrap.dedent(''' diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 1cee67fa5d7094..16f3699e89e77d 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -281,7 +281,6 @@ def reset_mock(): def _setup_async_mock(mock): - mock._is_coroutine = asyncio.coroutines._is_coroutine mock.await_count = 0 mock.await_args = None mock.await_args_list = _CallList() @@ -2287,13 +2286,6 @@ class AsyncMockMixin(Base): def __init__(self, /, *args, **kwargs): super().__init__(*args, **kwargs) - # iscoroutinefunction() checks _is_coroutine property to say if an - # object is a coroutine. Without this check it looks to see if it is a - # function/method, which in this case it is not (since it is an - # AsyncMock). - # It is set through __dict__ because when spec_set is True, this - # attribute is likely undefined. - self.__dict__['_is_coroutine'] = asyncio.coroutines._is_coroutine self.__dict__['_mock_await_count'] = 0 self.__dict__['_mock_await_args'] = None self.__dict__['_mock_await_args_list'] = _CallList() diff --git a/Misc/NEWS.d/3.13.0a3.rst b/Misc/NEWS.d/3.13.0a3.rst index 0f8dee261c6589..3d3b414c9d46af 100644 --- a/Misc/NEWS.d/3.13.0a3.rst +++ b/Misc/NEWS.d/3.13.0a3.rst @@ -2166,7 +2166,7 @@ current user has no permission to the WMI. .. nonce: WOpiNt .. section: Windows -Deprecate :func:`sys._enablelegacywindowsfsencoding`. Use +Deprecate :func:`!sys._enablelegacywindowsfsencoding`. Use :envvar:`PYTHONLEGACYWINDOWSFSENCODING` instead. Patch by Inada Naoki. .. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-05-12-16-47-23.gh-issue-139808.iIs7_E.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-12-16-47-23.gh-issue-139808.iIs7_E.rst new file mode 100644 index 00000000000000..3e9d930bf1de89 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-12-16-47-23.gh-issue-139808.iIs7_E.rst @@ -0,0 +1,2 @@ +Add branch protections for AArch64 (BTI/PAC) in assembly code used by +:option:`-X perf_jit <-X>` (Linux perf profiler integration). diff --git a/Misc/NEWS.d/next/Library/2026-05-09-11-22-29.gh-issue-149595.1nuYXw.rst b/Misc/NEWS.d/next/Library/2026-05-09-11-22-29.gh-issue-149595.1nuYXw.rst new file mode 100644 index 00000000000000..f3971554de3748 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-09-11-22-29.gh-issue-149595.1nuYXw.rst @@ -0,0 +1,2 @@ +Remove the :func:`!sys._enablelegacywindowsfsencoding` function which has +been deprecated since Python 3.13. diff --git a/Misc/NEWS.d/next/Library/2026-05-09-15-42-54.gh-issue-149600.ZbL-iv.rst b/Misc/NEWS.d/next/Library/2026-05-09-15-42-54.gh-issue-149600.ZbL-iv.rst new file mode 100644 index 00000000000000..732787dc92c109 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-09-15-42-54.gh-issue-149600.ZbL-iv.rst @@ -0,0 +1 @@ +Remove deprecated :func:`!asyncio.iscoroutinefunction` function. diff --git a/Misc/NEWS.d/next/Library/2026-05-12-14-44-39.gh-issue-149720.ccsoW-.rst b/Misc/NEWS.d/next/Library/2026-05-12-14-44-39.gh-issue-149720.ccsoW-.rst new file mode 100644 index 00000000000000..f16d8770d740f4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-12-14-44-39.gh-issue-149720.ccsoW-.rst @@ -0,0 +1 @@ +Remove support for undotted *ext* in :meth:`mimetypes.MimeTypes.add_type`. diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 238e17bea303d3..a2506524f0bb6d 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -7946,8 +7946,9 @@ assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); #if TIER_ONE && defined(Py_DEBUG) if (!PyStackRef_IsNone(frame->f_executable)) { - int i = frame->instr_ptr - _PyFrame_GetBytecode(frame); - int opcode = _Py_GetBaseCodeUnit(_PyFrame_GetCode(frame), i).op.code; + Py_ssize_t i = frame->instr_ptr - _PyFrame_GetBytecode(frame); + assert(i >= 0 && i <= INT_MAX); + int opcode = _Py_GetBaseCodeUnit(_PyFrame_GetCode(frame), (int)i).op.code; assert(opcode == SEND || opcode == FOR_ITER); } #endif @@ -13056,8 +13057,9 @@ assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); #if TIER_ONE && defined(Py_DEBUG) if (!PyStackRef_IsNone(frame->f_executable)) { - int i = frame->instr_ptr - _PyFrame_GetBytecode(frame); - int opcode = _Py_GetBaseCodeUnit(_PyFrame_GetCode(frame), i).op.code; + Py_ssize_t i = frame->instr_ptr - _PyFrame_GetBytecode(frame); + assert(i >= 0 && i <= INT_MAX); + int opcode = _Py_GetBaseCodeUnit(_PyFrame_GetCode(frame), (int)i).op.code; assert(opcode == SEND || opcode == FOR_ITER); } #endif diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 5c97efd6838ef3..b92743a884a708 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -14928,33 +14928,6 @@ _PyUnicode_FiniEncodings(struct _Py_unicode_fs_codec *fs_codec) } -#ifdef MS_WINDOWS -int -_PyUnicode_EnableLegacyWindowsFSEncoding(void) -{ - PyInterpreterState *interp = _PyInterpreterState_GET(); - PyConfig *config = (PyConfig *)_PyInterpreterState_GetConfig(interp); - - /* Set the filesystem encoding to mbcs/replace (PEP 529) */ - wchar_t *encoding = _PyMem_RawWcsdup(L"mbcs"); - wchar_t *errors = _PyMem_RawWcsdup(L"replace"); - if (encoding == NULL || errors == NULL) { - PyMem_RawFree(encoding); - PyMem_RawFree(errors); - PyErr_NoMemory(); - return -1; - } - - PyMem_RawFree(config->filesystem_encoding); - config->filesystem_encoding = encoding; - PyMem_RawFree(config->filesystem_errors); - config->filesystem_errors = errors; - - return init_fs_codec(interp); -} -#endif - - #ifdef Py_DEBUG static inline int unicode_is_finalizing(void) diff --git a/Python/asm_trampoline.S b/Python/asm_trampoline.S index 93adae3d99038f..9f3ca909ab7d85 100644 --- a/Python/asm_trampoline.S +++ b/Python/asm_trampoline.S @@ -1,3 +1,5 @@ +#include "asm_trampoline_aarch64.h" + .text #if defined(__APPLE__) .globl __Py_trampoline_func_start @@ -29,10 +31,12 @@ _Py_trampoline_func_start: #if defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__) // ARM64 little endian, 64bit ABI // generate with aarch64-linux-gnu-gcc 12.1 + SIGN_LR stp x29, x30, [sp, -16]! mov x29, sp blr x3 ldp x29, x30, [sp], 16 + VERIFY_LR ret #endif #ifdef __riscv diff --git a/Python/asm_trampoline_aarch64.h b/Python/asm_trampoline_aarch64.h new file mode 100644 index 00000000000000..bc83aa460b6860 --- /dev/null +++ b/Python/asm_trampoline_aarch64.h @@ -0,0 +1,56 @@ +#ifndef ASM_TRAMPOLINE_AARCH_64_H_ +#define ASM_TRAMPOLINE_AARCH_64_H_ + +/* + * References: + * - https://developer.arm.com/documentation/101028/0012/5--Feature-test-macros + * - https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst + */ + +#if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1 + #define BTI_J hint 36 /* bti j: for jumps, IE br instructions */ + #define BTI_C hint 34 /* bti c: for calls, IE bl instructions */ + #define GNU_PROPERTY_AARCH64_BTI 1 /* bit 0 GNU Notes is for BTI support */ +#else + #define BTI_J + #define BTI_C + #define GNU_PROPERTY_AARCH64_BTI 0 +#endif + +#if defined(__ARM_FEATURE_PAC_DEFAULT) + #if __ARM_FEATURE_PAC_DEFAULT & 1 + #define SIGN_LR hint 25 /* paciasp: sign with the A key */ + #define VERIFY_LR hint 29 /* autiasp: verify with the A key */ + #elif __ARM_FEATURE_PAC_DEFAULT & 2 + #define SIGN_LR hint 27 /* pacibsp: sign with the b key */ + #define VERIFY_LR hint 31 /* autibsp: verify with the b key */ + #endif + #define GNU_PROPERTY_AARCH64_POINTER_AUTH 2 /* bit 1 GNU Notes is for PAC support */ +#else + #define SIGN_LR BTI_C + #define VERIFY_LR + #define GNU_PROPERTY_AARCH64_POINTER_AUTH 0 +#endif + +#if defined(__ARM_FEATURE_GCS_DEFAULT) && __ARM_FEATURE_GCS_DEFAULT == 1 + #define GNU_PROPERTY_AARCH64_GCS 4 /* bit 2 GNU Notes is for GCS support */ +#else + #define GNU_PROPERTY_AARCH64_GCS 0 +#endif + +/* Add the BTI, PAC and GCS support to GNU Notes section */ +#if GNU_PROPERTY_AARCH64_BTI != 0 || GNU_PROPERTY_AARCH64_POINTER_AUTH != 0 || GNU_PROPERTY_AARCH64_GCS != 0 + .pushsection .note.gnu.property, "a"; /* Start a new allocatable section */ + .balign 8; /* align it on a byte boundry */ + .long 4; /* size of "GNU\0" */ + .long 0x10; /* size of descriptor */ + .long 0x5; /* NT_GNU_PROPERTY_TYPE_0 */ + .asciz "GNU"; + .long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ + .long 4; /* Four bytes of data */ + .long (GNU_PROPERTY_AARCH64_BTI|GNU_PROPERTY_AARCH64_POINTER_AUTH|GNU_PROPERTY_AARCH64_GCS); /* BTI, PAC or GCS is enabled */ + .long 0; /* padding for 8 byte alignment */ + .popsection; /* end the section */ +#endif + +#endif diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 3bd489122da9d4..f7487c7136962f 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1867,8 +1867,9 @@ dummy_func( assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); #if TIER_ONE && defined(Py_DEBUG) if (!PyStackRef_IsNone(frame->f_executable)) { - int i = frame->instr_ptr - _PyFrame_GetBytecode(frame); - int opcode = _Py_GetBaseCodeUnit(_PyFrame_GetCode(frame), i).op.code; + Py_ssize_t i = frame->instr_ptr - _PyFrame_GetBytecode(frame); + assert(i >= 0 && i <= INT_MAX); + int opcode = _Py_GetBaseCodeUnit(_PyFrame_GetCode(frame), (int)i).op.code; assert(opcode == SEND || opcode == FOR_ITER); } #endif diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index 86e942ec2b8afb..6609a88c1a9d58 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -761,34 +761,6 @@ sys_getwindowsversion(PyObject *module, PyObject *Py_UNUSED(ignored)) #endif /* defined(MS_WINDOWS) */ -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(sys__enablelegacywindowsfsencoding__doc__, -"_enablelegacywindowsfsencoding($module, /)\n" -"--\n" -"\n" -"Changes the default filesystem encoding to mbcs:replace.\n" -"\n" -"This is done for consistency with earlier versions of Python. See PEP\n" -"529 for more information.\n" -"\n" -"This is equivalent to defining the PYTHONLEGACYWINDOWSFSENCODING\n" -"environment variable before launching Python."); - -#define SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF \ - {"_enablelegacywindowsfsencoding", (PyCFunction)sys__enablelegacywindowsfsencoding, METH_NOARGS, sys__enablelegacywindowsfsencoding__doc__}, - -static PyObject * -sys__enablelegacywindowsfsencoding_impl(PyObject *module); - -static PyObject * -sys__enablelegacywindowsfsencoding(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return sys__enablelegacywindowsfsencoding_impl(module); -} - -#endif /* defined(MS_WINDOWS) */ - #if defined(HAVE_DLOPEN) PyDoc_STRVAR(sys_setdlopenflags__doc__, @@ -2082,10 +2054,6 @@ _jit_is_active(PyObject *module, PyObject *Py_UNUSED(ignored)) #define SYS_GETWINDOWSVERSION_METHODDEF #endif /* !defined(SYS_GETWINDOWSVERSION_METHODDEF) */ -#ifndef SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF - #define SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF -#endif /* !defined(SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF) */ - #ifndef SYS_SETDLOPENFLAGS_METHODDEF #define SYS_SETDLOPENFLAGS_METHODDEF #endif /* !defined(SYS_SETDLOPENFLAGS_METHODDEF) */ @@ -2121,4 +2089,4 @@ _jit_is_active(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=e8333fe10c01ae66 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ba849b6e4b9f1ba3 input=a9049054013a1b77]*/ diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index b6a2821db3007e..efa61d7de74e88 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -9346,8 +9346,9 @@ assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); #if TIER_ONE && defined(Py_DEBUG) if (!PyStackRef_IsNone(frame->f_executable)) { - int i = frame->instr_ptr - _PyFrame_GetBytecode(frame); - int opcode = _Py_GetBaseCodeUnit(_PyFrame_GetCode(frame), i).op.code; + Py_ssize_t i = frame->instr_ptr - _PyFrame_GetBytecode(frame); + assert(i >= 0 && i <= INT_MAX); + int opcode = _Py_GetBaseCodeUnit(_PyFrame_GetCode(frame), (int)i).op.code; assert(opcode == SEND || opcode == FOR_ITER); } #endif diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 2623105656c90c..53e09a8f4523c7 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -7945,8 +7945,9 @@ assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); #if TIER_ONE && defined(Py_DEBUG) if (!PyStackRef_IsNone(frame->f_executable)) { - int i = frame->instr_ptr - _PyFrame_GetBytecode(frame); - int opcode = _Py_GetBaseCodeUnit(_PyFrame_GetCode(frame), i).op.code; + Py_ssize_t i = frame->instr_ptr - _PyFrame_GetBytecode(frame); + assert(i >= 0 && i <= INT_MAX); + int opcode = _Py_GetBaseCodeUnit(_PyFrame_GetCode(frame), (int)i).op.code; assert(opcode == SEND || opcode == FOR_ITER); } #endif @@ -13053,8 +13054,9 @@ assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); #if TIER_ONE && defined(Py_DEBUG) if (!PyStackRef_IsNone(frame->f_executable)) { - int i = frame->instr_ptr - _PyFrame_GetBytecode(frame); - int opcode = _Py_GetBaseCodeUnit(_PyFrame_GetCode(frame), i).op.code; + Py_ssize_t i = frame->instr_ptr - _PyFrame_GetBytecode(frame); + assert(i >= 0 && i <= INT_MAX); + int opcode = _Py_GetBaseCodeUnit(_PyFrame_GetCode(frame), (int)i).op.code; assert(opcode == SEND || opcode == FOR_ITER); } #endif diff --git a/Python/jit_unwind.c b/Python/jit_unwind.c index 646106f0a9655c..0941ed593ff7d1 100644 --- a/Python/jit_unwind.c +++ b/Python/jit_unwind.c @@ -60,6 +60,9 @@ enum { DWRF_CFA_offset_extended_sf = 0x11, // Extended signed offset DWRF_CFA_advance_loc = 0x40, // Advance location counter DWRF_CFA_offset = 0x80, // Simple offset instruction +#if defined(__aarch64__) + DWRF_CFA_AARCH64_negate_ra_state = 0x2d, // Toggle return address signing state +#endif DWRF_CFA_restore = 0xc0 // Restore register }; @@ -562,6 +565,13 @@ static void elf_init_ehframe_perf(ELFObjectContext* ctx) { DWRF_UV(8); // New offset: SP + 8 #elif defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__) /* AArch64 calling convention unwinding rules */ +#if defined(__ARM_FEATURE_PAC_DEFAULT) || \ + (defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1) + DWRF_U8(DWRF_CFA_advance_loc | 1); // Advance past SIGN_LR (4 bytes) +#endif +#if defined(__ARM_FEATURE_PAC_DEFAULT) + DWRF_U8(DWRF_CFA_AARCH64_negate_ra_state); // Saved LR is PAC-signed from here +#endif DWRF_U8(DWRF_CFA_advance_loc | 1); // Advance by 1 instruction (4 bytes) DWRF_U8(DWRF_CFA_def_cfa_offset); // CFA = SP + 16 DWRF_UV(16); // Stack pointer moved by 16 bytes @@ -570,6 +580,9 @@ static void elf_init_ehframe_perf(ELFObjectContext* ctx) { DWRF_U8(DWRF_CFA_offset | DWRF_REG_RA); // x30 (link register) saved DWRF_UV(1); // At CFA-8 (1 * 8 = 8 bytes from CFA) DWRF_U8(DWRF_CFA_advance_loc | 3); // Advance by 3 instructions (12 bytes) +#if defined(__ARM_FEATURE_PAC_DEFAULT) + DWRF_U8(DWRF_CFA_AARCH64_negate_ra_state); // LR is authenticated, no longer PAC-signed +#endif DWRF_U8(DWRF_CFA_def_cfa_register); // CFA = FP (x29) + 16 DWRF_UV(DWRF_REG_FP); DWRF_U8(DWRF_CFA_restore | DWRF_REG_RA); // Restore x30 - NO DWRF_UV() after this! diff --git a/Python/sysmodule.c b/Python/sysmodule.c index c6447d03369a94..b75d9e864a18dc 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1790,36 +1790,6 @@ sys_getwindowsversion_impl(PyObject *module) } #pragma warning(pop) - -/*[clinic input] -sys._enablelegacywindowsfsencoding - -Changes the default filesystem encoding to mbcs:replace. - -This is done for consistency with earlier versions of Python. See PEP -529 for more information. - -This is equivalent to defining the PYTHONLEGACYWINDOWSFSENCODING -environment variable before launching Python. -[clinic start generated code]*/ - -static PyObject * -sys__enablelegacywindowsfsencoding_impl(PyObject *module) -/*[clinic end generated code: output=f5c3855b45e24fe9 input=2bfa931a20704492]*/ -{ - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "sys._enablelegacywindowsfsencoding() is deprecated and will be " - "removed in Python 3.16. Use PYTHONLEGACYWINDOWSFSENCODING " - "instead.", 1)) - { - return NULL; - } - if (_PyUnicode_EnableLegacyWindowsFSEncoding() < 0) { - return NULL; - } - Py_RETURN_NONE; -} - #endif /* MS_WINDOWS */ #ifdef HAVE_DLOPEN @@ -2941,7 +2911,6 @@ static PyMethodDef sys_methods[] = { SYS__GETFRAME_METHODDEF SYS__GETFRAMEMODULENAME_METHODDEF SYS_GETWINDOWSVERSION_METHODDEF - SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF SYS__IS_IMMORTAL_METHODDEF SYS_INTERN_METHODDEF SYS__IS_INTERNED_METHODDEF @@ -3436,13 +3405,6 @@ winver -- [Windows only] version number of the Python DLL\n\ " ) #endif /* MS_COREDLL */ -#ifdef MS_WINDOWS -/* concatenating string here */ -PyDoc_STR( -"_enablelegacywindowsfsencoding -- [Windows only]\n\ -" -) -#endif PyDoc_STR( "__stdin__ -- the original stdin; don't touch!\n\ __stdout__ -- the original stdout; don't touch!\n\