From 967527448b77d3e2f6080ae0d741067787378d82 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Thu, 2 Jul 2026 08:02:52 +0000 Subject: [PATCH] gh-98417: Stop modifying PyConfig in sys.set_int_max_str_digits() PyConfig is an input to interpreter initialization; the copy stored on PyInterpreterState records how the interpreter was initialized. The runtime int<->str digit limit already lives in PyInterpreterState.long_state.max_str_digits and that is what all readers use, so drop the write-back into interp->config.int_max_str_digits from _PySys_SetIntMaxStrDigits(). As a consequence, interpreters created after a runtime limit change now start from the initially-configured limit instead of inheriting the current runtime value. Co-Authored-By: Claude Fable 5 --- Lib/test/test_int.py | 18 ++++++++++++++++++ ...26-07-02-06-15-00.gh-issue-98417.Qk3vXm.rst | 5 +++++ Python/sysmodule.c | 3 --- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-07-02-06-15-00.gh-issue-98417.Qk3vXm.rst diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py index fa675f626cbe109..5d5ef44ae163007 100644 --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -732,6 +732,24 @@ def test_int_max_str_digits_is_per_interpreter(self): after_value = sys.get_int_max_str_digits() self.assertEqual(before_value, after_value) + def test_int_max_str_digits_not_inherited_by_subinterpreter(self): + # gh-98417: sys.set_int_max_str_digits() changes runtime state + # only; it must not be written back into the interpreter's + # initialization config. Interpreters created afterwards start + # from the initial config, not the current runtime value. + sentinel = 99_999 + if sys.get_int_max_str_digits() == sentinel: + sentinel = 88_888 + code = f"""if 1: + import sys + if sys.get_int_max_str_digits() == {sentinel}: + raise AssertionError( + 'subinterpreter inherited a runtime limit change') + """ + with support.adjust_int_max_str_digits(sentinel): + self.assertEqual(support.run_in_subinterp(code), 0, + 'subinterp code failure, check stderr.') + class IntSubclassStrDigitLimitsTests(IntStrDigitLimitsTests): int_class = IntSubclass diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-07-02-06-15-00.gh-issue-98417.Qk3vXm.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-02-06-15-00.gh-issue-98417.Qk3vXm.rst new file mode 100644 index 000000000000000..29ea4fd046d344b --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-02-06-15-00.gh-issue-98417.Qk3vXm.rst @@ -0,0 +1,5 @@ +:func:`sys.set_int_max_str_digits` no longer writes the new limit back into +the interpreter's initialization configuration (:c:type:`PyConfig`). As a +consequence, interpreters created after changing the limit at runtime now +start with the initial configured limit rather than inheriting the runtime +value. diff --git a/Python/sysmodule.c b/Python/sysmodule.c index d9f7b9c449cfb94..f6d142290f954d6 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -4701,10 +4701,7 @@ _PySys_SetIntMaxStrDigits(int maxdigits) return -1; } - // Set PyInterpreterState.long_state.max_str_digits - // and PyInterpreterState.config.int_max_str_digits. PyInterpreterState *interp = _PyInterpreterState_GET(); _Py_atomic_store_int(&interp->long_state.max_str_digits, maxdigits); - _Py_atomic_store_int(&interp->config.int_max_str_digits, maxdigits); return 0; }