update version to 3.10.9
This commit is contained in:
parent
537e076a0c
commit
ce1308c7b9
@ -1,5 +1,15 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: David Malcolm <dmalcolm@redhat.com>
|
||||
Date: Wed, 13 Jan 2010 21:25:18 +0000
|
||||
Subject: [PATCH] 00001: Fixup distutils/unixccompiler.py to remove standard
|
||||
library path from rpath Was Patch0 in ivazquez' python3000 specfile
|
||||
|
||||
---
|
||||
Lib/distutils/unixccompiler.py | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py
|
||||
index f0792de..4d83793 100644
|
||||
index d00c48981e..0283a28c19 100644
|
||||
--- a/Lib/distutils/unixccompiler.py
|
||||
+++ b/Lib/distutils/unixccompiler.py
|
||||
@@ -82,6 +82,15 @@ class UnixCCompiler(CCompiler):
|
||||
@ -18,6 +28,3 @@ index f0792de..4d83793 100644
|
||||
def preprocess(self, source, output_file=None, macros=None,
|
||||
include_dirs=None, extra_preargs=None, extra_postargs=None):
|
||||
fixed_args = self._fix_compile_args(None, macros, include_dirs)
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
@ -1,37 +1,65 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lumir Balhar <lbalhar@redhat.com>
|
||||
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
|
||||
Date: Mon, 15 Feb 2021 12:19:27 +0100
|
||||
Subject: [PATCH] 00251: Change user install location
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Change the values of sysconfig's "posix_prefix" install scheme to /usr/local
|
||||
when RPM build or venv/virtualenv is not detected,
|
||||
to make pip, sysconfig and distutils install into an isolated location.
|
||||
Set values of base and platbase in sysconfig from /usr
|
||||
to /usr/local when RPM build is not detected
|
||||
to make pip and similar tools install into separate location.
|
||||
|
||||
The original values are saved as an additional "rpm_prefix" install scheme.
|
||||
|
||||
The site module adds the /usr/local paths to sys.path when site packages are
|
||||
enabled and RPM build is not detected.
|
||||
Set values of prefix and exec_prefix in distutils install command
|
||||
to /usr/local if executable is /usr/bin/python* and RPM build
|
||||
is not detected to make distutils and pypa/distutils install into separate location.
|
||||
|
||||
Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||
Downstream only.
|
||||
|
||||
Rewrote in Fedora 36+ to patch sysconfig instead of distutils,
|
||||
see https://discuss.python.org/t/pep-632-deprecate-distutils-module/5134/104
|
||||
We've tried to rework in Fedora 36/Python 3.10 to follow https://bugs.python.org/issue43976
|
||||
but we have identified serious problems with that approach,
|
||||
see https://bugzilla.redhat.com/2026979 or https://bugzilla.redhat.com/2097183
|
||||
|
||||
Downstream only for now, waiting for https://bugs.python.org/issue43976
|
||||
pypa/distutils integration: https://github.com/pypa/distutils/pull/70
|
||||
|
||||
Co-authored-by: Petr Viktorin <encukou@gmail.com>
|
||||
Co-authored-by: Miro Hrončok <miro@hroncok.cz>
|
||||
Co-authored-by: Michal Cyprian <m.cyprian@gmail.com>
|
||||
Co-authored-by: Lumír Balhar <frenzy.madness@gmail.com>
|
||||
---
|
||||
Lib/site.py | 9 ++++++++-
|
||||
Lib/sysconfig.py | 25 +++++++++++++++++++++++++
|
||||
Lib/test/test_sysconfig.py | 4 +++-
|
||||
3 files changed, 36 insertions(+), 2 deletions(-)
|
||||
Lib/distutils/command/install.py | 8 +++--
|
||||
Lib/site.py | 9 +++++-
|
||||
Lib/sysconfig.py | 53 +++++++++++++++++++++++++++++++-
|
||||
Lib/test/test_sysconfig.py | 17 ++++++++--
|
||||
4 files changed, 81 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py
|
||||
index 01d5331a63..79f70f0de4 100644
|
||||
--- a/Lib/distutils/command/install.py
|
||||
+++ b/Lib/distutils/command/install.py
|
||||
@@ -159,6 +159,8 @@ class install(Command):
|
||||
|
||||
negative_opt = {'no-compile' : 'compile'}
|
||||
|
||||
+ # Allow Fedora to add components to the prefix
|
||||
+ _prefix_addition = getattr(sysconfig, '_prefix_addition', '')
|
||||
|
||||
def initialize_options(self):
|
||||
"""Initializes options."""
|
||||
@@ -441,8 +443,10 @@ def finalize_unix(self):
|
||||
raise DistutilsOptionError(
|
||||
"must not supply exec-prefix without prefix")
|
||||
|
||||
- self.prefix = os.path.normpath(sys.prefix)
|
||||
- self.exec_prefix = os.path.normpath(sys.exec_prefix)
|
||||
+ self.prefix = (
|
||||
+ os.path.normpath(sys.prefix) + self._prefix_addition)
|
||||
+ self.exec_prefix = (
|
||||
+ os.path.normpath(sys.exec_prefix) + self._prefix_addition)
|
||||
|
||||
else:
|
||||
if self.exec_prefix is None:
|
||||
diff --git a/Lib/site.py b/Lib/site.py
|
||||
index 939893eb5e..d1316c3355 100644
|
||||
--- a/Lib/site.py
|
||||
@ -54,46 +82,113 @@ index 939893eb5e..d1316c3355 100644
|
||||
if os.path.isdir(sitedir):
|
||||
addsitedir(sitedir, known_paths)
|
||||
diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py
|
||||
index daf9f00006..40e4edf0ae 100644
|
||||
index daf9f00006..10368c92a7 100644
|
||||
--- a/Lib/sysconfig.py
|
||||
+++ b/Lib/sysconfig.py
|
||||
@@ -58,6 +58,31 @@
|
||||
@@ -58,6 +58,16 @@
|
||||
},
|
||||
}
|
||||
|
||||
+# backup the original posix_prefix as rpm_prefix
|
||||
+# RPM packages use it and we need to be able to read it even when changed
|
||||
+# For a brief period of time in the Fedora 36 life cycle,
|
||||
+# this installation scheme existed and was documented in the release notes.
|
||||
+# For backwards compatibility, we keep it here (at least on 3.10 and 3.11).
|
||||
+_INSTALL_SCHEMES['rpm_prefix'] = _INSTALL_SCHEMES['posix_prefix']
|
||||
+# Virtualenv >= 20.10.0 favors the "venv" scheme over the defaults when creating virtual environments.
|
||||
+# See: https://github.com/pypa/virtualenv/commit/8da79db86d8a5c74d03667a40e64ff832076445e
|
||||
+# See: https://bugs.python.org/issue45413
|
||||
+# "venv" should be the same as the unpatched posix_prefix for us,
|
||||
+# "venv" should be the same as the posix_prefix for us,
|
||||
+# so new virtual environments aren't created with paths like venv/local/bin/python.
|
||||
+_INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_prefix']
|
||||
+
|
||||
+if (not (hasattr(sys, 'real_prefix') or
|
||||
+ sys.prefix != sys.base_prefix) and
|
||||
+ 'RPM_BUILD_ROOT' not in os.environ):
|
||||
+ _INSTALL_SCHEMES['posix_prefix'] = {
|
||||
+ 'stdlib': '{installed_base}/{platlibdir}/python{py_version_short}',
|
||||
+ 'platstdlib': '{platbase}/{platlibdir}/python{py_version_short}',
|
||||
+ 'purelib': '{base}/local/lib/python{py_version_short}/site-packages',
|
||||
+ 'platlib': '{platbase}/local/{platlibdir}/python{py_version_short}/site-packages',
|
||||
+ 'include':
|
||||
+ '{installed_base}/include/python{py_version_short}{abiflags}',
|
||||
+ 'platinclude':
|
||||
+ '{installed_platbase}/include/python{py_version_short}{abiflags}',
|
||||
+ 'scripts': '{base}/local/bin',
|
||||
+ 'data': '{base}/local',
|
||||
+ }
|
||||
|
||||
# NOTE: site.py has copy of this function.
|
||||
# Sync it when modify this function.
|
||||
@@ -117,6 +127,19 @@ def joinuser(*args):
|
||||
},
|
||||
}
|
||||
|
||||
+# This is used by distutils.command.install in the stdlib
|
||||
+# as well as pypa/distutils (e.g. bundled in setuptools).
|
||||
+# The self.prefix value is set to sys.prefix + /local/
|
||||
+# if neither RPM build nor virtual environment is
|
||||
+# detected to make distutils install packages
|
||||
+# into the separate location.
|
||||
+# https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||
+if (not (hasattr(sys, 'real_prefix') or
|
||||
+ sys.prefix != sys.base_prefix) and
|
||||
+ 'RPM_BUILD_ROOT' not in os.environ):
|
||||
+ _prefix_addition = '/local'
|
||||
+
|
||||
+
|
||||
_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
|
||||
'scripts', 'data')
|
||||
|
||||
@@ -211,11 +234,39 @@ def _extend_dict(target_dict, other_dict):
|
||||
target_dict[key] = value
|
||||
|
||||
|
||||
+_CONFIG_VARS_LOCAL = None
|
||||
+
|
||||
+
|
||||
+def _config_vars_local():
|
||||
+ # This function returns the config vars with prefixes amended to /usr/local
|
||||
+ # https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||
+ global _CONFIG_VARS_LOCAL
|
||||
+ if _CONFIG_VARS_LOCAL is None:
|
||||
+ _CONFIG_VARS_LOCAL = dict(get_config_vars())
|
||||
+ _CONFIG_VARS_LOCAL['base'] = '/usr/local'
|
||||
+ _CONFIG_VARS_LOCAL['platbase'] = '/usr/local'
|
||||
+ return _CONFIG_VARS_LOCAL
|
||||
+
|
||||
+
|
||||
def _expand_vars(scheme, vars):
|
||||
res = {}
|
||||
if vars is None:
|
||||
vars = {}
|
||||
- _extend_dict(vars, get_config_vars())
|
||||
+
|
||||
+ # when we are not in a virtual environment or an RPM build
|
||||
+ # we change '/usr' to '/usr/local'
|
||||
+ # to avoid surprises, we explicitly check for the /usr/ prefix
|
||||
+ # Python virtual environments have different prefixes
|
||||
+ # we only do this for posix_prefix, not to mangle the venv scheme
|
||||
+ # posix_prefix is used by sudo pip install
|
||||
+ # we only change the defaults here, so explicit --prefix will take precedence
|
||||
+ # https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||
+ if (scheme == 'posix_prefix' and
|
||||
+ _PREFIX == '/usr' and
|
||||
+ 'RPM_BUILD_ROOT' not in os.environ):
|
||||
+ _extend_dict(vars, _config_vars_local())
|
||||
+ else:
|
||||
+ _extend_dict(vars, get_config_vars())
|
||||
|
||||
for key, value in _INSTALL_SCHEMES[scheme].items():
|
||||
if os.name in ('posix', 'nt'):
|
||||
diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py
|
||||
index 9408657c91..fd49b2bcce 100644
|
||||
index 5ee9839c04..16e92ca86f 100644
|
||||
--- a/Lib/test/test_sysconfig.py
|
||||
+++ b/Lib/test/test_sysconfig.py
|
||||
@@ -263,7 +263,7 @@ def test_get_config_h_filename(self):
|
||||
@@ -105,8 +105,19 @@ def test_get_path(self):
|
||||
for scheme in _INSTALL_SCHEMES:
|
||||
for name in _INSTALL_SCHEMES[scheme]:
|
||||
expected = _INSTALL_SCHEMES[scheme][name].format(**config_vars)
|
||||
+ tested = get_path(name, scheme)
|
||||
+ # https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||
+ if tested.startswith('/usr/local'):
|
||||
+ # /usr/local should only be used in posix_prefix
|
||||
+ self.assertEqual(scheme, 'posix_prefix')
|
||||
+ # Fedora CI runs tests for venv and virtualenv that check for other prefixes
|
||||
+ self.assertEqual(sys.prefix, '/usr')
|
||||
+ # When building the RPM of Python, %check runs this with RPM_BUILD_ROOT set
|
||||
+ # Fedora CI runs this with RPM_BUILD_ROOT unset
|
||||
+ self.assertNotIn('RPM_BUILD_ROOT', os.environ)
|
||||
+ tested = tested.replace('/usr/local', '/usr')
|
||||
self.assertEqual(
|
||||
- os.path.normpath(get_path(name, scheme)),
|
||||
+ os.path.normpath(tested),
|
||||
os.path.normpath(expected),
|
||||
)
|
||||
|
||||
@@ -263,7 +274,7 @@ def test_get_config_h_filename(self):
|
||||
self.assertTrue(os.path.isfile(config_h), config_h)
|
||||
|
||||
def test_get_scheme_names(self):
|
||||
@ -102,7 +197,7 @@ index 9408657c91..fd49b2bcce 100644
|
||||
if HAS_USER_BASE:
|
||||
wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
|
||||
self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
|
||||
@@ -274,6 +274,8 @@ def test_symlink(self): # Issue 7880
|
||||
@@ -274,6 +285,8 @@ def test_symlink(self): # Issue 7880
|
||||
cmd = "-c", "import sysconfig; print(sysconfig.get_platform())"
|
||||
self.assertEqual(py.call_real(*cmd), py.call_link(*cmd))
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,36 +0,0 @@
|
||||
From 3a56a938f375f17f39baeb4b1529793dd0eb79b8 Mon Sep 17 00:00:00 2001
|
||||
From: "Miss Islington (bot)"
|
||||
<31488909+miss-islington@users.noreply.github.com>
|
||||
Date: Sun, 4 Sep 2022 00:12:34 -0700
|
||||
Subject: [PATCH] gh-95778: remove unneeded doc note on float.as_integer_ratio
|
||||
(GH-96553)
|
||||
|
||||
Per mdickinson@'s comment on the main branch PR.
|
||||
(cherry picked from commit 69bb83c2bf254f92491d527ccec1ff41897add56)
|
||||
|
||||
Co-authored-by: Gregory P. Smith <greg@krypto.org>
|
||||
---
|
||||
Doc/library/stdtypes.rst | 7 -------
|
||||
1 file changed, 7 deletions(-)
|
||||
|
||||
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
|
||||
index bc365bb..c82a6ad 100644
|
||||
--- a/Doc/library/stdtypes.rst
|
||||
+++ b/Doc/library/stdtypes.rst
|
||||
@@ -584,13 +584,6 @@ class`. float also has the following additional methods.
|
||||
:exc:`OverflowError` on infinities and a :exc:`ValueError` on
|
||||
NaNs.
|
||||
|
||||
- .. note::
|
||||
-
|
||||
- The values returned by ``as_integer_ratio()`` can be huge. Attempts
|
||||
- to render such integers into decimal strings may bump into the
|
||||
- :ref:`integer string conversion length limitation
|
||||
- <int_max_str_digits>`.
|
||||
-
|
||||
.. method:: float.is_integer()
|
||||
|
||||
Return ``True`` if the float instance is finite with integral
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,226 +0,0 @@
|
||||
From eace09e63ed7978dbdfeb1ae537fac505e6b5b0e Mon Sep 17 00:00:00 2001
|
||||
From: "Gregory P. Smith" <greg@krypto.org>
|
||||
Date: Sun, 4 Sep 2022 09:54:56 -0700
|
||||
Subject: [PATCH] [3.10] gh-95778: Correctly pre-check for int-to-str
|
||||
conversion (GH-96537) (#96563)
|
||||
|
||||
Converting a large enough `int` to a decimal string raises `ValueError` as expected. However, the raise comes _after_ the quadratic-time base-conversion algorithm has run to completion. For effective DOS prevention, we need some kind of check before entering the quadratic-time loop. Oops! =)
|
||||
|
||||
The quick fix: essentially we catch _most_ values that exceed the threshold up front. Those that slip through will still be on the small side (read: sufficiently fast), and will get caught by the existing check so that the limit remains exact.
|
||||
|
||||
The justification for the current check. The C code check is:
|
||||
```c
|
||||
max_str_digits / (3 * PyLong_SHIFT) <= (size_a - 11) / 10
|
||||
```
|
||||
|
||||
In GitHub markdown math-speak, writing $M$ for `max_str_digits`, $L$ for `PyLong_SHIFT` and $s$ for `size_a`, that check is:
|
||||
$$\left\lfloor\frac{M}{3L}\right\rfloor \le \left\lfloor\frac{s - 11}{10}\right\rfloor$$
|
||||
|
||||
From this it follows that
|
||||
$$\frac{M}{3L} < \frac{s-1}{10}$$
|
||||
hence that
|
||||
$$\frac{L(s-1)}{M} > \frac{10}{3} > \log_2(10).$$
|
||||
So
|
||||
$$2^{L(s-1)} > 10^M.$$
|
||||
But our input integer $a$ satisfies $|a| \ge 2^{L(s-1)}$, so $|a|$ is larger than $10^M$. This shows that we don't accidentally capture anything _below_ the intended limit in the check.
|
||||
|
||||
<!-- gh-issue-number: gh-95778 -->
|
||||
* Issue: gh-95778
|
||||
<!-- /gh-issue-number -->
|
||||
|
||||
Co-authored-by: Gregory P. Smith [Google LLC] <greg@krypto.org>
|
||||
(cherry picked from commit b126196838bbaf5f4d35120e0e6bcde435b0b480)
|
||||
|
||||
Co-authored-by: Mark Dickinson <dickinsm@gmail.com>
|
||||
---
|
||||
Include/internal/pycore_long.h | 4 +-
|
||||
Lib/test/test_int.py | 82 ++++++++++++++++++++++
|
||||
...2022-08-07-16-53-38.gh-issue-95778.ch010gps.rst | 2 +-
|
||||
Objects/longobject.c | 26 +++++--
|
||||
4 files changed, 107 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h
|
||||
index ee9a592..90069f8 100644
|
||||
--- a/Include/internal/pycore_long.h
|
||||
+++ b/Include/internal/pycore_long.h
|
||||
@@ -18,9 +18,9 @@
|
||||
* everyone's existing deployed numpy test suite passes before
|
||||
* https://github.com/numpy/numpy/issues/22098 is widely available.
|
||||
*
|
||||
- * $ python -m timeit -s 's = * "1"*4300' 'int(s)'
|
||||
+ * $ python -m timeit -s 's = "1"*4300' 'int(s)'
|
||||
* 2000 loops, best of 5: 125 usec per loop
|
||||
- * $ python -m timeit -s 's = * "1"*4300; v = int(s)' 'str(v)'
|
||||
+ * $ python -m timeit -s 's = "1"*4300; v = int(s)' 'str(v)'
|
||||
* 1000 loops, best of 5: 311 usec per loop
|
||||
* (zen2 cloud VM)
|
||||
*
|
||||
diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py
|
||||
index 2f678ed..a578ca8 100644
|
||||
--- a/Lib/test/test_int.py
|
||||
+++ b/Lib/test/test_int.py
|
||||
@@ -1,4 +1,5 @@
|
||||
import sys
|
||||
+import time
|
||||
|
||||
import unittest
|
||||
from test import support
|
||||
@@ -623,6 +624,87 @@ def test_max_str_digits(self):
|
||||
with self.assertRaises(ValueError):
|
||||
str(i)
|
||||
|
||||
+ def test_denial_of_service_prevented_int_to_str(self):
|
||||
+ """Regression test: ensure we fail before performing O(N**2) work."""
|
||||
+ maxdigits = sys.get_int_max_str_digits()
|
||||
+ assert maxdigits < 50_000, maxdigits # A test prerequisite.
|
||||
+ get_time = time.process_time
|
||||
+ if get_time() <= 0: # some platforms like WASM lack process_time()
|
||||
+ get_time = time.monotonic
|
||||
+
|
||||
+ huge_int = int(f'0x{"c"*65_000}', base=16) # 78268 decimal digits.
|
||||
+ digits = 78_268
|
||||
+ with support.adjust_int_max_str_digits(digits):
|
||||
+ start = get_time()
|
||||
+ huge_decimal = str(huge_int)
|
||||
+ seconds_to_convert = get_time() - start
|
||||
+ self.assertEqual(len(huge_decimal), digits)
|
||||
+ # Ensuring that we chose a slow enough conversion to measure.
|
||||
+ # It takes 0.1 seconds on a Zen based cloud VM in an opt build.
|
||||
+ if seconds_to_convert < 0.005:
|
||||
+ raise unittest.SkipTest('"slow" conversion took only '
|
||||
+ f'{seconds_to_convert} seconds.')
|
||||
+
|
||||
+ # We test with the limit almost at the size needed to check performance.
|
||||
+ # The performant limit check is slightly fuzzy, give it a some room.
|
||||
+ with support.adjust_int_max_str_digits(int(.995 * digits)):
|
||||
+ with self.assertRaises(ValueError) as err:
|
||||
+ start = get_time()
|
||||
+ str(huge_int)
|
||||
+ seconds_to_fail_huge = get_time() - start
|
||||
+ self.assertIn('conversion', str(err.exception))
|
||||
+ self.assertLess(seconds_to_fail_huge, seconds_to_convert/8)
|
||||
+
|
||||
+ # Now we test that a conversion that would take 30x as long also fails
|
||||
+ # in a similarly fast fashion.
|
||||
+ extra_huge_int = int(f'0x{"c"*500_000}', base=16) # 602060 digits.
|
||||
+ with self.assertRaises(ValueError) as err:
|
||||
+ start = get_time()
|
||||
+ # If not limited, 8 seconds said Zen based cloud VM.
|
||||
+ str(extra_huge_int)
|
||||
+ seconds_to_fail_extra_huge = get_time() - start
|
||||
+ self.assertIn('conversion', str(err.exception))
|
||||
+ self.assertLess(seconds_to_fail_extra_huge, seconds_to_convert/8)
|
||||
+
|
||||
+ def test_denial_of_service_prevented_str_to_int(self):
|
||||
+ """Regression test: ensure we fail before performing O(N**2) work."""
|
||||
+ maxdigits = sys.get_int_max_str_digits()
|
||||
+ assert maxdigits < 100_000, maxdigits # A test prerequisite.
|
||||
+ get_time = time.process_time
|
||||
+ if get_time() <= 0: # some platforms like WASM lack process_time()
|
||||
+ get_time = time.monotonic
|
||||
+
|
||||
+ digits = 133700
|
||||
+ huge = '8'*digits
|
||||
+ with support.adjust_int_max_str_digits(digits):
|
||||
+ start = get_time()
|
||||
+ int(huge)
|
||||
+ seconds_to_convert = get_time() - start
|
||||
+ # Ensuring that we chose a slow enough conversion to measure.
|
||||
+ # It takes 0.1 seconds on a Zen based cloud VM in an opt build.
|
||||
+ if seconds_to_convert < 0.005:
|
||||
+ raise unittest.SkipTest('"slow" conversion took only '
|
||||
+ f'{seconds_to_convert} seconds.')
|
||||
+
|
||||
+ with support.adjust_int_max_str_digits(digits - 1):
|
||||
+ with self.assertRaises(ValueError) as err:
|
||||
+ start = get_time()
|
||||
+ int(huge)
|
||||
+ seconds_to_fail_huge = get_time() - start
|
||||
+ self.assertIn('conversion', str(err.exception))
|
||||
+ self.assertLess(seconds_to_fail_huge, seconds_to_convert/8)
|
||||
+
|
||||
+ # Now we test that a conversion that would take 30x as long also fails
|
||||
+ # in a similarly fast fashion.
|
||||
+ extra_huge = '7'*1_200_000
|
||||
+ with self.assertRaises(ValueError) as err:
|
||||
+ start = get_time()
|
||||
+ # If not limited, 8 seconds in the Zen based cloud VM.
|
||||
+ int(extra_huge)
|
||||
+ seconds_to_fail_extra_huge = get_time() - start
|
||||
+ self.assertIn('conversion', str(err.exception))
|
||||
+ self.assertLess(seconds_to_fail_extra_huge, seconds_to_convert/8)
|
||||
+
|
||||
def test_power_of_two_bases_unlimited(self):
|
||||
"""The limit does not apply to power of 2 bases."""
|
||||
maxdigits = sys.get_int_max_str_digits()
|
||||
diff --git a/Misc/NEWS.d/next/Security/2022-08-07-16-53-38.gh-issue-95778.ch010gps.rst b/Misc/NEWS.d/next/Security/2022-08-07-16-53-38.gh-issue-95778.ch010gps.rst
|
||||
index ea3b85d..8eb8a34 100644
|
||||
--- a/Misc/NEWS.d/next/Security/2022-08-07-16-53-38.gh-issue-95778.ch010gps.rst
|
||||
+++ b/Misc/NEWS.d/next/Security/2022-08-07-16-53-38.gh-issue-95778.ch010gps.rst
|
||||
@@ -11,4 +11,4 @@ limitation <int_max_str_digits>` 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, and Ned Deily.
|
||||
+from Victor Stinner, Thomas Wouters, Steve Dower, Ned Deily, and Mark Dickinson.
|
||||
diff --git a/Objects/longobject.c b/Objects/longobject.c
|
||||
index 780ea81..aea5edc 100644
|
||||
--- a/Objects/longobject.c
|
||||
+++ b/Objects/longobject.c
|
||||
@@ -36,7 +36,8 @@ class int "PyObject *" "&PyLong_Type"
|
||||
#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)
|
||||
#define IS_SMALL_UINT(ival) ((ival) < NSMALLPOSINTS)
|
||||
|
||||
-#define _MAX_STR_DIGITS_ERROR_FMT "Exceeds the limit (%d) for integer string conversion: value has %zd digits"
|
||||
+#define _MAX_STR_DIGITS_ERROR_FMT_TO_INT "Exceeds the limit (%d) for integer string conversion: value has %zd digits"
|
||||
+#define _MAX_STR_DIGITS_ERROR_FMT_TO_STR "Exceeds the limit (%d) for integer string conversion"
|
||||
|
||||
static PyObject *
|
||||
get_small_int(sdigit ival)
|
||||
@@ -1604,6 +1605,23 @@ class int "PyObject *" "&PyLong_Type"
|
||||
size_a = Py_ABS(Py_SIZE(a));
|
||||
negative = Py_SIZE(a) < 0;
|
||||
|
||||
+ /* quick and dirty pre-check for overflowing the decimal digit limit,
|
||||
+ based on the inequality 10/3 >= log2(10)
|
||||
+
|
||||
+ explanation in https://github.com/python/cpython/pull/96537
|
||||
+ */
|
||||
+ if (size_a >= 10 * _PY_LONG_MAX_STR_DIGITS_THRESHOLD
|
||||
+ / (3 * PyLong_SHIFT) + 2) {
|
||||
+ PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
+ int max_str_digits = interp->int_max_str_digits;
|
||||
+ if ((max_str_digits > 0) &&
|
||||
+ (max_str_digits / (3 * PyLong_SHIFT) <= (size_a - 11) / 10)) {
|
||||
+ PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT_TO_STR,
|
||||
+ max_str_digits);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* quick and dirty upper bound for the number of digits
|
||||
required to express a in base _PyLong_DECIMAL_BASE:
|
||||
|
||||
@@ -1669,8 +1687,8 @@ class int "PyObject *" "&PyLong_Type"
|
||||
Py_ssize_t strlen_nosign = strlen - negative;
|
||||
if ((max_str_digits > 0) && (strlen_nosign > max_str_digits)) {
|
||||
Py_DECREF(scratch);
|
||||
- PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT,
|
||||
- max_str_digits, strlen_nosign);
|
||||
+ PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT_TO_STR,
|
||||
+ max_str_digits);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -2344,7 +2362,7 @@ that triggers it(!). Instead the code was tested by artificially allocating
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
int max_str_digits = interp->int_max_str_digits;
|
||||
if ((max_str_digits > 0) && (digits > max_str_digits)) {
|
||||
- PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT,
|
||||
+ PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT_TO_INT,
|
||||
max_str_digits, digits);
|
||||
return NULL;
|
||||
}
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,149 +0,0 @@
|
||||
From b9509ba7a9c668b984dab876c7926fe1dc5aa0ba Mon Sep 17 00:00:00 2001
|
||||
From: Petr Viktorin <encukou@gmail.com>
|
||||
Date: Fri, 3 Jun 2022 11:43:35 +0200
|
||||
Subject: [PATCH] gh-68966: Make mailcap refuse to match unsafe
|
||||
filenames/types/params (GH-91993)
|
||||
|
||||
---
|
||||
Doc/library/mailcap.rst | 12 +++++++++
|
||||
Lib/mailcap.py | 26 +++++++++++++++++--
|
||||
Lib/test/test_mailcap.py | 8 ++++--
|
||||
...2-04-27-18-25-30.gh-issue-68966.gjS8zs.rst | 4 +++
|
||||
4 files changed, 46 insertions(+), 4 deletions(-)
|
||||
create mode 100644 Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst
|
||||
|
||||
diff --git a/Doc/library/mailcap.rst b/Doc/library/mailcap.rst
|
||||
index 5490c8468d..bfaedb4609 100644
|
||||
--- a/Doc/library/mailcap.rst
|
||||
+++ b/Doc/library/mailcap.rst
|
||||
@@ -60,6 +60,18 @@ standard. However, mailcap files are supported on most Unix systems.
|
||||
use) to determine whether or not the mailcap line applies. :func:`findmatch`
|
||||
will automatically check such conditions and skip the entry if the check fails.
|
||||
|
||||
+ .. versionchanged:: 3.11
|
||||
+
|
||||
+ To prevent security issues with shell metacharacters (symbols that have
|
||||
+ special effects in a shell command line), ``findmatch`` will refuse
|
||||
+ to inject ASCII characters other than alphanumerics and ``@+=:,./-_``
|
||||
+ into the returned command line.
|
||||
+
|
||||
+ If a disallowed character appears in *filename*, ``findmatch`` will always
|
||||
+ return ``(None, None)`` as if no entry was found.
|
||||
+ If such a character appears elsewhere (a value in *plist* or in *MIMEtype*),
|
||||
+ ``findmatch`` will ignore all mailcap entries which use that value.
|
||||
+ A :mod:`warning <warnings>` will be raised in either case.
|
||||
|
||||
.. function:: getcaps()
|
||||
|
||||
diff --git a/Lib/mailcap.py b/Lib/mailcap.py
|
||||
index 856b6a5547..7278ea7051 100644
|
||||
--- a/Lib/mailcap.py
|
||||
+++ b/Lib/mailcap.py
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import os
|
||||
import warnings
|
||||
+import re
|
||||
|
||||
__all__ = ["getcaps","findmatch"]
|
||||
|
||||
@@ -19,6 +20,11 @@ def lineno_sort_key(entry):
|
||||
else:
|
||||
return 1, 0
|
||||
|
||||
+_find_unsafe = re.compile(r'[^\xa1-\U0010FFFF\w@+=:,./-]').search
|
||||
+
|
||||
+class UnsafeMailcapInput(Warning):
|
||||
+ """Warning raised when refusing unsafe input"""
|
||||
+
|
||||
|
||||
# Part 1: top-level interface.
|
||||
|
||||
@@ -171,15 +177,22 @@ def findmatch(caps, MIMEtype, key='view', filename="/dev/null", plist=[]):
|
||||
entry to use.
|
||||
|
||||
"""
|
||||
+ if _find_unsafe(filename):
|
||||
+ msg = "Refusing to use mailcap with filename %r. Use a safe temporary filename." % (filename,)
|
||||
+ warnings.warn(msg, UnsafeMailcapInput)
|
||||
+ return None, None
|
||||
entries = lookup(caps, MIMEtype, key)
|
||||
# XXX This code should somehow check for the needsterminal flag.
|
||||
for e in entries:
|
||||
if 'test' in e:
|
||||
test = subst(e['test'], filename, plist)
|
||||
+ if test is None:
|
||||
+ continue
|
||||
if test and os.system(test) != 0:
|
||||
continue
|
||||
command = subst(e[key], MIMEtype, filename, plist)
|
||||
- return command, e
|
||||
+ if command is not None:
|
||||
+ return command, e
|
||||
return None, None
|
||||
|
||||
def lookup(caps, MIMEtype, key=None):
|
||||
@@ -212,6 +225,10 @@ def subst(field, MIMEtype, filename, plist=[]):
|
||||
elif c == 's':
|
||||
res = res + filename
|
||||
elif c == 't':
|
||||
+ if _find_unsafe(MIMEtype):
|
||||
+ msg = "Refusing to substitute MIME type %r into a shell command." % (MIMEtype,)
|
||||
+ warnings.warn(msg, UnsafeMailcapInput)
|
||||
+ return None
|
||||
res = res + MIMEtype
|
||||
elif c == '{':
|
||||
start = i
|
||||
@@ -219,7 +236,12 @@ def subst(field, MIMEtype, filename, plist=[]):
|
||||
i = i+1
|
||||
name = field[start:i]
|
||||
i = i+1
|
||||
- res = res + findparam(name, plist)
|
||||
+ param = findparam(name, plist)
|
||||
+ if _find_unsafe(param):
|
||||
+ msg = "Refusing to substitute parameter %r (%s) into a shell command" % (param, name)
|
||||
+ warnings.warn(msg, UnsafeMailcapInput)
|
||||
+ return None
|
||||
+ res = res + param
|
||||
# XXX To do:
|
||||
# %n == number of parts if type is multipart/*
|
||||
# %F == list of alternating type and filename for parts
|
||||
diff --git a/Lib/test/test_mailcap.py b/Lib/test/test_mailcap.py
|
||||
index d3995b1472..8185f4a780 100644
|
||||
--- a/Lib/test/test_mailcap.py
|
||||
+++ b/Lib/test/test_mailcap.py
|
||||
@@ -128,7 +128,8 @@ def test_subst(self):
|
||||
(["", "audio/*", "foo.txt"], ""),
|
||||
(["echo foo", "audio/*", "foo.txt"], "echo foo"),
|
||||
(["echo %s", "audio/*", "foo.txt"], "echo foo.txt"),
|
||||
- (["echo %t", "audio/*", "foo.txt"], "echo audio/*"),
|
||||
+ (["echo %t", "audio/*", "foo.txt"], None),
|
||||
+ (["echo %t", "audio/wav", "foo.txt"], "echo audio/wav"),
|
||||
(["echo \\%t", "audio/*", "foo.txt"], "echo %t"),
|
||||
(["echo foo", "audio/*", "foo.txt", plist], "echo foo"),
|
||||
(["echo %{total}", "audio/*", "foo.txt", plist], "echo 3")
|
||||
@@ -212,7 +213,10 @@ def test_findmatch(self):
|
||||
('"An audio fragment"', audio_basic_entry)),
|
||||
([c, "audio/*"],
|
||||
{"filename": fname},
|
||||
- ("/usr/local/bin/showaudio audio/*", audio_entry)),
|
||||
+ (None, None)),
|
||||
+ ([c, "audio/wav"],
|
||||
+ {"filename": fname},
|
||||
+ ("/usr/local/bin/showaudio audio/wav", audio_entry)),
|
||||
([c, "message/external-body"],
|
||||
{"plist": plist},
|
||||
("showexternal /dev/null default john python.org /tmp foo bar", message_entry))
|
||||
diff --git a/Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst b/Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst
|
||||
new file mode 100644
|
||||
index 0000000000..da81a1f699
|
||||
--- /dev/null
|
||||
+++ b/Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst
|
||||
@@ -0,0 +1,4 @@
|
||||
+The deprecated mailcap module now refuses to inject unsafe text (filenames,
|
||||
+MIME types, parameters) into shell commands. Instead of using such text, it
|
||||
+will warn and act as if a match was not found (or for test commands, as if
|
||||
+the test failed).
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,131 +0,0 @@
|
||||
From 5715382d3a89ca118ce2e224d8c69550d21fe51b Mon Sep 17 00:00:00 2001
|
||||
From: "Miss Islington (bot)"
|
||||
<31488909+miss-islington@users.noreply.github.com>
|
||||
Date: Tue, 21 Jun 2022 14:36:55 -0700
|
||||
Subject: [PATCH] gh-87389: Fix an open redirection vulnerability in
|
||||
http.server. (GH-93879)
|
||||
|
||||
Fix an open redirection vulnerability in the `http.server` module when
|
||||
an URI path starts with `//` that could produce a 301 Location header
|
||||
with a misleading target. Vulnerability discovered, and logic fix
|
||||
proposed, by Hamza Avvan (@hamzaavvan).
|
||||
|
||||
Test and comments authored by Gregory P. Smith [Google].
|
||||
(cherry picked from commit 4abab6b603dd38bec1168e9a37c40a48ec89508e)
|
||||
|
||||
Co-authored-by: Gregory P. Smith <greg@krypto.org>
|
||||
---
|
||||
Lib/http/server.py | 7 +++
|
||||
Lib/test/test_httpservers.py | 53 +++++++++++++++++++++-
|
||||
.../2022-06-15-20-09-23.gh-issue-87389.QVaC3f.rst | 3 ++
|
||||
3 files changed, 61 insertions(+), 2 deletions(-)
|
||||
create mode 100644 Misc/NEWS.d/next/Security/2022-06-15-20-09-23.gh-issue-87389.QVaC3f.rst
|
||||
|
||||
diff --git a/Lib/http/server.py b/Lib/http/server.py
|
||||
index e985dfd..78748c6 100644
|
||||
--- a/Lib/http/server.py
|
||||
+++ b/Lib/http/server.py
|
||||
@@ -332,6 +332,13 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler):
|
||||
return False
|
||||
self.command, self.path = command, path
|
||||
|
||||
+ # gh-87389: The purpose of replacing '//' with '/' is to protect
|
||||
+ # against open redirect attacks possibly triggered if the path starts
|
||||
+ # with '//' because http clients treat //path as an absolute URI
|
||||
+ # without scheme (similar to http://path) rather than a path.
|
||||
+ if self.path.startswith('//'):
|
||||
+ self.path = '/' + self.path.lstrip('/') # Reduce to a single /
|
||||
+
|
||||
# Examine the headers and look for a Connection directive.
|
||||
try:
|
||||
self.headers = http.client.parse_headers(self.rfile,
|
||||
diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py
|
||||
index 1cc020f..8fdbab4 100644
|
||||
--- a/Lib/test/test_httpservers.py
|
||||
+++ b/Lib/test/test_httpservers.py
|
||||
@@ -333,7 +333,7 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
pass
|
||||
|
||||
def setUp(self):
|
||||
- BaseTestCase.setUp(self)
|
||||
+ super().setUp()
|
||||
self.cwd = os.getcwd()
|
||||
basetempdir = tempfile.gettempdir()
|
||||
os.chdir(basetempdir)
|
||||
@@ -361,7 +361,7 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
- BaseTestCase.tearDown(self)
|
||||
+ super().tearDown()
|
||||
|
||||
def check_status_and_reason(self, response, status, data=None):
|
||||
def close_conn():
|
||||
@@ -417,6 +417,55 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
self.check_status_and_reason(response, HTTPStatus.OK,
|
||||
data=os_helper.TESTFN_UNDECODABLE)
|
||||
|
||||
+ def test_get_dir_redirect_location_domain_injection_bug(self):
|
||||
+ """Ensure //evil.co/..%2f../../X does not put //evil.co/ in Location.
|
||||
+
|
||||
+ //netloc/ in a Location header is a redirect to a new host.
|
||||
+ https://github.com/python/cpython/issues/87389
|
||||
+
|
||||
+ This checks that a path resolving to a directory on our server cannot
|
||||
+ resolve into a redirect to another server.
|
||||
+ """
|
||||
+ os.mkdir(os.path.join(self.tempdir, 'existing_directory'))
|
||||
+ url = f'/python.org/..%2f..%2f..%2f..%2f..%2f../%0a%0d/../{self.tempdir_name}/existing_directory'
|
||||
+ expected_location = f'{url}/' # /python.org.../ single slash single prefix, trailing slash
|
||||
+ # Canonicalizes to /tmp/tempdir_name/existing_directory which does
|
||||
+ # exist and is a dir, triggering the 301 redirect logic.
|
||||
+ response = self.request(url)
|
||||
+ self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY)
|
||||
+ location = response.getheader('Location')
|
||||
+ self.assertEqual(location, expected_location, msg='non-attack failed!')
|
||||
+
|
||||
+ # //python.org... multi-slash prefix, no trailing slash
|
||||
+ attack_url = f'/{url}'
|
||||
+ response = self.request(attack_url)
|
||||
+ self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY)
|
||||
+ location = response.getheader('Location')
|
||||
+ self.assertFalse(location.startswith('//'), msg=location)
|
||||
+ self.assertEqual(location, expected_location,
|
||||
+ msg='Expected Location header to start with a single / and '
|
||||
+ 'end with a / as this is a directory redirect.')
|
||||
+
|
||||
+ # ///python.org... triple-slash prefix, no trailing slash
|
||||
+ attack3_url = f'//{url}'
|
||||
+ response = self.request(attack3_url)
|
||||
+ self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY)
|
||||
+ self.assertEqual(response.getheader('Location'), expected_location)
|
||||
+
|
||||
+ # If the second word in the http request (Request-URI for the http
|
||||
+ # method) is a full URI, we don't worry about it, as that'll be parsed
|
||||
+ # and reassembled as a full URI within BaseHTTPRequestHandler.send_head
|
||||
+ # so no errant scheme-less //netloc//evil.co/ domain mixup can happen.
|
||||
+ attack_scheme_netloc_2slash_url = f'https://pypi.org/{url}'
|
||||
+ expected_scheme_netloc_location = f'{attack_scheme_netloc_2slash_url}/'
|
||||
+ response = self.request(attack_scheme_netloc_2slash_url)
|
||||
+ self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY)
|
||||
+ location = response.getheader('Location')
|
||||
+ # We're just ensuring that the scheme and domain make it through, if
|
||||
+ # there are or aren't multiple slashes at the start of the path that
|
||||
+ # follows that isn't important in this Location: header.
|
||||
+ self.assertTrue(location.startswith('https://pypi.org/'), msg=location)
|
||||
+
|
||||
def test_get(self):
|
||||
#constructs the path relative to the root directory of the HTTPServer
|
||||
response = self.request(self.base_url + '/test')
|
||||
diff --git a/Misc/NEWS.d/next/Security/2022-06-15-20-09-23.gh-issue-87389.QVaC3f.rst b/Misc/NEWS.d/next/Security/2022-06-15-20-09-23.gh-issue-87389.QVaC3f.rst
|
||||
new file mode 100644
|
||||
index 0000000..029d437
|
||||
--- /dev/null
|
||||
+++ b/Misc/NEWS.d/next/Security/2022-06-15-20-09-23.gh-issue-87389.QVaC3f.rst
|
||||
@@ -0,0 +1,3 @@
|
||||
+:mod:`http.server`: Fix an open redirection vulnerability in the HTTP server
|
||||
+when an URI path starts with ``//``. Vulnerability discovered, and initial
|
||||
+fix proposed, by Hamza Avvan.
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,103 +0,0 @@
|
||||
From 0e4e058602d93b88256ff90bbef501ba20be9dd3 Mon Sep 17 00:00:00 2001
|
||||
From: Theo Buehler <botovq@users.noreply.github.com>
|
||||
Date: Fri, 21 Oct 2022 21:26:01 +0200
|
||||
Subject: [PATCH] [3.10] gh-98517: Fix buffer overflows in _sha3 module
|
||||
(#98519)
|
||||
|
||||
This is a port of the applicable part of XKCP's fix [1] for
|
||||
CVE-2022-37454 and avoids the segmentation fault and the infinite
|
||||
loop in the test cases published in [2].
|
||||
|
||||
[1]:
|
||||
https://github.com/XKCP/XKCP/commit/fdc6fef075f4e81d6b1bc38364248975e08e340a
|
||||
[2]: https://mouha.be/sha-3-buffer-overflow/
|
||||
|
||||
Regression test added by: Gregory P. Smith [Google LLC]
|
||||
<greg@krypto.org>
|
||||
|
||||
---
|
||||
Lib/test/test_hashlib.py | 9 +++++++++
|
||||
.../2022-10-21-13-31-47.gh-issue-98517.SXXGfV.rst | 1 +
|
||||
Modules/_sha3/kcp/KeccakSponge.inc | 15 ++++++++-------
|
||||
3 files changed, 18 insertions(+), 7 deletions(-)
|
||||
create mode 100644 Misc/NEWS.d/next/Security/2022-10-21-13-31-47.gh-issue-98517.SXXGfV.rst
|
||||
|
||||
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
|
||||
index 110eb48..378127a 100644
|
||||
--- a/Lib/test/test_hashlib.py
|
||||
+++ b/Lib/test/test_hashlib.py
|
||||
@@ -481,6 +481,15 @@ class HashLibTestCase(unittest.TestCase):
|
||||
def test_case_md5_uintmax(self, size):
|
||||
self.check('md5', b'A'*size, '28138d306ff1b8281f1a9067e1a1a2b3')
|
||||
|
||||
+ @unittest.skipIf(sys.maxsize < _4G - 1, 'test cannot run on 32-bit systems')
|
||||
+ @bigmemtest(size=_4G - 1, memuse=1, dry_run=False)
|
||||
+ def test_sha3_update_overflow(self, size):
|
||||
+ """Regression test for gh-98517 CVE-2022-37454."""
|
||||
+ h = hashlib.sha3_224()
|
||||
+ h.update(b'\x01')
|
||||
+ h.update(b'\x01'*0xffff_ffff)
|
||||
+ self.assertEqual(h.hexdigest(), '80762e8ce6700f114fec0f621fd97c4b9c00147fa052215294cceeed')
|
||||
+
|
||||
# use the three examples from Federal Information Processing Standards
|
||||
# Publication 180-1, Secure Hash Standard, 1995 April 17
|
||||
# http://www.itl.nist.gov/div897/pubs/fip180-1.htm
|
||||
diff --git a/Misc/NEWS.d/next/Security/2022-10-21-13-31-47.gh-issue-98517.SXXGfV.rst b/Misc/NEWS.d/next/Security/2022-10-21-13-31-47.gh-issue-98517.SXXGfV.rst
|
||||
new file mode 100644
|
||||
index 0000000..2d23a6a
|
||||
--- /dev/null
|
||||
+++ b/Misc/NEWS.d/next/Security/2022-10-21-13-31-47.gh-issue-98517.SXXGfV.rst
|
||||
@@ -0,0 +1 @@
|
||||
+Port XKCP's fix for the buffer overflows in SHA-3 (CVE-2022-37454).
|
||||
diff --git a/Modules/_sha3/kcp/KeccakSponge.inc b/Modules/_sha3/kcp/KeccakSponge.inc
|
||||
index e10739d..cf92e4d 100644
|
||||
--- a/Modules/_sha3/kcp/KeccakSponge.inc
|
||||
+++ b/Modules/_sha3/kcp/KeccakSponge.inc
|
||||
@@ -171,7 +171,7 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat
|
||||
i = 0;
|
||||
curData = data;
|
||||
while(i < dataByteLen) {
|
||||
- if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) {
|
||||
+ if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) {
|
||||
#ifdef SnP_FastLoop_Absorb
|
||||
/* processing full blocks first */
|
||||
|
||||
@@ -199,10 +199,10 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat
|
||||
}
|
||||
else {
|
||||
/* normal lane: using the message queue */
|
||||
-
|
||||
- partialBlock = (unsigned int)(dataByteLen - i);
|
||||
- if (partialBlock+instance->byteIOIndex > rateInBytes)
|
||||
+ if (dataByteLen-i > rateInBytes-instance->byteIOIndex)
|
||||
partialBlock = rateInBytes-instance->byteIOIndex;
|
||||
+ else
|
||||
+ partialBlock = (unsigned int)(dataByteLen - i);
|
||||
#ifdef KeccakReference
|
||||
displayBytes(1, "Block to be absorbed (part)", curData, partialBlock);
|
||||
#endif
|
||||
@@ -281,7 +281,7 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte
|
||||
i = 0;
|
||||
curData = data;
|
||||
while(i < dataByteLen) {
|
||||
- if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) {
|
||||
+ if ((instance->byteIOIndex == rateInBytes) && (dataByteLen-i >= rateInBytes)) {
|
||||
for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
|
||||
SnP_Permute(instance->state);
|
||||
SnP_ExtractBytes(instance->state, curData, 0, rateInBytes);
|
||||
@@ -299,9 +299,10 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte
|
||||
SnP_Permute(instance->state);
|
||||
instance->byteIOIndex = 0;
|
||||
}
|
||||
- partialBlock = (unsigned int)(dataByteLen - i);
|
||||
- if (partialBlock+instance->byteIOIndex > rateInBytes)
|
||||
+ if (dataByteLen-i > rateInBytes-instance->byteIOIndex)
|
||||
partialBlock = rateInBytes-instance->byteIOIndex;
|
||||
+ else
|
||||
+ partialBlock = (unsigned int)(dataByteLen - i);
|
||||
i += partialBlock;
|
||||
|
||||
SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -1,71 +0,0 @@
|
||||
From eae692eed18892309bcc25a2c0f8980038305ea2 Mon Sep 17 00:00:00 2001
|
||||
From: "Miss Islington (bot)"
|
||||
<31488909+miss-islington@users.noreply.github.com>
|
||||
Date: Thu, 20 Oct 2022 16:55:51 -0700
|
||||
Subject: [PATCH] [3.10] gh-97514: Don't use Linux abstract sockets for
|
||||
multiprocessing (GH-98501) (GH-98503)
|
||||
|
||||
Linux abstract sockets are insecure as they lack any form of filesystem
|
||||
permissions so their use allows anyone on the system to inject code into
|
||||
the process.
|
||||
|
||||
This removes the default preference for abstract sockets in
|
||||
multiprocessing introduced in Python 3.9+ via
|
||||
https://github.com/python/cpython/pull/18866 while fixing
|
||||
https://github.com/python/cpython/issues/84031.
|
||||
|
||||
Explicit use of an abstract socket by a user now generates a
|
||||
RuntimeWarning. If we choose to keep this warning, it should be
|
||||
backported to the 3.7 and 3.8 branches.
|
||||
(cherry picked from commit 49f61068f49747164988ffc5a442d2a63874fc17)
|
||||
|
||||
|
||||
Co-authored-by: Gregory P. Smith <greg@krypto.org>
|
||||
|
||||
Automerge-Triggered-By: GH:gpshead
|
||||
---
|
||||
Lib/multiprocessing/connection.py | 5 -----
|
||||
.../2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst | 15 +++++++++++++++
|
||||
2 files changed, 15 insertions(+), 5 deletions(-)
|
||||
create mode 100644 Misc/NEWS.d/next/Security/2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst
|
||||
|
||||
diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py
|
||||
index 510e4b5aba..8e2facf92a 100644
|
||||
--- a/Lib/multiprocessing/connection.py
|
||||
+++ b/Lib/multiprocessing/connection.py
|
||||
@@ -73,11 +73,6 @@ def arbitrary_address(family):
|
||||
if family == 'AF_INET':
|
||||
return ('localhost', 0)
|
||||
elif family == 'AF_UNIX':
|
||||
- # Prefer abstract sockets if possible to avoid problems with the address
|
||||
- # size. When coding portable applications, some implementations have
|
||||
- # sun_path as short as 92 bytes in the sockaddr_un struct.
|
||||
- if util.abstract_sockets_supported:
|
||||
- return f"\0listener-{os.getpid()}-{next(_mmap_counter)}"
|
||||
return tempfile.mktemp(prefix='listener-', dir=util.get_temp_dir())
|
||||
elif family == 'AF_PIPE':
|
||||
return tempfile.mktemp(prefix=r'\\.\pipe\pyc-%d-%d-' %
|
||||
diff --git a/Misc/NEWS.d/next/Security/2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst b/Misc/NEWS.d/next/Security/2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst
|
||||
new file mode 100644
|
||||
index 0000000000..02d95b5705
|
||||
--- /dev/null
|
||||
+++ b/Misc/NEWS.d/next/Security/2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst
|
||||
@@ -0,0 +1,15 @@
|
||||
+On Linux the :mod:`multiprocessing` module returns to using filesystem backed
|
||||
+unix domain sockets for communication with the *forkserver* process instead of
|
||||
+the Linux abstract socket namespace. Only code that chooses to use the
|
||||
+:ref:`"forkserver" start method <multiprocessing-start-methods>` is affected.
|
||||
+
|
||||
+Abstract sockets have no permissions and could allow any user on the system in
|
||||
+the same `network namespace
|
||||
+<https://man7.org/linux/man-pages/man7/network_namespaces.7.html>`_ (often the
|
||||
+whole system) to inject code into the multiprocessing *forkserver* process.
|
||||
+This was a potential privilege escalation. Filesystem based socket permissions
|
||||
+restrict this to the *forkserver* process user as was the default in Python 3.8
|
||||
+and earlier.
|
||||
+
|
||||
+This prevents Linux `CVE-2022-42919
|
||||
+<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-42919>`_.
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -1,98 +0,0 @@
|
||||
From 9bb8e18ca46fe66fa6802602f8a7228a24dd785f Mon Sep 17 00:00:00 2001
|
||||
From: "Miss Islington (bot)"
|
||||
<31488909+miss-islington@users.noreply.github.com>
|
||||
Date: Mon, 7 Nov 2022 19:23:16 -0800
|
||||
Subject: [PATCH] [3.11] gh-98433: Fix quadratic time idna decoding. (GH-99092)
|
||||
(GH-99222)
|
||||
|
||||
There was an unnecessary quadratic loop in idna decoding. This restores
|
||||
the behavior to linear.
|
||||
|
||||
(cherry picked from commit d315722564927c7202dd6e111dc79eaf14240b0d)
|
||||
|
||||
(cherry picked from commit a6f6c3a3d6f2b580f2d87885c9b8a9350ad7bf15)
|
||||
|
||||
Co-authored-by: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
|
||||
Co-authored-by: Gregory P. Smith <greg@krypto.org>
|
||||
---
|
||||
Lib/encodings/idna.py | 32 +++++++++----------
|
||||
Lib/test/test_codecs.py | 6 ++++
|
||||
...2-11-04-09-29-36.gh-issue-98433.l76c5G.rst | 6 ++++
|
||||
3 files changed, 27 insertions(+), 17 deletions(-)
|
||||
create mode 100644 Misc/NEWS.d/next/Security/2022-11-04-09-29-36.gh-issue-98433.l76c5G.rst
|
||||
|
||||
diff --git a/Lib/encodings/idna.py b/Lib/encodings/idna.py
|
||||
index ea40585..bf98f51 100644
|
||||
--- a/Lib/encodings/idna.py
|
||||
+++ b/Lib/encodings/idna.py
|
||||
@@ -39,23 +39,21 @@ def nameprep(label):
|
||||
|
||||
# Check bidi
|
||||
RandAL = [stringprep.in_table_d1(x) for x in label]
|
||||
- for c in RandAL:
|
||||
- if c:
|
||||
- # There is a RandAL char in the string. Must perform further
|
||||
- # tests:
|
||||
- # 1) The characters in section 5.8 MUST be prohibited.
|
||||
- # This is table C.8, which was already checked
|
||||
- # 2) If a string contains any RandALCat character, the string
|
||||
- # MUST NOT contain any LCat character.
|
||||
- if any(stringprep.in_table_d2(x) for x in label):
|
||||
- raise UnicodeError("Violation of BIDI requirement 2")
|
||||
-
|
||||
- # 3) If a string contains any RandALCat character, a
|
||||
- # RandALCat character MUST be the first character of the
|
||||
- # string, and a RandALCat character MUST be the last
|
||||
- # character of the string.
|
||||
- if not RandAL[0] or not RandAL[-1]:
|
||||
- raise UnicodeError("Violation of BIDI requirement 3")
|
||||
+ if any(RandAL):
|
||||
+ # There is a RandAL char in the string. Must perform further
|
||||
+ # tests:
|
||||
+ # 1) The characters in section 5.8 MUST be prohibited.
|
||||
+ # This is table C.8, which was already checked
|
||||
+ # 2) If a string contains any RandALCat character, the string
|
||||
+ # MUST NOT contain any LCat character.
|
||||
+ if any(stringprep.in_table_d2(x) for x in label):
|
||||
+ raise UnicodeError("Violation of BIDI requirement 2")
|
||||
+ # 3) If a string contains any RandALCat character, a
|
||||
+ # RandALCat character MUST be the first character of the
|
||||
+ # string, and a RandALCat character MUST be the last
|
||||
+ # character of the string.
|
||||
+ if not RandAL[0] or not RandAL[-1]:
|
||||
+ raise UnicodeError("Violation of BIDI requirement 3")
|
||||
|
||||
return label
|
||||
|
||||
diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py
|
||||
index f7310fb..439fab7 100644
|
||||
--- a/Lib/test/test_codecs.py
|
||||
+++ b/Lib/test/test_codecs.py
|
||||
@@ -1534,6 +1534,12 @@ class IDNACodecTest(unittest.TestCase):
|
||||
self.assertEqual("pyth\xf6n.org".encode("idna"), b"xn--pythn-mua.org")
|
||||
self.assertEqual("pyth\xf6n.org.".encode("idna"), b"xn--pythn-mua.org.")
|
||||
|
||||
+ def test_builtin_decode_length_limit(self):
|
||||
+ with self.assertRaisesRegex(UnicodeError, "too long"):
|
||||
+ (b"xn--016c"+b"a"*1100).decode("idna")
|
||||
+ with self.assertRaisesRegex(UnicodeError, "too long"):
|
||||
+ (b"xn--016c"+b"a"*70).decode("idna")
|
||||
+
|
||||
def test_stream(self):
|
||||
r = codecs.getreader("idna")(io.BytesIO(b"abc"))
|
||||
r.read(3)
|
||||
diff --git a/Misc/NEWS.d/next/Security/2022-11-04-09-29-36.gh-issue-98433.l76c5G.rst b/Misc/NEWS.d/next/Security/2022-11-04-09-29-36.gh-issue-98433.l76c5G.rst
|
||||
new file mode 100644
|
||||
index 0000000..5185fac
|
||||
--- /dev/null
|
||||
+++ b/Misc/NEWS.d/next/Security/2022-11-04-09-29-36.gh-issue-98433.l76c5G.rst
|
||||
@@ -0,0 +1,6 @@
|
||||
+The IDNA codec decoder used on DNS hostnames by :mod:`socket` or :mod:`asyncio`
|
||||
+related name resolution functions no longer involves a quadratic algorithm.
|
||||
+This prevents a potential CPU denial of service if an out-of-spec excessive
|
||||
+length hostname involving bidirectional characters were decoded. Some protocols
|
||||
+such as :mod:`urllib` http ``3xx`` redirects potentially allow for an attacker
|
||||
+to supply such a name.
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -1,104 +0,0 @@
|
||||
From 7da97f61816f3cadaa6788804b22a2434b40e8c5 Mon Sep 17 00:00:00 2001
|
||||
From: "Miss Islington (bot)"
|
||||
<31488909+miss-islington@users.noreply.github.com>
|
||||
Date: Mon, 21 Feb 2022 08:16:09 -0800
|
||||
Subject: [PATCH] bpo-46811: Make test suite support Expat >=2.4.5 (GH-31453)
|
||||
(GH-31472)
|
||||
|
||||
Curly brackets were never allowed in namespace URIs
|
||||
according to RFC 3986, and so-called namespace-validating
|
||||
XML parsers have the right to reject them a invalid URIs.
|
||||
|
||||
libexpat >=2.4.5 has become strcter in that regard due to
|
||||
related security issues; with ET.XML instantiating a
|
||||
namespace-aware parser under the hood, this test has no
|
||||
future in CPython.
|
||||
|
||||
References:
|
||||
- https://datatracker.ietf.org/doc/html/rfc3968
|
||||
- https://www.w3.org/TR/xml-names/
|
||||
|
||||
Also, test_minidom.py: Support Expat >=2.4.5
|
||||
(cherry picked from commit 2cae93832f46b245847bdc252456ddf7742ef45e)
|
||||
|
||||
Co-authored-by: Sebastian Pipping <sebastian@pipping.org>
|
||||
---
|
||||
Lib/test/test_minidom.py | 17 +++++++++++++++--
|
||||
Lib/test/test_xml_etree.py | 6 ------
|
||||
.../Library/2022-02-20-21-03-31.bpo-46811.8BxgdQ.rst | 1 +
|
||||
3 files changed, 16 insertions(+), 8 deletions(-)
|
||||
create mode 100644 Misc/NEWS.d/next/Library/2022-02-20-21-03-31.bpo-46811.8BxgdQ.rst
|
||||
|
||||
diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py
|
||||
index 1663b1f..9762025 100644
|
||||
--- a/Lib/test/test_minidom.py
|
||||
+++ b/Lib/test/test_minidom.py
|
||||
@@ -6,10 +6,12 @@ import io
|
||||
from test import support
|
||||
import unittest
|
||||
|
||||
+import pyexpat
|
||||
import xml.dom.minidom
|
||||
|
||||
from xml.dom.minidom import parse, Node, Document, parseString
|
||||
from xml.dom.minidom import getDOMImplementation
|
||||
+from xml.parsers.expat import ExpatError
|
||||
|
||||
|
||||
tstfile = support.findfile("test.xml", subdir="xmltestdata")
|
||||
@@ -1147,7 +1149,13 @@ class MinidomTest(unittest.TestCase):
|
||||
|
||||
# Verify that character decoding errors raise exceptions instead
|
||||
# of crashing
|
||||
- self.assertRaises(UnicodeDecodeError, parseString,
|
||||
+ if pyexpat.version_info >= (2, 4, 5):
|
||||
+ self.assertRaises(ExpatError, parseString,
|
||||
+ b'<fran\xe7ais></fran\xe7ais>')
|
||||
+ self.assertRaises(ExpatError, parseString,
|
||||
+ b'<franais>Comment \xe7a va ? Tr\xe8s bien ?</franais>')
|
||||
+ else:
|
||||
+ self.assertRaises(UnicodeDecodeError, parseString,
|
||||
b'<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
|
||||
|
||||
doc.unlink()
|
||||
@@ -1609,7 +1617,12 @@ class MinidomTest(unittest.TestCase):
|
||||
self.confirm(doc2.namespaceURI == xml.dom.EMPTY_NAMESPACE)
|
||||
|
||||
def testExceptionOnSpacesInXMLNSValue(self):
|
||||
- with self.assertRaisesRegex(ValueError, 'Unsupported syntax'):
|
||||
+ if pyexpat.version_info >= (2, 4, 5):
|
||||
+ context = self.assertRaisesRegex(ExpatError, 'syntax error')
|
||||
+ else:
|
||||
+ context = self.assertRaisesRegex(ValueError, 'Unsupported syntax')
|
||||
+
|
||||
+ with context:
|
||||
parseString('<element xmlns:abc="http:abc.com/de f g/hi/j k"><abc:foo /></element>')
|
||||
|
||||
def testDocRemoveChild(self):
|
||||
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
|
||||
index 285559a..4bd4291 100644
|
||||
--- a/Lib/test/test_xml_etree.py
|
||||
+++ b/Lib/test/test_xml_etree.py
|
||||
@@ -2183,12 +2183,6 @@ class BugsTest(unittest.TestCase):
|
||||
b"<?xml version='1.0' encoding='ascii'?>\n"
|
||||
b'<body>tãg</body>')
|
||||
|
||||
- def test_issue3151(self):
|
||||
- e = ET.XML('<prefix:localname xmlns:prefix="${stuff}"/>')
|
||||
- self.assertEqual(e.tag, '{${stuff}}localname')
|
||||
- t = ET.ElementTree(e)
|
||||
- self.assertEqual(ET.tostring(e), b'<ns0:localname xmlns:ns0="${stuff}" />')
|
||||
-
|
||||
def test_issue6565(self):
|
||||
elem = ET.XML("<body><tag/></body>")
|
||||
self.assertEqual(summarize_list(elem), ['tag'])
|
||||
diff --git a/Misc/NEWS.d/next/Library/2022-02-20-21-03-31.bpo-46811.8BxgdQ.rst b/Misc/NEWS.d/next/Library/2022-02-20-21-03-31.bpo-46811.8BxgdQ.rst
|
||||
new file mode 100644
|
||||
index 0000000..6969bd1
|
||||
--- /dev/null
|
||||
+++ b/Misc/NEWS.d/next/Library/2022-02-20-21-03-31.bpo-46811.8BxgdQ.rst
|
||||
@@ -0,0 +1 @@
|
||||
+Make test suite support Expat >=2.4.5
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
28
python3.spec
28
python3.spec
@ -2,8 +2,8 @@ Name: python3
|
||||
Summary: Interpreter of the Python3 programming language
|
||||
URL: https://www.python.org/
|
||||
|
||||
Version: 3.10.2
|
||||
Release: 12
|
||||
Version: 3.10.9
|
||||
Release: 1
|
||||
License: Python-2.0
|
||||
|
||||
%global branchversion 3.10
|
||||
@ -87,15 +87,6 @@ Source1: pyconfig.h
|
||||
|
||||
Patch1: 00001-rpath.patch
|
||||
Patch251: 00251-change-user-install-location.patch
|
||||
Patch6000: backport-bpo-46811-Make-test-suite-support-Expat-2.4.5.patch
|
||||
Patch6001: backport-CVE-2015-20107.patch
|
||||
Patch6002: backport-CVE-2021-28861.patch
|
||||
Patch6003: backport-0001-CVE-2020-10735.patch
|
||||
Patch6004: backport-0002-CVE-2020-10735.patch
|
||||
Patch6005: backport-0003-CVE-2020-10735.patch
|
||||
Patch6006: backport-CVE-2022-42919.patch
|
||||
Patch6007: backport-CVE-2022-45061.patch
|
||||
Patch6008: backport-CVE-2022-37454.patch
|
||||
|
||||
Patch9000: add-the-sm3-method-for-obtaining-the-salt-value.patch
|
||||
|
||||
@ -191,15 +182,6 @@ rm configure pyconfig.h.in
|
||||
|
||||
%patch1 -p1
|
||||
%patch251 -p1
|
||||
%patch6000 -p1
|
||||
%patch6001 -p1
|
||||
%patch6002 -p1
|
||||
%patch6003 -p1
|
||||
%patch6004 -p1
|
||||
%patch6005 -p1
|
||||
%patch6006 -p1
|
||||
%patch6007 -p1
|
||||
%patch6008 -p1
|
||||
|
||||
%patch9000 -p1
|
||||
|
||||
@ -817,6 +799,12 @@ export BEP_GTDLIST="$BEP_GTDLIST_TMP"
|
||||
%{_mandir}/*/*
|
||||
|
||||
%changelog
|
||||
* Mon Jan 30 2023 zhuofeng <zhuofeng2@huawei.com> - 3.10.9-1
|
||||
- Type:enhancement
|
||||
- CVE:NA
|
||||
- SUG:NA
|
||||
- DESC:update version to 3.10.9
|
||||
|
||||
* Mon Nov 28 2022 zhuofeng <zhuofeng2@huawei.com> - 3.10.2-12
|
||||
- Type:CVE
|
||||
- CVE:CVE-2022-37454
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user