diff options
| author | Gregory P. Smith <greg@krypto.org> | 2022-09-06 05:24:36 (GMT) |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-09-06 05:24:36 (GMT) |
| commit | 15ec1afd4fcd2da1e2d2b256c562fb42d8d886a2 (patch) | |
| tree | 2d57338531c6e22098a8a76f26262894920a85bc /Python/sysmodule.c | |
| parent | d5fe9951fe6e69e9175eca24170a220747ec9047 (diff) | |
| download | cpython-15ec1afd4fcd2da1e2d2b256c562fb42d8d886a2.zip cpython-15ec1afd4fcd2da1e2d2b256c562fb42d8d886a2.tar.gz cpython-15ec1afd4fcd2da1e2d2b256c562fb42d8d886a2.tar.bz2 | |
[3.7] gh-95778: CVE-2020-10735: Prevent DoS by very large int() (GH-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.
Diffstat (limited to 'Python/sysmodule.c')
| -rw-r--r-- | Python/sysmodule.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/Python/sysmodule.c b/Python/sysmodule.c index b953a00..82e029f 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -15,6 +15,7 @@ Data members: */ #include "Python.h" +#include "internal/pycore_long.h" // _PY_LONG_MAX_STR_DIGITS_THRESHOLD #include "internal/pystate.h" #include "code.h" #include "frameobject.h" @@ -1218,6 +1219,43 @@ sys_mdebug(PyObject *self, PyObject *args) } #endif /* USE_MALLOPT */ + +/*[clinic input] +sys.get_int_max_str_digits + +Set the maximum string digits limit for non-binary int<->str conversions. +[clinic start generated code]*/ + +static PyObject * +sys_get_int_max_str_digits_impl(PyObject *module) +/*[clinic end generated code: output=0042f5e8ae0e8631 input=8dab13e2023e60d5]*/ +{ + return PyLong_FromSsize_t(_PyRuntime.int_max_str_digits); +} + +/*[clinic input] +sys.set_int_max_str_digits + + maxdigits: int + +Set the maximum string digits limit for non-binary int<->str conversions. +[clinic start generated code]*/ + +static PyObject * +sys_set_int_max_str_digits_impl(PyObject *module, int maxdigits) +/*[clinic end generated code: output=734d4c2511f2a56d input=d7e3f325db6910c5]*/ +{ + if ((!maxdigits) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD)) { + _PyRuntime.int_max_str_digits = maxdigits; + Py_RETURN_NONE; + } else { + PyErr_Format( + PyExc_ValueError, "maxdigits must be 0 or larger than %d", + _PY_LONG_MAX_STR_DIGITS_THRESHOLD); + return NULL; + } +} + size_t _PySys_GetSizeOf(PyObject *o) { @@ -1605,6 +1643,8 @@ static PyMethodDef sys_methods[] = { {"getandroidapilevel", (PyCFunction)sys_getandroidapilevel, METH_NOARGS, getandroidapilevel_doc}, #endif + SYS_GET_INT_MAX_STR_DIGITS_METHODDEF + SYS_SET_INT_MAX_STR_DIGITS_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -2051,6 +2091,7 @@ static PyStructSequence_Field flags_fields[] = { {"isolated", "-I"}, {"dev_mode", "-X dev"}, {"utf8_mode", "-X utf8"}, + {"int_max_str_digits", "-X int_max_str_digits"}, {0} }; @@ -2058,7 +2099,7 @@ static PyStructSequence_Desc flags_desc = { "sys.flags", /* name */ flags__doc__, /* doc */ flags_fields, /* fields */ - 15 + 16 }; static PyObject* @@ -2092,6 +2133,7 @@ make_flags(void) SetFlag(Py_IsolatedFlag); PyStructSequence_SET_ITEM(seq, pos++, PyBool_FromLong(core_config->dev_mode)); SetFlag(Py_UTF8Mode); + SetFlag(_Py_global_config_int_max_str_digits); #undef SetFlag if (PyErr_Occurred()) { |
