summaryrefslogtreecommitdiffstats
path: root/Python/sysmodule.c
diff options
context:
space:
mode:
authorGregory P. Smith <greg@krypto.org>2022-09-06 05:24:36 (GMT)
committerGitHub <noreply@github.com>2022-09-06 05:24:36 (GMT)
commit15ec1afd4fcd2da1e2d2b256c562fb42d8d886a2 (patch)
tree2d57338531c6e22098a8a76f26262894920a85bc /Python/sysmodule.c
parentd5fe9951fe6e69e9175eca24170a220747ec9047 (diff)
downloadcpython-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.c44
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()) {