Skip to content

Commit 859b6a4

Browse files
vstinnerstratakis
authored andcommitted
00387: CVE-2020-10735: Prevent DoS by very large int()
pythongh-95778: CVE-2020-10735: Prevent DoS by very large int() (pythonGH-96504) Converting between `int` and `str` in bases other than 2 (binary), 4, 8 (octal), 16 (hexadecimal), or 32 such as base 10 (decimal) now raises a `ValueError` if the number of digits in string form is above a limit to avoid potential denial of service attacks due to the algorithmic complexity. This is a mitigation for CVE-2020-10735 (https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10735). This new limit can be configured or disabled by environment variable, command line flag, or :mod:`sys` APIs. See the `Integer String Conversion Length Limitation` documentation. The default limit is 4300 digits in string form. Patch by Gregory P. Smith [Google] and Christian Heimes [Red Hat] with feedback from Victor Stinner, Thomas Wouters, Steve Dower, Ned Deily, and Mark Dickinson. Notes on the backport to Python 3.6: * Use "Python 3.6.15-13" version in the documentation, whereas this version will never be released * Only add _Py_global_config_int_max_str_digits global variable: Python 3.6 doesn't have PyConfig API (PEP 597) nor _PyRuntime. * sys.flags.int_max_str_digits cannot be -1 on Python 3.6: it is set to the default limit. Adapt test_int_max_str_digits() for that. * Declare _PY_LONG_DEFAULT_MAX_STR_DIGITS and _PY_LONG_MAX_STR_DIGITS_THRESHOLD macros in longobject.h but only if the Py_BUILD_CORE macro is defined. * Declare _Py_global_config_int_max_str_digits in pydebug.h. (cherry picked from commit 511ca94) pythongh-95778: Mention sys.set_int_max_str_digits() in error message (python#96874) When ValueError is raised if an integer is larger than the limit, mention sys.set_int_max_str_digits() in the error message. (cherry picked from commit e841ffc) pythongh-96848: Fix -X int_max_str_digits option parsing (python#96988) Fix command line parsing: reject "-X int_max_str_digits" option with no value (invalid) when the PYTHONINTMAXSTRDIGITS environment variable is set to a valid limit. (cherry picked from commit 4135166)
1 parent 409761f commit 859b6a4

25 files changed

+870
-15
lines changed

Doc/library/functions.rst

+8
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,14 @@ are always available. They are listed here in alphabetical order.
748748
.. versionchanged:: 3.6
749749
Grouping digits with underscores as in code literals is allowed.
750750

751+
.. versionchanged:: 3.6.15-13
752+
:class:`int` string inputs and string representations can be limited to
753+
help avoid denial of service attacks. A :exc:`ValueError` is raised when
754+
the limit is exceeded while converting a string *x* to an :class:`int` or
755+
when converting an :class:`int` into a string would exceed the limit.
756+
See the :ref:`integer string conversion length limitation
757+
<int_max_str_digits>` documentation.
758+
751759

752760
.. function:: isinstance(object, classinfo)
753761

Doc/library/json.rst

+11
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ is a lightweight data interchange format inspired by
1818
`JavaScript <https://en.wikipedia.org/wiki/JavaScript>`_ object literal syntax
1919
(although it is not a strict subset of JavaScript [#rfc-errata]_ ).
2020

21+
.. warning::
22+
Be cautious when parsing JSON data from untrusted sources. A malicious
23+
JSON string may cause the decoder to consume considerable CPU and memory
24+
resources. Limiting the size of data to be parsed is recommended.
25+
2126
:mod:`json` exposes an API familiar to users of the standard library
2227
:mod:`marshal` and :mod:`pickle` modules.
2328

@@ -245,6 +250,12 @@ Basic Usage
245250
be used to use another datatype or parser for JSON integers
246251
(e.g. :class:`float`).
247252

253+
.. versionchanged:: 3.6.15-13
254+
The default *parse_int* of :func:`int` now limits the maximum length of
255+
the integer string via the interpreter's :ref:`integer string
256+
conversion length limitation <int_max_str_digits>` to help avoid denial
257+
of service attacks.
258+
248259
*parse_constant*, if specified, will be called with one of the following
249260
strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``.
250261
This can be used to raise an exception if invalid JSON numbers

Doc/library/stdtypes.rst

+159
Original file line numberDiff line numberDiff line change
@@ -4671,6 +4671,165 @@ types, where they are relevant. Some of these are not reported by the
46714671
[<class 'bool'>]
46724672

46734673

4674+
.. _int_max_str_digits:
4675+
4676+
Integer string conversion length limitation
4677+
===========================================
4678+
4679+
CPython has a global limit for converting between :class:`int` and :class:`str`
4680+
to mitigate denial of service attacks. This limit *only* applies to decimal or
4681+
other non-power-of-two number bases. Hexadecimal, octal, and binary conversions
4682+
are unlimited. The limit can be configured.
4683+
4684+
The :class:`int` type in CPython is an abitrary length number stored in binary
4685+
form (commonly known as a "bignum"). There exists no algorithm that can convert
4686+
a string to a binary integer or a binary integer to a string in linear time,
4687+
*unless* the base is a power of 2. Even the best known algorithms for base 10
4688+
have sub-quadratic complexity. Converting a large value such as ``int('1' *
4689+
500_000)`` can take over a second on a fast CPU.
4690+
4691+
Limiting conversion size offers a practical way to avoid `CVE-2020-10735
4692+
<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10735>`_.
4693+
4694+
The limit is applied to the number of digit characters in the input or output
4695+
string when a non-linear conversion algorithm would be involved. Underscores
4696+
and the sign are not counted towards the limit.
4697+
4698+
When an operation would exceed the limit, a :exc:`ValueError` is raised:
4699+
4700+
.. doctest::
4701+
4702+
>>> import sys
4703+
>>> sys.set_int_max_str_digits(4300) # Illustrative, this is the default.
4704+
>>> _ = int('2' * 5432)
4705+
Traceback (most recent call last):
4706+
...
4707+
ValueError: Exceeds the limit (4300) for integer string conversion: value has 5432 digits; use sys.set_int_max_str_digits() to increase the limit.
4708+
>>> i = int('2' * 4300)
4709+
>>> len(str(i))
4710+
4300
4711+
>>> i_squared = i*i
4712+
>>> len(str(i_squared))
4713+
Traceback (most recent call last):
4714+
...
4715+
ValueError: Exceeds the limit (4300) for integer string conversion: value has 8599 digits; use sys.set_int_max_str_digits() to increase the limit.
4716+
>>> len(hex(i_squared))
4717+
7144
4718+
>>> assert int(hex(i_squared), base=16) == i*i # Hexadecimal is unlimited.
4719+
4720+
The default limit is 4300 digits as provided in
4721+
:data:`sys.int_info.default_max_str_digits <sys.int_info>`.
4722+
The lowest limit that can be configured is 640 digits as provided in
4723+
:data:`sys.int_info.str_digits_check_threshold <sys.int_info>`.
4724+
4725+
Verification:
4726+
4727+
.. doctest::
4728+
4729+
>>> import sys
4730+
>>> assert sys.int_info.default_max_str_digits == 4300, sys.int_info
4731+
>>> assert sys.int_info.str_digits_check_threshold == 640, sys.int_info
4732+
>>> msg = int('578966293710682886880994035146873798396722250538762761564'
4733+
... '9252925514383915483333812743580549779436104706260696366600'
4734+
... '571186405732').to_bytes(53, 'big')
4735+
...
4736+
4737+
.. versionadded:: 3.6.15-13
4738+
4739+
Affected APIs
4740+
-------------
4741+
4742+
The limitation only applies to potentially slow conversions between :class:`int`
4743+
and :class:`str` or :class:`bytes`:
4744+
4745+
* ``int(string)`` with default base 10.
4746+
* ``int(string, base)`` for all bases that are not a power of 2.
4747+
* ``str(integer)``.
4748+
* ``repr(integer)``
4749+
* any other string conversion to base 10, for example ``f"{integer}"``,
4750+
``"{}".format(integer)``, or ``b"%d" % integer``.
4751+
4752+
The limitations do not apply to functions with a linear algorithm:
4753+
4754+
* ``int(string, base)`` with base 2, 4, 8, 16, or 32.
4755+
* :func:`int.from_bytes` and :func:`int.to_bytes`.
4756+
* :func:`hex`, :func:`oct`, :func:`bin`.
4757+
* :ref:`formatspec` for hex, octal, and binary numbers.
4758+
* :class:`str` to :class:`float`.
4759+
* :class:`str` to :class:`decimal.Decimal`.
4760+
4761+
Configuring the limit
4762+
---------------------
4763+
4764+
Before Python starts up you can use an environment variable or an interpreter
4765+
command line flag to configure the limit:
4766+
4767+
* :envvar:`PYTHONINTMAXSTRDIGITS`, e.g.
4768+
``PYTHONINTMAXSTRDIGITS=640 python3`` to set the limit to 640 or
4769+
``PYTHONINTMAXSTRDIGITS=0 python3`` to disable the limitation.
4770+
* :option:`-X int_max_str_digits <-X>`, e.g.
4771+
``python3 -X int_max_str_digits=640``
4772+
* :data:`sys.flags.int_max_str_digits` contains the value of
4773+
:envvar:`PYTHONINTMAXSTRDIGITS` or :option:`-X int_max_str_digits <-X>`.
4774+
If both the env var and the ``-X`` option are set, the ``-X`` option takes
4775+
precedence. A value of *-1* indicates that both were unset, thus a value of
4776+
:data:`sys.int_info.default_max_str_digits` was used during initilization.
4777+
4778+
From code, you can inspect the current limit and set a new one using these
4779+
:mod:`sys` APIs:
4780+
4781+
* :func:`sys.get_int_max_str_digits` and :func:`sys.set_int_max_str_digits` are
4782+
a getter and setter for the interpreter-wide limit. Subinterpreters have
4783+
their own limit.
4784+
4785+
Information about the default and minimum can be found in :attr:`sys.int_info`:
4786+
4787+
* :data:`sys.int_info.default_max_str_digits <sys.int_info>` is the compiled-in
4788+
default limit.
4789+
* :data:`sys.int_info.str_digits_check_threshold <sys.int_info>` is the lowest
4790+
accepted value for the limit (other than 0 which disables it).
4791+
4792+
.. versionadded:: 3.6.15-13
4793+
4794+
.. caution::
4795+
4796+
Setting a low limit *can* lead to problems. While rare, code exists that
4797+
contains integer constants in decimal in their source that exceed the
4798+
minimum threshold. A consequence of setting the limit is that Python source
4799+
code containing decimal integer literals longer than the limit will
4800+
encounter an error during parsing, usually at startup time or import time or
4801+
even at installation time - anytime an up to date ``.pyc`` does not already
4802+
exist for the code. A workaround for source that contains such large
4803+
constants is to convert them to ``0x`` hexadecimal form as it has no limit.
4804+
4805+
Test your application thoroughly if you use a low limit. Ensure your tests
4806+
run with the limit set early via the environment or flag so that it applies
4807+
during startup and even during any installation step that may invoke Python
4808+
to precompile ``.py`` sources to ``.pyc`` files.
4809+
4810+
Recommended configuration
4811+
-------------------------
4812+
4813+
The default :data:`sys.int_info.default_max_str_digits` is expected to be
4814+
reasonable for most applications. If your application requires a different
4815+
limit, set it from your main entry point using Python version agnostic code as
4816+
these APIs were added in security patch releases in versions before 3.11.
4817+
4818+
Example::
4819+
4820+
>>> import sys
4821+
>>> if hasattr(sys, "set_int_max_str_digits"):
4822+
... upper_bound = 68000
4823+
... lower_bound = 4004
4824+
... current_limit = sys.get_int_max_str_digits()
4825+
... if current_limit == 0 or current_limit > upper_bound:
4826+
... sys.set_int_max_str_digits(upper_bound)
4827+
... elif current_limit < lower_bound:
4828+
... sys.set_int_max_str_digits(lower_bound)
4829+
4830+
If you need to disable it entirely, set it to ``0``.
4831+
4832+
46744833
.. rubric:: Footnotes
46754834

46764835
.. [1] Additional information on these special methods may be found in the Python

Doc/library/sys.rst

+43-10
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ always available.
296296
:const:`bytes_warning` :option:`-b`
297297
:const:`quiet` :option:`-q`
298298
:const:`hash_randomization` :option:`-R`
299+
:const:`int_max_str_digits` :option:`-X int_max_str_digits <-X>` (:ref:`integer string conversion length limitation <int_max_str_digits>`)
299300
============================= =============================
300301

301302
.. versionchanged:: 3.2
@@ -310,6 +311,9 @@ always available.
310311
.. versionchanged:: 3.4
311312
Added ``isolated`` attribute for :option:`-I` ``isolated`` flag.
312313

314+
.. versionchanged:: 3.6.15-13
315+
Added the ``int_max_str_digits`` attribute.
316+
313317
.. data:: float_info
314318

315319
A :term:`struct sequence` holding information about the float type. It
@@ -468,6 +472,15 @@ always available.
468472

469473
.. versionadded:: 3.6
470474

475+
476+
.. function:: get_int_max_str_digits()
477+
478+
Returns the current value for the :ref:`integer string conversion length
479+
limitation <int_max_str_digits>`. See also :func:`set_int_max_str_digits`.
480+
481+
.. versionadded:: 3.6.15-13
482+
483+
471484
.. function:: getrefcount(object)
472485

473486
Return the reference count of the *object*. The count returned is generally one
@@ -730,19 +743,31 @@ always available.
730743

731744
.. tabularcolumns:: |l|L|
732745

733-
+-------------------------+----------------------------------------------+
734-
| Attribute | Explanation |
735-
+=========================+==============================================+
736-
| :const:`bits_per_digit` | number of bits held in each digit. Python |
737-
| | integers are stored internally in base |
738-
| | ``2**int_info.bits_per_digit`` |
739-
+-------------------------+----------------------------------------------+
740-
| :const:`sizeof_digit` | size in bytes of the C type used to |
741-
| | represent a digit |
742-
+-------------------------+----------------------------------------------+
746+
+----------------------------------------+-----------------------------------------------+
747+
| Attribute | Explanation |
748+
+========================================+===============================================+
749+
| :const:`bits_per_digit` | number of bits held in each digit. Python |
750+
| | integers are stored internally in base |
751+
| | ``2**int_info.bits_per_digit`` |
752+
+----------------------------------------+-----------------------------------------------+
753+
| :const:`sizeof_digit` | size in bytes of the C type used to |
754+
| | represent a digit |
755+
+----------------------------------------+-----------------------------------------------+
756+
| :const:`default_max_str_digits` | default value for |
757+
| | :func:`sys.get_int_max_str_digits` when it |
758+
| | is not otherwise explicitly configured. |
759+
+----------------------------------------+-----------------------------------------------+
760+
| :const:`str_digits_check_threshold` | minimum non-zero value for |
761+
| | :func:`sys.set_int_max_str_digits`, |
762+
| | :envvar:`PYTHONINTMAXSTRDIGITS`, or |
763+
| | :option:`-X int_max_str_digits <-X>`. |
764+
+----------------------------------------+-----------------------------------------------+
743765

744766
.. versionadded:: 3.1
745767

768+
.. versionchanged:: 3.6.15-13
769+
Added ``default_max_str_digits`` and ``str_digits_check_threshold``.
770+
746771

747772
.. data:: __interactivehook__
748773

@@ -1001,6 +1026,14 @@ always available.
10011026

10021027
Availability: Unix.
10031028

1029+
.. function:: set_int_max_str_digits(n)
1030+
1031+
Set the :ref:`integer string conversion length limitation
1032+
<int_max_str_digits>` used by this interpreter. See also
1033+
:func:`get_int_max_str_digits`.
1034+
1035+
.. versionadded:: 3.6.15-13
1036+
10041037
.. function:: setprofile(profilefunc)
10051038

10061039
.. index::

Doc/library/test.rst

+10
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,16 @@ The :mod:`test.support` module defines the following functions:
625625
.. versionadded:: 3.6
626626

627627

628+
.. function:: adjust_int_max_str_digits(max_digits)
629+
630+
This function returns a context manager that will change the global
631+
:func:`sys.set_int_max_str_digits` setting for the duration of the
632+
context to allow execution of test code that needs a different limit
633+
on the number of digits when converting between an integer and string.
634+
635+
.. versionadded:: 3.6.15-13
636+
637+
628638
The :mod:`test.support` module defines the following classes:
629639

630640
.. class:: TransientResource(exc, **kwargs)

Doc/using/cmdline.rst

+14
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,9 @@ Miscellaneous options
422422
* ``-X showalloccount`` to output the total count of allocated objects for
423423
each type when the program finishes. This only works when Python was built with
424424
``COUNT_ALLOCS`` defined.
425+
* ``-X int_max_str_digits`` configures the :ref:`integer string conversion
426+
length limitation <int_max_str_digits>`. See also
427+
:envvar:`PYTHONINTMAXSTRDIGITS`.
425428

426429
It also allows passing arbitrary values and retrieving them through the
427430
:data:`sys._xoptions` dictionary.
@@ -438,6 +441,9 @@ Miscellaneous options
438441
.. versionadded:: 3.6
439442
The ``-X showalloccount`` option.
440443

444+
.. versionadded:: 3.6.15-13
445+
The ``-X int_max_str_digits`` option.
446+
441447

442448
Options you shouldn't use
443449
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -571,6 +577,14 @@ conflict.
571577
.. versionadded:: 3.2.3
572578

573579

580+
.. envvar:: PYTHONINTMAXSTRDIGITS
581+
582+
If this variable is set to an integer, it is used to configure the
583+
interpreter's global :ref:`integer string conversion length limitation
584+
<int_max_str_digits>`.
585+
586+
.. versionadded:: 3.6.15-13
587+
574588
.. envvar:: PYTHONIOENCODING
575589

576590
If this is set before running the interpreter, it overrides the encoding used

Doc/whatsnew/3.6.rst

+15
Original file line numberDiff line numberDiff line change
@@ -2488,3 +2488,18 @@ ASCII newline ``\n``, ``\r`` and tab ``\t`` characters are stripped from the
24882488
URL by the parser :func:`urllib.parse` preventing such attacks. The removal
24892489
characters are controlled by a new module level variable
24902490
``urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE``. (See :issue:`43882`)
2491+
2492+
2493+
Notable security feature in 3.6.15-13
2494+
=====================================
2495+
2496+
Converting between :class:`int` and :class:`str` in bases other than 2
2497+
(binary), 4, 8 (octal), 16 (hexadecimal), or 32 such as base 10 (decimal)
2498+
now raises a :exc:`ValueError` if the number of digits in string form is
2499+
above a limit to avoid potential denial of service attacks due to the
2500+
algorithmic complexity. This is a mitigation for `CVE-2020-10735
2501+
<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10735>`_.
2502+
This limit can be configured or disabled by environment variable, command
2503+
line flag, or :mod:`sys` APIs. See the :ref:`integer string conversion
2504+
length limitation <int_max_str_digits>` documentation. The default limit
2505+
is 4300 digits in string form.

0 commit comments

Comments
 (0)