@@ -584,6 +584,13 @@ class`. float also has the following additional methods.
584584 :exc: `OverflowError ` on infinities and a :exc: `ValueError ` on
585585 NaNs.
586586
587+ .. note ::
588+
589+ The values returned by ``as_integer_ratio() `` can be huge. Attempts
590+ to render such integers into decimal strings may bump into the
591+ :ref: `integer string conversion length limitation
592+ <int_max_str_digits>`.
593+
587594.. method :: float.is_integer()
588595
589596 Return ``True `` if the float instance is finite with integral
@@ -5406,6 +5413,165 @@ types, where they are relevant. Some of these are not reported by the
54065413 [<class 'bool'>]
54075414
54085415
5416+ .. _int_max_str_digits :
5417+
5418+ Integer string conversion length limitation
5419+ ===========================================
5420+
5421+ CPython has a global limit for converting between :class: `int ` and :class: `str `
5422+ to mitigate denial of service attacks. This limit *only * applies to decimal or
5423+ other non-power-of-two number bases. Hexadecimal, octal, and binary conversions
5424+ are unlimited. The limit can be configured.
5425+
5426+ The :class: `int ` type in CPython is an abitrary length number stored in binary
5427+ form (commonly known as a "bignum"). There exists no algorithm that can convert
5428+ a string to a binary integer or a binary integer to a string in linear time,
5429+ *unless * the base is a power of 2. Even the best known algorithms for base 10
5430+ have sub-quadratic complexity. Converting a large value such as ``int('1' *
5431+ 500_000) `` can take over a second on a fast CPU.
5432+
5433+ Limiting conversion size offers a practical way to avoid `CVE-2020-10735
5434+ <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10735> `_.
5435+
5436+ The limit is applied to the number of digit characters in the input or output
5437+ string when a non-linear conversion algorithm would be involved. Underscores
5438+ and the sign are not counted towards the limit.
5439+
5440+ When an operation would exceed the limit, a :exc: `ValueError ` is raised:
5441+
5442+ .. doctest ::
5443+
5444+ >>> import sys
5445+ >>> sys.set_int_max_str_digits(4300 ) # Illustrative, this is the default.
5446+ >>> _ = int (' 2' * 5432 )
5447+ Traceback (most recent call last):
5448+ ...
5449+ ValueError: Exceeds the limit (4300) for integer string conversion: value has 5432 digits.
5450+ >>> i = int (' 2' * 4300 )
5451+ >>> len (str (i))
5452+ 4300
5453+ >>> i_squared = i* i
5454+ >>> len (str (i_squared))
5455+ Traceback (most recent call last):
5456+ ...
5457+ ValueError: Exceeds the limit (4300) for integer string conversion: value has 8599 digits.
5458+ >>> len (hex (i_squared))
5459+ 7144
5460+ >>> assert int (hex (i_squared), base = 16 ) == i* i # Hexadecimal is unlimited.
5461+
5462+ The default limit is 4300 digits as provided in
5463+ :data: `sys.int_info.default_max_str_digits <sys.int_info> `.
5464+ The lowest limit that can be configured is 640 digits as provided in
5465+ :data: `sys.int_info.str_digits_check_threshold <sys.int_info> `.
5466+
5467+ Verification:
5468+
5469+ .. doctest ::
5470+
5471+ >>> import sys
5472+ >>> assert sys.int_info.default_max_str_digits == 4300 , sys.int_info
5473+ >>> assert sys.int_info.str_digits_check_threshold == 640 , sys.int_info
5474+ >>> msg = int (' 578966293710682886880994035146873798396722250538762761564'
5475+ ... ' 9252925514383915483333812743580549779436104706260696366600'
5476+ ... ' 571186405732' ).to_bytes(53 , ' big' )
5477+ ...
5478+
5479+ .. versionadded :: 3.10.7
5480+
5481+ Affected APIs
5482+ -------------
5483+
5484+ The limition only applies to potentially slow conversions between :class: `int `
5485+ and :class: `str ` or :class: `bytes `:
5486+
5487+ * ``int(string) `` with default base 10.
5488+ * ``int(string, base) `` for all bases that are not a power of 2.
5489+ * ``str(integer) ``.
5490+ * ``repr(integer) ``
5491+ * any other string conversion to base 10, for example ``f"{integer}" ``,
5492+ ``"{}".format(integer) ``, or ``b"%d" % integer ``.
5493+
5494+ The limitations do not apply to functions with a linear algorithm:
5495+
5496+ * ``int(string, base) `` with base 2, 4, 8, 16, or 32.
5497+ * :func: `int.from_bytes ` and :func: `int.to_bytes `.
5498+ * :func: `hex `, :func: `oct `, :func: `bin `.
5499+ * :ref: `formatspec ` for hex, octal, and binary numbers.
5500+ * :class: `str ` to :class: `float `.
5501+ * :class: `str ` to :class: `decimal.Decimal `.
5502+
5503+ Configuring the limit
5504+ ---------------------
5505+
5506+ Before Python starts up you can use an environment variable or an interpreter
5507+ command line flag to configure the limit:
5508+
5509+ * :envvar: `PYTHONINTMAXSTRDIGITS `, e.g.
5510+ ``PYTHONINTMAXSTRDIGITS=640 python3 `` to set the limit to 640 or
5511+ ``PYTHONINTMAXSTRDIGITS=0 python3 `` to disable the limitation.
5512+ * :option: `-X int_max_str_digits <-X> `, e.g.
5513+ ``python3 -X int_max_str_digits=640 ``
5514+ * :data: `sys.flags.int_max_str_digits ` contains the value of
5515+ :envvar: `PYTHONINTMAXSTRDIGITS ` or :option: `-X int_max_str_digits <-X> `.
5516+ If both the env var and the ``-X `` option are set, the ``-X `` option takes
5517+ precedence. A value of *-1 * indicates that both were unset, thus a value of
5518+ :data: `sys.int_info.default_max_str_digits ` was used during initilization.
5519+
5520+ From code, you can inspect the current limit and set a new one using these
5521+ :mod: `sys ` APIs:
5522+
5523+ * :func: `sys.get_int_max_str_digits ` and :func: `sys.set_int_max_str_digits ` are
5524+ a getter and setter for the interpreter-wide limit. Subinterpreters have
5525+ their own limit.
5526+
5527+ Information about the default and minimum can be found in :attr: `sys.int_info `:
5528+
5529+ * :data: `sys.int_info.default_max_str_digits <sys.int_info> ` is the compiled-in
5530+ default limit.
5531+ * :data: `sys.int_info.str_digits_check_threshold <sys.int_info> ` is the lowest
5532+ accepted value for the limit (other than 0 which disables it).
5533+
5534+ .. versionadded :: 3.10.7
5535+
5536+ .. caution ::
5537+
5538+ Setting a low limit *can * lead to problems. While rare, code exists that
5539+ contains integer constants in decimal in their source that exceed the
5540+ minimum threshold. A consequence of setting the limit is that Python source
5541+ code containing decimal integer literals longer than the limit will
5542+ encounter an error during parsing, usually at startup time or import time or
5543+ even at installation time - anytime an up to date ``.pyc `` does not already
5544+ exist for the code. A workaround for source that contains such large
5545+ constants is to convert them to ``0x `` hexadecimal form as it has no limit.
5546+
5547+ Test your application thoroughly if you use a low limit. Ensure your tests
5548+ run with the limit set early via the environment or flag so that it applies
5549+ during startup and even during any installation step that may invoke Python
5550+ to precompile ``.py `` sources to ``.pyc `` files.
5551+
5552+ Recommended configuration
5553+ -------------------------
5554+
5555+ The default :data: `sys.int_info.default_max_str_digits ` is expected to be
5556+ reasonable for most applications. If your application requires a different
5557+ limit, set it from your main entry point using Python version agnostic code as
5558+ these APIs were added in security patch releases in versions before 3.11.
5559+
5560+ Example::
5561+
5562+ >>> import sys
5563+ >>> if hasattr(sys, "set_int_max_str_digits"):
5564+ ... upper_bound = 68000
5565+ ... lower_bound = 4004
5566+ ... current_limit = sys.get_int_max_str_digits()
5567+ ... if current_limit == 0 or current_limit > upper_bound:
5568+ ... sys.set_int_max_str_digits(upper_bound)
5569+ ... elif current_limit < lower_bound:
5570+ ... sys.set_int_max_str_digits(lower_bound)
5571+
5572+ If you need to disable it entirely, set it to ``0 ``.
5573+
5574+
54095575.. rubric :: Footnotes
54105576
54115577.. [1 ] Additional information on these special methods may be found in the Python
0 commit comments