import UBI python3.12-3.12.5-2.el9_5.1
This commit is contained in:
		
							parent
							
								
									fb9cb95ae7
								
							
						
					
					
						commit
						0c48c99a16
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | |||||||
| SOURCES/Python-3.12.1.tar.xz | SOURCES/Python-3.12.5.tar.xz | ||||||
|  | |||||||
| @ -1 +1 @@ | |||||||
| 5b11c58ea58cd6b8e1943c7e9b5f6e0997ca3632 SOURCES/Python-3.12.1.tar.xz | d9b83c17a717e1cbd3ab6bd14cfe3e508e6d87b2 SOURCES/Python-3.12.5.tar.xz | ||||||
|  | |||||||
| @ -30,10 +30,10 @@ Co-authored-by: Lumír Balhar <frenzy.madness@gmail.com> | |||||||
|  3 files changed, 71 insertions(+), 4 deletions(-) |  3 files changed, 71 insertions(+), 4 deletions(-) | ||||||
| 
 | 
 | ||||||
| diff --git a/Lib/site.py b/Lib/site.py
 | diff --git a/Lib/site.py b/Lib/site.py
 | ||||||
| index 672fa7b000..0a9c5be53e 100644
 | index 924cfbecec..e2871ecc89 100644
 | ||||||
| --- a/Lib/site.py
 | --- a/Lib/site.py
 | ||||||
| +++ b/Lib/site.py
 | +++ b/Lib/site.py
 | ||||||
| @@ -377,8 +377,15 @@ def getsitepackages(prefixes=None):
 | @@ -398,8 +398,15 @@ def getsitepackages(prefixes=None):
 | ||||||
|      return sitepackages |      return sitepackages | ||||||
|   |   | ||||||
|  def addsitepackages(known_paths, prefixes=None): |  def addsitepackages(known_paths, prefixes=None): | ||||||
| @ -129,7 +129,7 @@ index 122d441bd1..2d354a11da 100644 | |||||||
|          # On Windows we want to substitute 'lib' for schemes rather |          # On Windows we want to substitute 'lib' for schemes rather | ||||||
|          # than the native value (without modifying vars, in case it |          # than the native value (without modifying vars, in case it | ||||||
| diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py
 | diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py
 | ||||||
| index b6dbf3d52c..4f06a7673c 100644
 | index 1137c2032b..8fc2b84f52 100644
 | ||||||
| --- a/Lib/test/test_sysconfig.py
 | --- a/Lib/test/test_sysconfig.py
 | ||||||
| +++ b/Lib/test/test_sysconfig.py
 | +++ b/Lib/test/test_sysconfig.py
 | ||||||
| @@ -110,8 +110,19 @@ def test_get_path(self):
 | @@ -110,8 +110,19 @@ def test_get_path(self):
 | ||||||
| @ -153,7 +153,7 @@ index b6dbf3d52c..4f06a7673c 100644 | |||||||
|                      os.path.normpath(expected), |                      os.path.normpath(expected), | ||||||
|                  ) |                  ) | ||||||
|   |   | ||||||
| @@ -335,7 +346,7 @@ def test_get_config_h_filename(self):
 | @@ -344,7 +355,7 @@ def test_get_config_h_filename(self):
 | ||||||
|          self.assertTrue(os.path.isfile(config_h), config_h) |          self.assertTrue(os.path.isfile(config_h), config_h) | ||||||
|   |   | ||||||
|      def test_get_scheme_names(self): |      def test_get_scheme_names(self): | ||||||
| @ -162,7 +162,7 @@ index b6dbf3d52c..4f06a7673c 100644 | |||||||
|          if HAS_USER_BASE: |          if HAS_USER_BASE: | ||||||
|              wanted.extend(['nt_user', 'osx_framework_user', 'posix_user']) |              wanted.extend(['nt_user', 'osx_framework_user', 'posix_user']) | ||||||
|          self.assertEqual(get_scheme_names(), tuple(sorted(wanted))) |          self.assertEqual(get_scheme_names(), tuple(sorted(wanted))) | ||||||
| @@ -347,6 +358,8 @@ def test_symlink(self): # Issue 7880
 | @@ -356,6 +367,8 @@ def test_symlink(self): # Issue 7880
 | ||||||
|              cmd = "-c", "import sysconfig; print(sysconfig.get_platform())" |              cmd = "-c", "import sysconfig; print(sysconfig.get_platform())" | ||||||
|              self.assertEqual(py.call_real(*cmd), py.call_link(*cmd)) |              self.assertEqual(py.call_real(*cmd), py.call_link(*cmd)) | ||||||
|   |   | ||||||
|  | |||||||
| @ -750,7 +750,7 @@ index 8b4eb2f..e8e4864 100644 | |||||||
|              raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__) |              raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__) | ||||||
|   |   | ||||||
|          if not digestmod: |          if not digestmod: | ||||||
|              raise TypeError("Missing required parameter 'digestmod'.") |              raise TypeError("Missing required argument 'digestmod'.") | ||||||
|   |   | ||||||
| -        if _hashopenssl and isinstance(digestmod, (str, _functype)):
 | -        if _hashopenssl and isinstance(digestmod, (str, _functype)):
 | ||||||
| +        if _hashopenssl.get_fips_mode() or (_hashopenssl and isinstance(digestmod, (str, _functype))):
 | +        if _hashopenssl.get_fips_mode() or (_hashopenssl and isinstance(digestmod, (str, _functype))):
 | ||||||
|  | |||||||
| @ -16,10 +16,10 @@ https://github.com/GrahamDumpleton/mod_wsgi/issues/730 | |||||||
|  2 files changed, 8 insertions(+), 50 deletions(-) |  2 files changed, 8 insertions(+), 50 deletions(-) | ||||||
| 
 | 
 | ||||||
| diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
 | diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
 | ||||||
| index 756d5e329f..5d09775efc 100644
 | index 2e4b860b97..3066b23ee1 100644
 | ||||||
| --- a/Lib/test/test_threading.py
 | --- a/Lib/test/test_threading.py
 | ||||||
| +++ b/Lib/test/test_threading.py
 | +++ b/Lib/test/test_threading.py
 | ||||||
| @@ -1007,39 +1007,6 @@ def noop(): pass
 | @@ -1100,39 +1100,6 @@ def noop(): pass
 | ||||||
|              threading.Thread(target=noop).start() |              threading.Thread(target=noop).start() | ||||||
|              # Thread.join() is not called |              # Thread.join() is not called | ||||||
|   |   | ||||||
| @ -56,14 +56,14 @@ index 756d5e329f..5d09775efc 100644 | |||||||
| -        self.assertEqual(out, b'')
 | -        self.assertEqual(out, b'')
 | ||||||
| -        self.assertEqual(err, b'')
 | -        self.assertEqual(err, b'')
 | ||||||
| -
 | -
 | ||||||
|      def test_start_new_thread_at_exit(self): |      def test_start_new_thread_at_finalization(self): | ||||||
|          code = """if 1: |          code = """if 1: | ||||||
|              import atexit |              import _thread | ||||||
| diff --git a/Lib/threading.py b/Lib/threading.py
 | diff --git a/Lib/threading.py b/Lib/threading.py
 | ||||||
| index 8dcaf8ca6a..ed0b0f4632 100644
 | index 0bba85d08a..b256e3273f 100644
 | ||||||
| --- a/Lib/threading.py
 | --- a/Lib/threading.py
 | ||||||
| +++ b/Lib/threading.py
 | +++ b/Lib/threading.py
 | ||||||
| @@ -1586,29 +1586,20 @@ def _shutdown():
 | @@ -1587,29 +1587,20 @@ def _shutdown():
 | ||||||
|   |   | ||||||
|      global _SHUTTING_DOWN |      global _SHUTTING_DOWN | ||||||
|      _SHUTTING_DOWN = True |      _SHUTTING_DOWN = True | ||||||
|  | |||||||
| @ -1,19 +1,24 @@ | |||||||
| From 73d2995223c725638d53b9cb8e1d26b82daf0874 Mon Sep 17 00:00:00 2001 | From ddd8064257a1916726b784d43f18e889ea1634f7 Mon Sep 17 00:00:00 2001 | ||||||
| From: Petr Viktorin <encukou@gmail.com> | From: Petr Viktorin <encukou@gmail.com> | ||||||
| Date: Mon, 6 Mar 2023 17:24:24 +0100 | Date: Tue, 2 Jul 2024 11:40:37 +0200 | ||||||
| Subject: [PATCH] CVE-2007-4559, PEP-706: Add filters for tarfile extraction | Subject: [PATCH] CVE-2007-4559, PEP-706: Add filters for tarfile extraction | ||||||
|  (downstream) |  (downstream) | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
| 
 | 
 | ||||||
| Add and test RHEL-specific ways of configuring the default behavior: environment | Add and test RHEL-specific ways of configuring the default behavior: environment | ||||||
| variable and config file. | variable and config file. | ||||||
|  | 
 | ||||||
|  | Co-Authored-By: Tomáš Hrnčiar <thrnciar@redhat.com> | ||||||
| ---
 | ---
 | ||||||
|  Lib/tarfile.py           |  47 +++++++++++++-- |  Lib/tarfile.py           |  47 +++++++++++-- | ||||||
|  Lib/test/test_shutil.py  |   2 +- |  Lib/test/test_shutil.py  |   2 +- | ||||||
|  Lib/test/test_tarfile.py | 123 ++++++++++++++++++++++++++++++++++++++- |  Lib/test/test_tarfile.py | 147 +++++++++++++++++++++++++++++++++++++-- | ||||||
|  3 files changed, 163 insertions(+), 9 deletions(-) |  3 files changed, 185 insertions(+), 11 deletions(-) | ||||||
| 
 | 
 | ||||||
| diff --git a/Lib/tarfile.py b/Lib/tarfile.py
 | diff --git a/Lib/tarfile.py b/Lib/tarfile.py
 | ||||||
| index 02f5e3b..f7109f3 100755
 | index e1487e3..89b6843 100755
 | ||||||
| --- a/Lib/tarfile.py
 | --- a/Lib/tarfile.py
 | ||||||
| +++ b/Lib/tarfile.py
 | +++ b/Lib/tarfile.py
 | ||||||
| @@ -71,6 +71,13 @@ __all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError", "ReadError",
 | @@ -71,6 +71,13 @@ __all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError", "ReadError",
 | ||||||
| @ -30,7 +35,7 @@ index 02f5e3b..f7109f3 100755 | |||||||
|   |   | ||||||
|  #--------------------------------------------------------- |  #--------------------------------------------------------- | ||||||
|  # tar constants |  # tar constants | ||||||
| @@ -2217,11 +2224,41 @@ class TarFile(object):
 | @@ -2218,11 +2225,41 @@ class TarFile(object):
 | ||||||
|          if filter is None: |          if filter is None: | ||||||
|              filter = self.extraction_filter |              filter = self.extraction_filter | ||||||
|              if filter is None: |              if filter is None: | ||||||
| @ -38,7 +43,7 @@ index 02f5e3b..f7109f3 100755 | |||||||
| -                    'Python 3.14 will, by default, filter extracted tar '
 | -                    'Python 3.14 will, by default, filter extracted tar '
 | ||||||
| -                    + 'archives and reject files or modify their metadata. '
 | -                    + 'archives and reject files or modify their metadata. '
 | ||||||
| -                    + 'Use the filter argument to control this behavior.',
 | -                    + 'Use the filter argument to control this behavior.',
 | ||||||
| -                    DeprecationWarning)
 | -                    DeprecationWarning, stacklevel=3)
 | ||||||
| +                name = os.environ.get('PYTHON_TARFILE_EXTRACTION_FILTER')
 | +                name = os.environ.get('PYTHON_TARFILE_EXTRACTION_FILTER')
 | ||||||
| +                if name is None:
 | +                if name is None:
 | ||||||
| +                    try:
 | +                    try:
 | ||||||
| @ -72,16 +77,16 @@ index 02f5e3b..f7109f3 100755 | |||||||
| +                        + 'and some mode bits are cleared. '
 | +                        + 'and some mode bits are cleared. '
 | ||||||
| +                        + 'See https://access.redhat.com/articles/7004769 '
 | +                        + 'See https://access.redhat.com/articles/7004769 '
 | ||||||
| +                        + 'for more details.',
 | +                        + 'for more details.',
 | ||||||
| +                        RuntimeWarning)
 | +                        RuntimeWarning, stacklevel=3)
 | ||||||
| +                    return tar_filter
 | +                    return tar_filter
 | ||||||
|                  return fully_trusted_filter |                  return fully_trusted_filter | ||||||
|              if isinstance(filter, str): |              if isinstance(filter, str): | ||||||
|                  raise TypeError( |                  raise TypeError( | ||||||
| diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py
 | diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py
 | ||||||
| index 5fd8fb4..501da8f 100644
 | index 7bc5d12..88b4bdb 100644
 | ||||||
| --- a/Lib/test/test_shutil.py
 | --- a/Lib/test/test_shutil.py
 | ||||||
| +++ b/Lib/test/test_shutil.py
 | +++ b/Lib/test/test_shutil.py
 | ||||||
| @@ -1950,7 +1950,7 @@ class TestArchives(BaseTest, unittest.TestCase):
 | @@ -2096,7 +2096,7 @@ class TestArchives(BaseTest, unittest.TestCase):
 | ||||||
|          self.check_unpack_archive(format, filter='fully_trusted') |          self.check_unpack_archive(format, filter='fully_trusted') | ||||||
|          self.check_unpack_archive(format, filter='data') |          self.check_unpack_archive(format, filter='data') | ||||||
|          with warnings_helper.check_warnings( |          with warnings_helper.check_warnings( | ||||||
| @ -91,10 +96,48 @@ index 5fd8fb4..501da8f 100644 | |||||||
|   |   | ||||||
|      def test_unpack_archive_tar(self): |      def test_unpack_archive_tar(self): | ||||||
| diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
 | diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
 | ||||||
| index c5fc76d..397e334 100644
 | index 3fbd25e..9aa727e 100644
 | ||||||
| --- a/Lib/test/test_tarfile.py
 | --- a/Lib/test/test_tarfile.py
 | ||||||
| +++ b/Lib/test/test_tarfile.py
 | +++ b/Lib/test/test_tarfile.py
 | ||||||
| @@ -3097,8 +3097,8 @@ class NoneInfoExtractTests(ReadTest):
 | @@ -727,7 +727,17 @@ class MiscReadTestBase(CommonReadTest):
 | ||||||
|  |              tarfile.open(tarname, encoding="iso8859-1") as tar | ||||||
|  |          ): | ||||||
|  |              directories = [t for t in tar if t.isdir()] | ||||||
|  | -            with self.assertWarnsRegex(DeprecationWarning, "Use the filter argument") as cm:
 | ||||||
|  | +            with self.assertWarnsRegex(
 | ||||||
|  | +                RuntimeWarning,
 | ||||||
|  | +                re.escape(
 | ||||||
|  | +                    'The default behavior of tarfile extraction has been '
 | ||||||
|  | +                    'changed to disallow common exploits '
 | ||||||
|  | +                    '(including CVE-2007-4559). '
 | ||||||
|  | +                    'By default, absolute/parent paths are disallowed '
 | ||||||
|  | +                    'and some mode bits are cleared. '
 | ||||||
|  | +                    'See https://access.redhat.com/articles/7004769 '
 | ||||||
|  | +                    'for more details.'
 | ||||||
|  | +                )) as cm:
 | ||||||
|  |                  tar.extractall(DIR, directories) | ||||||
|  |              # check that the stacklevel of the deprecation warning is correct: | ||||||
|  |              self.assertEqual(cm.filename, __file__) | ||||||
|  | @@ -740,7 +750,17 @@ class MiscReadTestBase(CommonReadTest):
 | ||||||
|  |              tarfile.open(tarname, encoding="iso8859-1") as tar | ||||||
|  |          ): | ||||||
|  |              tarinfo = tar.getmember(dirtype) | ||||||
|  | -            with self.assertWarnsRegex(DeprecationWarning, "Use the filter argument") as cm:
 | ||||||
|  | +            with self.assertWarnsRegex(
 | ||||||
|  | +                RuntimeWarning,
 | ||||||
|  | +                re.escape(
 | ||||||
|  | +                    'The default behavior of tarfile extraction has been '
 | ||||||
|  | +                    'changed to disallow common exploits '
 | ||||||
|  | +                    '(including CVE-2007-4559). '
 | ||||||
|  | +                    'By default, absolute/parent paths are disallowed '
 | ||||||
|  | +                    'and some mode bits are cleared. '
 | ||||||
|  | +                    'See https://access.redhat.com/articles/7004769 '
 | ||||||
|  | +                    'for more details.'
 | ||||||
|  | +                )) as cm:
 | ||||||
|  |                  tar.extract(tarinfo, path=DIR) | ||||||
|  |              # check that the stacklevel of the deprecation warning is correct: | ||||||
|  |              self.assertEqual(cm.filename, __file__) | ||||||
|  | @@ -3144,8 +3164,8 @@ class NoneInfoExtractTests(ReadTest):
 | ||||||
|          tar.errorlevel = 0 |          tar.errorlevel = 0 | ||||||
|          with ExitStack() as cm: |          with ExitStack() as cm: | ||||||
|              if cls.extraction_filter is None: |              if cls.extraction_filter is None: | ||||||
| @ -105,7 +148,7 @@ index c5fc76d..397e334 100644 | |||||||
|              tar.extractall(cls.control_dir, filter=cls.extraction_filter) |              tar.extractall(cls.control_dir, filter=cls.extraction_filter) | ||||||
|          tar.close() |          tar.close() | ||||||
|          cls.control_paths = set( |          cls.control_paths = set( | ||||||
| @@ -3919,7 +3919,7 @@ class TestExtractionFilters(unittest.TestCase):
 | @@ -3966,7 +3986,7 @@ class TestExtractionFilters(unittest.TestCase):
 | ||||||
|          with ArchiveMaker() as arc: |          with ArchiveMaker() as arc: | ||||||
|              arc.add('foo') |              arc.add('foo') | ||||||
|          with warnings_helper.check_warnings( |          with warnings_helper.check_warnings( | ||||||
| @ -114,7 +157,7 @@ index c5fc76d..397e334 100644 | |||||||
|              with self.check_context(arc.open(), None): |              with self.check_context(arc.open(), None): | ||||||
|                  self.expect_file('foo') |                  self.expect_file('foo') | ||||||
|   |   | ||||||
| @@ -4089,6 +4089,123 @@ class TestExtractionFilters(unittest.TestCase):
 | @@ -4136,6 +4156,123 @@ class TestExtractionFilters(unittest.TestCase):
 | ||||||
|              self.expect_exception(TypeError)  # errorlevel is not int |              self.expect_exception(TypeError)  # errorlevel is not int | ||||||
|   |   | ||||||
|   |   | ||||||
| @ -235,9 +278,9 @@ index c5fc76d..397e334 100644 | |||||||
| +                self.check_trusted_default(tar, tempdir)
 | +                self.check_trusted_default(tar, tempdir)
 | ||||||
| +
 | +
 | ||||||
| +
 | +
 | ||||||
|  def setUpModule(): |  class OverwriteTests(archiver_tests.OverwriteTests, unittest.TestCase): | ||||||
|      os_helper.unlink(TEMPDIR) |      testdir = os.path.join(TEMPDIR, "testoverwrite") | ||||||
|      os.makedirs(TEMPDIR) |   | ||||||
| -- 
 | -- 
 | ||||||
| 2.43.0 | 2.44.0 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -19,7 +19,7 @@ Co-Authored-By: Thomas Dwyer <github@tomd.tel> | |||||||
|  create mode 100644 Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst |  create mode 100644 Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst | ||||||
| 
 | 
 | ||||||
| diff --git a/Doc/library/email.utils.rst b/Doc/library/email.utils.rst
 | diff --git a/Doc/library/email.utils.rst b/Doc/library/email.utils.rst
 | ||||||
| index 345b64001c..d693a9bc39 100644
 | index 6ba42491d6..6bd45200d8 100644
 | ||||||
| --- a/Doc/library/email.utils.rst
 | --- a/Doc/library/email.utils.rst
 | ||||||
| +++ b/Doc/library/email.utils.rst
 | +++ b/Doc/library/email.utils.rst
 | ||||||
| @@ -58,13 +58,18 @@ of the new API.
 | @@ -58,13 +58,18 @@ of the new API.
 | ||||||
| @ -72,7 +72,7 @@ index 345b64001c..d693a9bc39 100644 | |||||||
|  .. function:: parsedate(date) |  .. function:: parsedate(date) | ||||||
|   |   | ||||||
| diff --git a/Lib/email/utils.py b/Lib/email/utils.py
 | diff --git a/Lib/email/utils.py b/Lib/email/utils.py
 | ||||||
| index 81da5394ea..43c3627fca 100644
 | index 1de547a011..e53abc8b84 100644
 | ||||||
| --- a/Lib/email/utils.py
 | --- a/Lib/email/utils.py
 | ||||||
| +++ b/Lib/email/utils.py
 | +++ b/Lib/email/utils.py
 | ||||||
| @@ -48,6 +48,7 @@
 | @@ -48,6 +48,7 @@
 | ||||||
| @ -81,7 +81,7 @@ index 81da5394ea..43c3627fca 100644 | |||||||
|   |   | ||||||
| +
 | +
 | ||||||
|  def _has_surrogates(s): |  def _has_surrogates(s): | ||||||
|      """Return True if s contains surrogate-escaped binary data.""" |      """Return True if s may contain surrogate-escaped binary data.""" | ||||||
|      # This check is based on the fact that unless there are surrogates, utf8 |      # This check is based on the fact that unless there are surrogates, utf8 | ||||||
| @@ -106,12 +107,127 @@ def formataddr(pair, charset='utf-8'):
 | @@ -106,12 +107,127 @@ def formataddr(pair, charset='utf-8'):
 | ||||||
|      return address |      return address | ||||||
| @ -255,7 +255,7 @@ index 81da5394ea..43c3627fca 100644 | |||||||
|   |   | ||||||
|   |   | ||||||
| diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
 | diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
 | ||||||
| index 2a237095b9..4672b790d8 100644
 | index fc8d87974e..ef8aa0d53c 100644
 | ||||||
| --- a/Lib/test/test_email/test_email.py
 | --- a/Lib/test/test_email/test_email.py
 | ||||||
| +++ b/Lib/test/test_email/test_email.py
 | +++ b/Lib/test/test_email/test_email.py
 | ||||||
| @@ -16,6 +16,7 @@
 | @@ -16,6 +16,7 @@
 | ||||||
| @ -266,7 +266,7 @@ index 2a237095b9..4672b790d8 100644 | |||||||
|   |   | ||||||
|  from email.charset import Charset |  from email.charset import Charset | ||||||
|  from email.generator import Generator, DecodedGenerator, BytesGenerator |  from email.generator import Generator, DecodedGenerator, BytesGenerator | ||||||
| @@ -3337,15 +3338,137 @@ def test_getaddresses_comma_in_name(self):
 | @@ -3352,15 +3353,137 @@ def test_getaddresses_comma_in_name(self):
 | ||||||
|              ], |              ], | ||||||
|          ) |          ) | ||||||
|   |   | ||||||
| @ -412,7 +412,7 @@ index 2a237095b9..4672b790d8 100644 | |||||||
|   |   | ||||||
|      def test_getaddresses_embedded_comment(self): |      def test_getaddresses_embedded_comment(self): | ||||||
|          """Test proper handling of a nested comment""" |          """Test proper handling of a nested comment""" | ||||||
| @@ -3536,6 +3659,54 @@ def test_mime_classes_policy_argument(self):
 | @@ -3551,6 +3674,54 @@ def test_mime_classes_policy_argument(self):
 | ||||||
|                  m = cls(*constructor, policy=email.policy.default) |                  m = cls(*constructor, policy=email.policy.default) | ||||||
|                  self.assertIs(m.policy, email.policy.default) |                  self.assertIs(m.policy, email.policy.default) | ||||||
|   |   | ||||||
|  | |||||||
| @ -0,0 +1,63 @@ | |||||||
|  | From 60d40d7095983e0bc23a103b2050adc519dc7fe3 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lumir Balhar <lbalhar@redhat.com> | ||||||
|  | Date: Fri, 3 May 2024 14:17:48 +0200 | ||||||
|  | Subject: [PATCH] Expect failures in tests not working properly with expat with | ||||||
|  |  a fixed CVE in RHEL | ||||||
|  | 
 | ||||||
|  | ---
 | ||||||
|  |  Lib/test/test_pyexpat.py   | 1 + | ||||||
|  |  Lib/test/test_sax.py       | 1 + | ||||||
|  |  Lib/test/test_xml_etree.py | 3 +++ | ||||||
|  |  3 files changed, 5 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py
 | ||||||
|  | index 43cbd27..27b1502 100644
 | ||||||
|  | --- a/Lib/test/test_pyexpat.py
 | ||||||
|  | +++ b/Lib/test/test_pyexpat.py
 | ||||||
|  | @@ -793,6 +793,7 @@ class ReparseDeferralTest(unittest.TestCase):
 | ||||||
|  |   | ||||||
|  |          self.assertEqual(started, ['doc']) | ||||||
|  |   | ||||||
|  | +    @unittest.expectedFailure
 | ||||||
|  |      def test_reparse_deferral_disabled(self): | ||||||
|  |          started = [] | ||||||
|  |   | ||||||
|  | diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py
 | ||||||
|  | index 9b3014a..646c92d 100644
 | ||||||
|  | --- a/Lib/test/test_sax.py
 | ||||||
|  | +++ b/Lib/test/test_sax.py
 | ||||||
|  | @@ -1240,6 +1240,7 @@ class ExpatReaderTest(XmlTestBase):
 | ||||||
|  |   | ||||||
|  |          self.assertEqual(result.getvalue(), start + b"<doc></doc>") | ||||||
|  |   | ||||||
|  | +    @unittest.expectedFailure
 | ||||||
|  |      def test_flush_reparse_deferral_disabled(self): | ||||||
|  |          result = BytesIO() | ||||||
|  |          xmlgen = XMLGenerator(result) | ||||||
|  | diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
 | ||||||
|  | index 9c382d1..62f2871 100644
 | ||||||
|  | --- a/Lib/test/test_xml_etree.py
 | ||||||
|  | +++ b/Lib/test/test_xml_etree.py
 | ||||||
|  | @@ -1424,9 +1424,11 @@ class XMLPullParserTest(unittest.TestCase):
 | ||||||
|  |          self.assert_event_tags(parser, [('end', 'root')]) | ||||||
|  |          self.assertIsNone(parser.close()) | ||||||
|  |   | ||||||
|  | +    @unittest.expectedFailure
 | ||||||
|  |      def test_simple_xml_chunk_1(self): | ||||||
|  |          self.test_simple_xml(chunk_size=1, flush=True) | ||||||
|  |   | ||||||
|  | +    @unittest.expectedFailure
 | ||||||
|  |      def test_simple_xml_chunk_5(self): | ||||||
|  |          self.test_simple_xml(chunk_size=5, flush=True) | ||||||
|  |   | ||||||
|  | @@ -1651,6 +1653,7 @@ class XMLPullParserTest(unittest.TestCase):
 | ||||||
|  |   | ||||||
|  |          self.assert_event_tags(parser, [('end', 'doc')]) | ||||||
|  |   | ||||||
|  | +    @unittest.expectedFailure
 | ||||||
|  |      def test_flush_reparse_deferral_disabled(self): | ||||||
|  |          parser = ET.XMLPullParser(events=('start', 'end')) | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.44.0 | ||||||
|  | 
 | ||||||
| @ -1,88 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Serhiy Storchaka <storchaka@gmail.com> |  | ||||||
| Date: Sun, 11 Feb 2024 12:08:39 +0200 |  | ||||||
| Subject: [PATCH] 00422: gh-115133: Fix tests for XMLPullParser with Expat |  | ||||||
|  2.6.0 |  | ||||||
| 
 |  | ||||||
| Feeding the parser by too small chunks defers parsing to prevent |  | ||||||
| CVE-2023-52425. Future versions of Expat may be more reactive. |  | ||||||
| 
 |  | ||||||
| (cherry picked from commit 4a08e7b3431cd32a0daf22a33421cd3035343dc4) |  | ||||||
| ---
 |  | ||||||
|  Lib/test/test_xml_etree.py                    | 58 ++++++++++++------- |  | ||||||
|  ...-02-08-14-21-28.gh-issue-115133.ycl4ko.rst |  2 + |  | ||||||
|  2 files changed, 38 insertions(+), 22 deletions(-) |  | ||||||
|  create mode 100644 Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst |  | ||||||
| 
 |  | ||||||
| diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
 |  | ||||||
| index b50898f1d1..6fb888cb21 100644
 |  | ||||||
| --- a/Lib/test/test_xml_etree.py
 |  | ||||||
| +++ b/Lib/test/test_xml_etree.py
 |  | ||||||
| @@ -1400,28 +1400,37 @@ class XMLPullParserTest(unittest.TestCase):
 |  | ||||||
|          self.assertEqual([(action, elem.tag) for action, elem in events], |  | ||||||
|                           expected) |  | ||||||
|   |  | ||||||
| -    def test_simple_xml(self):
 |  | ||||||
| -        for chunk_size in (None, 1, 5):
 |  | ||||||
| -            with self.subTest(chunk_size=chunk_size):
 |  | ||||||
| -                parser = ET.XMLPullParser()
 |  | ||||||
| -                self.assert_event_tags(parser, [])
 |  | ||||||
| -                self._feed(parser, "<!-- comment -->\n", chunk_size)
 |  | ||||||
| -                self.assert_event_tags(parser, [])
 |  | ||||||
| -                self._feed(parser,
 |  | ||||||
| -                           "<root>\n  <element key='value'>text</element",
 |  | ||||||
| -                           chunk_size)
 |  | ||||||
| -                self.assert_event_tags(parser, [])
 |  | ||||||
| -                self._feed(parser, ">\n", chunk_size)
 |  | ||||||
| -                self.assert_event_tags(parser, [('end', 'element')])
 |  | ||||||
| -                self._feed(parser, "<element>text</element>tail\n", chunk_size)
 |  | ||||||
| -                self._feed(parser, "<empty-element/>\n", chunk_size)
 |  | ||||||
| -                self.assert_event_tags(parser, [
 |  | ||||||
| -                    ('end', 'element'),
 |  | ||||||
| -                    ('end', 'empty-element'),
 |  | ||||||
| -                    ])
 |  | ||||||
| -                self._feed(parser, "</root>\n", chunk_size)
 |  | ||||||
| -                self.assert_event_tags(parser, [('end', 'root')])
 |  | ||||||
| -                self.assertIsNone(parser.close())
 |  | ||||||
| +    def test_simple_xml(self, chunk_size=None):
 |  | ||||||
| +        parser = ET.XMLPullParser()
 |  | ||||||
| +        self.assert_event_tags(parser, [])
 |  | ||||||
| +        self._feed(parser, "<!-- comment -->\n", chunk_size)
 |  | ||||||
| +        self.assert_event_tags(parser, [])
 |  | ||||||
| +        self._feed(parser,
 |  | ||||||
| +                   "<root>\n  <element key='value'>text</element",
 |  | ||||||
| +                   chunk_size)
 |  | ||||||
| +        self.assert_event_tags(parser, [])
 |  | ||||||
| +        self._feed(parser, ">\n", chunk_size)
 |  | ||||||
| +        self.assert_event_tags(parser, [('end', 'element')])
 |  | ||||||
| +        self._feed(parser, "<element>text</element>tail\n", chunk_size)
 |  | ||||||
| +        self._feed(parser, "<empty-element/>\n", chunk_size)
 |  | ||||||
| +        self.assert_event_tags(parser, [
 |  | ||||||
| +            ('end', 'element'),
 |  | ||||||
| +            ('end', 'empty-element'),
 |  | ||||||
| +            ])
 |  | ||||||
| +        self._feed(parser, "</root>\n", chunk_size)
 |  | ||||||
| +        self.assert_event_tags(parser, [('end', 'root')])
 |  | ||||||
| +        self.assertIsNone(parser.close())
 |  | ||||||
| +
 |  | ||||||
| +    @unittest.expectedFailure
 |  | ||||||
| +    def test_simple_xml_chunk_1(self):
 |  | ||||||
| +        self.test_simple_xml(chunk_size=1)
 |  | ||||||
| +
 |  | ||||||
| +    @unittest.expectedFailure
 |  | ||||||
| +    def test_simple_xml_chunk_5(self):
 |  | ||||||
| +        self.test_simple_xml(chunk_size=5)
 |  | ||||||
| +
 |  | ||||||
| +    def test_simple_xml_chunk_22(self):
 |  | ||||||
| +        self.test_simple_xml(chunk_size=22)
 |  | ||||||
|   |  | ||||||
|      def test_feed_while_iterating(self): |  | ||||||
|          parser = ET.XMLPullParser() |  | ||||||
| diff --git a/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst b/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst
 |  | ||||||
| new file mode 100644 |  | ||||||
| index 0000000000..6f1015235c
 |  | ||||||
| --- /dev/null
 |  | ||||||
| +++ b/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst
 |  | ||||||
| @@ -0,0 +1,2 @@
 |  | ||||||
| +Fix tests for :class:`~xml.etree.ElementTree.XMLPullParser` with Expat
 |  | ||||||
| +2.6.0.
 |  | ||||||
| @ -1,345 +0,0 @@ | |||||||
| From 7a25b2f511054dd2011308275bb24e914e1977af Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Petr Viktorin <encukou@gmail.com> |  | ||||||
| Date: Tue, 6 Aug 2024 19:07:19 +0200 |  | ||||||
| Subject: [PATCH] gh-121650: Encode newlines in headers, and verify headers are |  | ||||||
|  sound (GH-122233) (#122599) |  | ||||||
| 
 |  | ||||||
| * gh-121650: Encode newlines in headers, and verify headers are sound (GH-122233) |  | ||||||
| 
 |  | ||||||
| - Encode header parts that contain newlines
 |  | ||||||
| 
 |  | ||||||
| Per RFC 2047: |  | ||||||
| 
 |  | ||||||
| > [...] these encoding schemes allow the
 |  | ||||||
| > encoding of arbitrary octet values, mail readers that implement this
 |  | ||||||
| > decoding should also ensure that display of the decoded data on the
 |  | ||||||
| > recipient's terminal will not cause unwanted side-effects
 |  | ||||||
| 
 |  | ||||||
| It seems that the "quoted-word" scheme is a valid way to include |  | ||||||
| a newline character in a header value, just like we already allow |  | ||||||
| undecodable bytes or control characters. |  | ||||||
| They do need to be properly quoted when serialized to text, though. |  | ||||||
| 
 |  | ||||||
| - Verify that email headers are well-formed
 |  | ||||||
| 
 |  | ||||||
| This should fail for custom fold() implementations that aren't careful |  | ||||||
| about newlines. |  | ||||||
| 
 |  | ||||||
| Co-authored-by: Bas Bloemsaat <bas@bloemsaat.org> |  | ||||||
| Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> |  | ||||||
| (cherry picked from commit 097633981879b3c9de9a1dd120d3aa585ecc2384) |  | ||||||
| 
 |  | ||||||
| * Document changes as made in 3.12.5 |  | ||||||
| ---
 |  | ||||||
|  Doc/library/email.errors.rst                  |  7 +++ |  | ||||||
|  Doc/library/email.policy.rst                  | 18 ++++++ |  | ||||||
|  Lib/email/_header_value_parser.py             | 12 +++- |  | ||||||
|  Lib/email/_policybase.py                      |  8 +++ |  | ||||||
|  Lib/email/errors.py                           |  4 ++ |  | ||||||
|  Lib/email/generator.py                        | 13 +++- |  | ||||||
|  Lib/test/test_email/test_generator.py         | 62 +++++++++++++++++++ |  | ||||||
|  Lib/test/test_email/test_policy.py            | 26 ++++++++ |  | ||||||
|  ...-07-27-16-10-41.gh-issue-121650.nf6oc9.rst |  5 ++ |  | ||||||
|  9 files changed, 151 insertions(+), 4 deletions(-) |  | ||||||
|  create mode 100644 Misc/NEWS.d/next/Library/2024-07-27-16-10-41.gh-issue-121650.nf6oc9.rst |  | ||||||
| 
 |  | ||||||
| diff --git a/Doc/library/email.errors.rst b/Doc/library/email.errors.rst
 |  | ||||||
| index 56aea65..27b0481 100644
 |  | ||||||
| --- a/Doc/library/email.errors.rst
 |  | ||||||
| +++ b/Doc/library/email.errors.rst
 |  | ||||||
| @@ -58,6 +58,13 @@ The following exception classes are defined in the :mod:`email.errors` module:
 |  | ||||||
|     :class:`~email.mime.nonmultipart.MIMENonMultipart` (e.g. |  | ||||||
|     :class:`~email.mime.image.MIMEImage`). |  | ||||||
|   |  | ||||||
| +
 |  | ||||||
| +.. exception:: HeaderWriteError()
 |  | ||||||
| +
 |  | ||||||
| +   Raised when an error occurs when the :mod:`~email.generator` outputs
 |  | ||||||
| +   headers.
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
|  .. exception:: MessageDefect() |  | ||||||
|   |  | ||||||
|     This is the base class for all defects found when parsing email messages. |  | ||||||
| diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst
 |  | ||||||
| index fd47dd0..6ec6e4d 100644
 |  | ||||||
| --- a/Doc/library/email.policy.rst
 |  | ||||||
| +++ b/Doc/library/email.policy.rst
 |  | ||||||
| @@ -230,6 +230,24 @@ added matters.  To illustrate::
 |  | ||||||
|   |  | ||||||
|        .. versionadded:: 3.6 |  | ||||||
|   |  | ||||||
| +
 |  | ||||||
| +   .. attribute:: verify_generated_headers
 |  | ||||||
| +
 |  | ||||||
| +      If ``True`` (the default), the generator will raise
 |  | ||||||
| +      :exc:`~email.errors.HeaderWriteError` instead of writing a header
 |  | ||||||
| +      that is improperly folded or delimited, such that it would
 |  | ||||||
| +      be parsed as multiple headers or joined with adjacent data.
 |  | ||||||
| +      Such headers can be generated by custom header classes or bugs
 |  | ||||||
| +      in the ``email`` module.
 |  | ||||||
| +
 |  | ||||||
| +      As it's a security feature, this defaults to ``True`` even in the
 |  | ||||||
| +      :class:`~email.policy.Compat32` policy.
 |  | ||||||
| +      For backwards compatible, but unsafe, behavior, it must be set to
 |  | ||||||
| +      ``False`` explicitly.
 |  | ||||||
| +
 |  | ||||||
| +      .. versionadded:: 3.12.5
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
|     The following :class:`Policy` method is intended to be called by code using |  | ||||||
|     the email library to create policy instances with custom settings: |  | ||||||
|   |  | ||||||
| diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py
 |  | ||||||
| index 0d6bd81..362edc5 100644
 |  | ||||||
| --- a/Lib/email/_header_value_parser.py
 |  | ||||||
| +++ b/Lib/email/_header_value_parser.py
 |  | ||||||
| @@ -92,6 +92,8 @@ TOKEN_ENDS = TSPECIALS | WSP
 |  | ||||||
|  ASPECIALS = TSPECIALS | set("*'%") |  | ||||||
|  ATTRIBUTE_ENDS = ASPECIALS | WSP |  | ||||||
|  EXTENDED_ATTRIBUTE_ENDS = ATTRIBUTE_ENDS - set('%') |  | ||||||
| +NLSET = {'\n', '\r'}
 |  | ||||||
| +SPECIALSNL = SPECIALS | NLSET
 |  | ||||||
|   |  | ||||||
|  def quote_string(value): |  | ||||||
|      return '"'+str(value).replace('\\', '\\\\').replace('"', r'\"')+'"' |  | ||||||
| @@ -2776,9 +2778,13 @@ def _refold_parse_tree(parse_tree, *, policy):
 |  | ||||||
|              wrap_as_ew_blocked -= 1 |  | ||||||
|              continue |  | ||||||
|          tstr = str(part) |  | ||||||
| -        if part.token_type == 'ptext' and set(tstr) & SPECIALS:
 |  | ||||||
| -            # Encode if tstr contains special characters.
 |  | ||||||
| -            want_encoding = True
 |  | ||||||
| +        if not want_encoding:
 |  | ||||||
| +            if part.token_type == 'ptext':
 |  | ||||||
| +                # Encode if tstr contains special characters.
 |  | ||||||
| +                want_encoding = not SPECIALSNL.isdisjoint(tstr)
 |  | ||||||
| +            else:
 |  | ||||||
| +                # Encode if tstr contains newlines.
 |  | ||||||
| +                want_encoding = not NLSET.isdisjoint(tstr)
 |  | ||||||
|          try: |  | ||||||
|              tstr.encode(encoding) |  | ||||||
|              charset = encoding |  | ||||||
| diff --git a/Lib/email/_policybase.py b/Lib/email/_policybase.py
 |  | ||||||
| index c9cbadd..d1f4821 100644
 |  | ||||||
| --- a/Lib/email/_policybase.py
 |  | ||||||
| +++ b/Lib/email/_policybase.py
 |  | ||||||
| @@ -157,6 +157,13 @@ class Policy(_PolicyBase, metaclass=abc.ABCMeta):
 |  | ||||||
|      message_factory     -- the class to use to create new message objects. |  | ||||||
|                             If the value is None, the default is Message. |  | ||||||
|   |  | ||||||
| +    verify_generated_headers
 |  | ||||||
| +                        -- if true, the generator verifies that each header
 |  | ||||||
| +                           they are properly folded, so that a parser won't
 |  | ||||||
| +                           treat it as multiple headers, start-of-body, or
 |  | ||||||
| +                           part of another header.
 |  | ||||||
| +                           This is a check against custom Header & fold()
 |  | ||||||
| +                           implementations.
 |  | ||||||
|      """ |  | ||||||
|   |  | ||||||
|      raise_on_defect = False |  | ||||||
| @@ -165,6 +172,7 @@ class Policy(_PolicyBase, metaclass=abc.ABCMeta):
 |  | ||||||
|      max_line_length = 78 |  | ||||||
|      mangle_from_ = False |  | ||||||
|      message_factory = None |  | ||||||
| +    verify_generated_headers = True
 |  | ||||||
|   |  | ||||||
|      def handle_defect(self, obj, defect): |  | ||||||
|          """Based on policy, either raise defect or call register_defect. |  | ||||||
| diff --git a/Lib/email/errors.py b/Lib/email/errors.py
 |  | ||||||
| index 3ad0056..02aa5ec 100644
 |  | ||||||
| --- a/Lib/email/errors.py
 |  | ||||||
| +++ b/Lib/email/errors.py
 |  | ||||||
| @@ -29,6 +29,10 @@ class CharsetError(MessageError):
 |  | ||||||
|      """An illegal charset was given.""" |  | ||||||
|   |  | ||||||
|   |  | ||||||
| +class HeaderWriteError(MessageError):
 |  | ||||||
| +    """Error while writing headers."""
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
|  # These are parsing defects which the parser was able to work around. |  | ||||||
|  class MessageDefect(ValueError): |  | ||||||
|      """Base class for a message defect.""" |  | ||||||
| diff --git a/Lib/email/generator.py b/Lib/email/generator.py
 |  | ||||||
| index 7ccbe10..ea87ad2 100644
 |  | ||||||
| --- a/Lib/email/generator.py
 |  | ||||||
| +++ b/Lib/email/generator.py
 |  | ||||||
| @@ -14,12 +14,14 @@ import random
 |  | ||||||
|  from copy import deepcopy |  | ||||||
|  from io import StringIO, BytesIO |  | ||||||
|  from email.utils import _has_surrogates |  | ||||||
| +from email.errors import HeaderWriteError
 |  | ||||||
|   |  | ||||||
|  UNDERSCORE = '_' |  | ||||||
|  NL = '\n'  # XXX: no longer used by the code below. |  | ||||||
|   |  | ||||||
|  NLCRE = re.compile(r'\r\n|\r|\n') |  | ||||||
|  fcre = re.compile(r'^From ', re.MULTILINE) |  | ||||||
| +NEWLINE_WITHOUT_FWSP = re.compile(r'\r\n[^ \t]|\r[^ \n\t]|\n[^ \t]')
 |  | ||||||
|   |  | ||||||
|   |  | ||||||
|  class Generator: |  | ||||||
| @@ -222,7 +224,16 @@ class Generator:
 |  | ||||||
|   |  | ||||||
|      def _write_headers(self, msg): |  | ||||||
|          for h, v in msg.raw_items(): |  | ||||||
| -            self.write(self.policy.fold(h, v))
 |  | ||||||
| +            folded = self.policy.fold(h, v)
 |  | ||||||
| +            if self.policy.verify_generated_headers:
 |  | ||||||
| +                linesep = self.policy.linesep
 |  | ||||||
| +                if not folded.endswith(self.policy.linesep):
 |  | ||||||
| +                    raise HeaderWriteError(
 |  | ||||||
| +                        f'folded header does not end with {linesep!r}: {folded!r}')
 |  | ||||||
| +                if NEWLINE_WITHOUT_FWSP.search(folded.removesuffix(linesep)):
 |  | ||||||
| +                    raise HeaderWriteError(
 |  | ||||||
| +                        f'folded header contains newline: {folded!r}')
 |  | ||||||
| +            self.write(folded)
 |  | ||||||
|          # A blank line always separates headers from body |  | ||||||
|          self.write(self._NL) |  | ||||||
|   |  | ||||||
| diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py
 |  | ||||||
| index 89e7ede..d29400f 100644
 |  | ||||||
| --- a/Lib/test/test_email/test_generator.py
 |  | ||||||
| +++ b/Lib/test/test_email/test_generator.py
 |  | ||||||
| @@ -6,6 +6,7 @@ from email.message import EmailMessage
 |  | ||||||
|  from email.generator import Generator, BytesGenerator |  | ||||||
|  from email.headerregistry import Address |  | ||||||
|  from email import policy |  | ||||||
| +import email.errors
 |  | ||||||
|  from test.test_email import TestEmailBase, parameterize |  | ||||||
|   |  | ||||||
|   |  | ||||||
| @@ -216,6 +217,44 @@ class TestGeneratorBase:
 |  | ||||||
|          g.flatten(msg) |  | ||||||
|          self.assertEqual(s.getvalue(), self.typ(expected)) |  | ||||||
|   |  | ||||||
| +    def test_keep_encoded_newlines(self):
 |  | ||||||
| +        msg = self.msgmaker(self.typ(textwrap.dedent("""\
 |  | ||||||
| +            To: nobody
 |  | ||||||
| +            Subject: Bad subject=?UTF-8?Q?=0A?=Bcc: injection@example.com
 |  | ||||||
| +
 |  | ||||||
| +            None
 |  | ||||||
| +            """)))
 |  | ||||||
| +        expected = textwrap.dedent("""\
 |  | ||||||
| +            To: nobody
 |  | ||||||
| +            Subject: Bad subject=?UTF-8?Q?=0A?=Bcc: injection@example.com
 |  | ||||||
| +
 |  | ||||||
| +            None
 |  | ||||||
| +            """)
 |  | ||||||
| +        s = self.ioclass()
 |  | ||||||
| +        g = self.genclass(s, policy=self.policy.clone(max_line_length=80))
 |  | ||||||
| +        g.flatten(msg)
 |  | ||||||
| +        self.assertEqual(s.getvalue(), self.typ(expected))
 |  | ||||||
| +
 |  | ||||||
| +    def test_keep_long_encoded_newlines(self):
 |  | ||||||
| +        msg = self.msgmaker(self.typ(textwrap.dedent("""\
 |  | ||||||
| +            To: nobody
 |  | ||||||
| +            Subject: Bad subject=?UTF-8?Q?=0A?=Bcc: injection@example.com
 |  | ||||||
| +
 |  | ||||||
| +            None
 |  | ||||||
| +            """)))
 |  | ||||||
| +        expected = textwrap.dedent("""\
 |  | ||||||
| +            To: nobody
 |  | ||||||
| +            Subject: Bad subject
 |  | ||||||
| +             =?utf-8?q?=0A?=Bcc:
 |  | ||||||
| +             injection@example.com
 |  | ||||||
| +
 |  | ||||||
| +            None
 |  | ||||||
| +            """)
 |  | ||||||
| +        s = self.ioclass()
 |  | ||||||
| +        g = self.genclass(s, policy=self.policy.clone(max_line_length=30))
 |  | ||||||
| +        g.flatten(msg)
 |  | ||||||
| +        self.assertEqual(s.getvalue(), self.typ(expected))
 |  | ||||||
| +
 |  | ||||||
|   |  | ||||||
|  class TestGenerator(TestGeneratorBase, TestEmailBase): |  | ||||||
|   |  | ||||||
| @@ -224,6 +263,29 @@ class TestGenerator(TestGeneratorBase, TestEmailBase):
 |  | ||||||
|      ioclass = io.StringIO |  | ||||||
|      typ = str |  | ||||||
|   |  | ||||||
| +    def test_verify_generated_headers(self):
 |  | ||||||
| +        """gh-121650: by default the generator prevents header injection"""
 |  | ||||||
| +        class LiteralHeader(str):
 |  | ||||||
| +            name = 'Header'
 |  | ||||||
| +            def fold(self, **kwargs):
 |  | ||||||
| +                return self
 |  | ||||||
| +
 |  | ||||||
| +        for text in (
 |  | ||||||
| +            'Value\r\nBad Injection\r\n',
 |  | ||||||
| +            'NoNewLine'
 |  | ||||||
| +        ):
 |  | ||||||
| +            with self.subTest(text=text):
 |  | ||||||
| +                message = message_from_string(
 |  | ||||||
| +                    "Header: Value\r\n\r\nBody",
 |  | ||||||
| +                    policy=self.policy,
 |  | ||||||
| +                )
 |  | ||||||
| +
 |  | ||||||
| +                del message['Header']
 |  | ||||||
| +                message['Header'] = LiteralHeader(text)
 |  | ||||||
| +
 |  | ||||||
| +                with self.assertRaises(email.errors.HeaderWriteError):
 |  | ||||||
| +                    message.as_string()
 |  | ||||||
| +
 |  | ||||||
|   |  | ||||||
|  class TestBytesGenerator(TestGeneratorBase, TestEmailBase): |  | ||||||
|   |  | ||||||
| diff --git a/Lib/test/test_email/test_policy.py b/Lib/test/test_email/test_policy.py
 |  | ||||||
| index e87c275..ff1ddf7 100644
 |  | ||||||
| --- a/Lib/test/test_email/test_policy.py
 |  | ||||||
| +++ b/Lib/test/test_email/test_policy.py
 |  | ||||||
| @@ -26,6 +26,7 @@ class PolicyAPITests(unittest.TestCase):
 |  | ||||||
|          'raise_on_defect':          False, |  | ||||||
|          'mangle_from_':             True, |  | ||||||
|          'message_factory':          None, |  | ||||||
| +        'verify_generated_headers': True,
 |  | ||||||
|          } |  | ||||||
|      # These default values are the ones set on email.policy.default. |  | ||||||
|      # If any of these defaults change, the docs must be updated. |  | ||||||
| @@ -277,6 +278,31 @@ class PolicyAPITests(unittest.TestCase):
 |  | ||||||
|                  with self.assertRaises(email.errors.HeaderParseError): |  | ||||||
|                      policy.fold("Subject", subject) |  | ||||||
|   |  | ||||||
| +    def test_verify_generated_headers(self):
 |  | ||||||
| +        """Turning protection off allows header injection"""
 |  | ||||||
| +        policy = email.policy.default.clone(verify_generated_headers=False)
 |  | ||||||
| +        for text in (
 |  | ||||||
| +            'Header: Value\r\nBad: Injection\r\n',
 |  | ||||||
| +            'Header: NoNewLine'
 |  | ||||||
| +        ):
 |  | ||||||
| +            with self.subTest(text=text):
 |  | ||||||
| +                message = email.message_from_string(
 |  | ||||||
| +                    "Header: Value\r\n\r\nBody",
 |  | ||||||
| +                    policy=policy,
 |  | ||||||
| +                )
 |  | ||||||
| +                class LiteralHeader(str):
 |  | ||||||
| +                    name = 'Header'
 |  | ||||||
| +                    def fold(self, **kwargs):
 |  | ||||||
| +                        return self
 |  | ||||||
| +
 |  | ||||||
| +                del message['Header']
 |  | ||||||
| +                message['Header'] = LiteralHeader(text)
 |  | ||||||
| +
 |  | ||||||
| +                self.assertEqual(
 |  | ||||||
| +                    message.as_string(),
 |  | ||||||
| +                    f"{text}\nBody",
 |  | ||||||
| +                )
 |  | ||||||
| +
 |  | ||||||
|      # XXX: Need subclassing tests. |  | ||||||
|      # For adding subclassed objects, make sure the usual rules apply (subclass |  | ||||||
|      # wins), but that the order still works (right overrides left). |  | ||||||
| diff --git a/Misc/NEWS.d/next/Library/2024-07-27-16-10-41.gh-issue-121650.nf6oc9.rst b/Misc/NEWS.d/next/Library/2024-07-27-16-10-41.gh-issue-121650.nf6oc9.rst
 |  | ||||||
| new file mode 100644 |  | ||||||
| index 0000000..83dd28d
 |  | ||||||
| --- /dev/null
 |  | ||||||
| +++ b/Misc/NEWS.d/next/Library/2024-07-27-16-10-41.gh-issue-121650.nf6oc9.rst
 |  | ||||||
| @@ -0,0 +1,5 @@
 |  | ||||||
| +:mod:`email` headers with embedded newlines are now quoted on output. The
 |  | ||||||
| +:mod:`~email.generator` will now refuse to serialize (write) headers that
 |  | ||||||
| +are unsafely folded or delimited; see
 |  | ||||||
| +:attr:`~email.policy.Policy.verify_generated_headers`. (Contributed by Bas
 |  | ||||||
| +Bloemsaat and Petr Viktorin in :gh:`121650`.)
 |  | ||||||
| -- 
 |  | ||||||
| 2.45.2 |  | ||||||
| 
 |  | ||||||
| @ -1,18 +0,0 @@ | |||||||
| -----BEGIN PGP SIGNATURE----- |  | ||||||
| 
 |  | ||||||
| iQKTBAABCgB9FiEEcWlgX2LHUTVtBUomqCHmgOX6YwUFAmVyMspfFIAAAAAALgAo |  | ||||||
| aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDcx |  | ||||||
| Njk2MDVGNjJDNzUxMzU2RDA1NEEyNkE4MjFFNjgwRTVGQTYzMDUACgkQqCHmgOX6 |  | ||||||
| YwWv5w/+JlGtfy+x+6mtauH1uOkt7n9PMQou1LcthDs5s41wuwjO7RbwnmJD6aDk |  | ||||||
| DqwLHheoq6Kjbl6PF1kG2T8ZbHkMudhnc5yH4eQG52IGNQ6evilxoC6AyhVg8ANi |  | ||||||
| +u6Juh9r2Hjz/LDWFB4hzwcOBKy0jYw98+A0uMvpPd2bmdFMBLQE0GTZCdrRsGYs |  | ||||||
| q0oysUX7uCJBfINp7XwiVGAK/6ma0nrr0A1ho6LCau+VGkDnJZdKZgIMyyxp6qL1 |  | ||||||
| 7tMjb3LUpV3FWp57L2za59TaayApNf5BlanC+de6oKEhEJ8oEFyWxOx2GmXHZwch |  | ||||||
| ucj7Z1dxuI7fjNVkEvZ+JuheLGtB9mAmUZslXgUJf5wo49bCo9E4/ZlIFQk7VJR3 |  | ||||||
| Bm9VlQb5mMydB8QJbMy/BpgNjgKmEvBTnir37prJpUV/TL1YZT0eZ5JxCnlUIL/F |  | ||||||
| 6cOzAE3zHPnvHcyHhKV3q5CoONdBtB3RWgS66m4eMneuWoNKaoEbO5IDxtKvCd1J |  | ||||||
| AKLmzCB0/KCWVUIYBTfJ8ytBVQA0Z2w8CZ7SC8asX4DocDCvxim1sQg5s8c4mzh+ |  | ||||||
| 1JVbyqqEmf9m74Mqby0vICC6UVvgaPyiOxTphtRXLIYHUscLVn5+586RMYnM9nP4 |  | ||||||
| nEK+H/fq6Rcp1XEtIPzCG4IPUAYnuDLjbGQegltpKV/SAYn+DGg= |  | ||||||
| =dCpy |  | ||||||
| -----END PGP SIGNATURE----- |  | ||||||
							
								
								
									
										18
									
								
								SOURCES/Python-3.12.5.tar.xz.asc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								SOURCES/Python-3.12.5.tar.xz.asc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | -----BEGIN PGP SIGNATURE----- | ||||||
|  | 
 | ||||||
|  | iQKTBAABCgB9FiEEcWlgX2LHUTVtBUomqCHmgOX6YwUFAmayiFtfFIAAAAAALgAo | ||||||
|  | aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDcx | ||||||
|  | Njk2MDVGNjJDNzUxMzU2RDA1NEEyNkE4MjFFNjgwRTVGQTYzMDUACgkQqCHmgOX6 | ||||||
|  | YwUr4g//VyVs9tvbtiSp8pGe8f1gYErEw54r124sL/CBuNii8Irts1j5ymGxcm+l | ||||||
|  | hshPK5UlqRnhd5dCJWFTvLTXa5Ko2R1L3JyyxfGd1hmDuMhrWsDHijI0R7L/mGM5 | ||||||
|  | 6X2LTaadBVNvk8HaNKvR8SEWvo68rdnOuYElFA9ir7uqwjO26ZWz9FfH80YDGwo8 | ||||||
|  | Blef2NYw8rNhiaZMFV0HYV7D+YyUAZnFNfW8M7Fd4oskUyj1tD9J89T9FFLYN09d | ||||||
|  | BcCIf+EdiEfqRpKxH89bW2g52kDrm4jYGONtpyF8eruyS3YwYSbvbuWioBYKmlxC | ||||||
|  | s51mieXz6G325GTZnmPxLek3ywPv6Gil9y0wH3fIr2BsWsmXust4LBpjDGt56Fy6 | ||||||
|  | seokGBg8xzsBSk3iEqNoFmNsy/QOiuCcDejX4XqBDNodOlETQPJb07TkTI2iOmg9 | ||||||
|  | NG4Atiz1HvGVxK68UuK9IIcNHyaWUmH8h4VQFGvc6KV6feP5Nm21Y12PZ5XIqJBO | ||||||
|  | Y8M/VJIJ5koaNPQfnBbbI5YBkUr4BVpIXIpY5LM/L5sUo2C3R7hMi0VGK88HGfSQ | ||||||
|  | KV4JmZgf6RMBNmrWY12sryS1QQ6q3P110GTUGQWB3sxxNbhmfcrK+4viqHc83yDz | ||||||
|  | ifmk33HuqaQGU7OzUMHeNcoCJIPo3H1FpoHOn9wLLCtA1pT+as4= | ||||||
|  | =t0Rk | ||||||
|  | -----END PGP SIGNATURE----- | ||||||
| @ -16,12 +16,12 @@ URL: https://www.python.org/ | |||||||
| 
 | 
 | ||||||
| #  WARNING  When rebasing to a new Python version, | #  WARNING  When rebasing to a new Python version, | ||||||
| #           remember to update the python3-docs package as well | #           remember to update the python3-docs package as well | ||||||
| %global general_version %{pybasever}.1 | %global general_version %{pybasever}.5 | ||||||
| #global prerel ... | #global prerel ... | ||||||
| %global upstream_version %{general_version}%{?prerel} | %global upstream_version %{general_version}%{?prerel} | ||||||
| Version: %{general_version}%{?prerel:~%{prerel}} | Version: %{general_version}%{?prerel:~%{prerel}} | ||||||
| Release: 4%{?dist}.4 | Release: 2%{?dist}.1 | ||||||
| License: Python | License: Python-2.0.1 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # ================================== | # ================================== | ||||||
| @ -66,36 +66,31 @@ License: Python | |||||||
| # If the rpmwheels condition is disabled, we use the bundled wheel packages | # If the rpmwheels condition is disabled, we use the bundled wheel packages | ||||||
| # from Python with the versions below. | # from Python with the versions below. | ||||||
| # This needs to be manually updated when we update Python. | # This needs to be manually updated when we update Python. | ||||||
| %global pip_version 23.2.1 | %global pip_version 24.2 | ||||||
| %global setuptools_version 67.6.1 | %global setuptools_version 67.6.1 | ||||||
| %global wheel_version 0.40.0 | %global wheel_version 0.40.0 | ||||||
| # All of those also include a list of indirect bundled libs: | # All of those also include a list of indirect bundled libs: | ||||||
| # pip | # pip | ||||||
| #  $ %%{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/ensurepip/_bundled/pip-*.whl pip/_vendor/vendor.txt) | #  $ %%{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/ensurepip/_bundled/pip-*.whl pip/_vendor/vendor.txt) | ||||||
| %global pip_bundled_provides %{expand: | %global pip_bundled_provides %{expand: | ||||||
| Provides: bundled(python3dist(cachecontrol)) = 0.12.11 | Provides: bundled(python3dist(cachecontrol)) = 0.14 | ||||||
| Provides: bundled(python3dist(certifi)) = 2023.5.7 | Provides: bundled(python3dist(certifi)) = 2024.7.4 | ||||||
| Provides: bundled(python3dist(chardet)) = 5.1 | Provides: bundled(python3dist(distlib)) = 0.3.8 | ||||||
| Provides: bundled(python3dist(colorama)) = 0.4.6 | Provides: bundled(python3dist(distro)) = 1.9 | ||||||
| Provides: bundled(python3dist(distlib)) = 0.3.6 | Provides: bundled(python3dist(idna)) = 3.7 | ||||||
| Provides: bundled(python3dist(distro)) = 1.8 | Provides: bundled(python3dist(msgpack)) = 1.0.8 | ||||||
| Provides: bundled(python3dist(idna)) = 3.4 | Provides: bundled(python3dist(packaging)) = 24.1 | ||||||
| Provides: bundled(python3dist(msgpack)) = 1.0.5 | Provides: bundled(python3dist(platformdirs)) = 4.2.2 | ||||||
| Provides: bundled(python3dist(packaging)) = 21.3 | Provides: bundled(python3dist(pygments)) = 2.18 | ||||||
| Provides: bundled(python3dist(platformdirs)) = 3.8.1 |  | ||||||
| Provides: bundled(python3dist(pygments)) = 2.15.1 |  | ||||||
| Provides: bundled(python3dist(pyparsing)) = 3.1 |  | ||||||
| Provides: bundled(python3dist(pyproject-hooks)) = 1 | Provides: bundled(python3dist(pyproject-hooks)) = 1 | ||||||
| Provides: bundled(python3dist(requests)) = 2.31 | Provides: bundled(python3dist(requests)) = 2.32.3 | ||||||
| Provides: bundled(python3dist(resolvelib)) = 1.0.1 | Provides: bundled(python3dist(resolvelib)) = 1.0.1 | ||||||
| Provides: bundled(python3dist(rich)) = 13.4.2 | Provides: bundled(python3dist(rich)) = 13.7.1 | ||||||
| Provides: bundled(python3dist(setuptools)) = 68 | Provides: bundled(python3dist(setuptools)) = 70.3 | ||||||
| Provides: bundled(python3dist(six)) = 1.16 |  | ||||||
| Provides: bundled(python3dist(tenacity)) = 8.2.2 |  | ||||||
| Provides: bundled(python3dist(tomli)) = 2.0.1 | Provides: bundled(python3dist(tomli)) = 2.0.1 | ||||||
| Provides: bundled(python3dist(typing-extensions)) = 4.7.1 | Provides: bundled(python3dist(truststore)) = 0.9.1 | ||||||
| Provides: bundled(python3dist(urllib3)) = 1.26.16 | Provides: bundled(python3dist(typing-extensions)) = 4.12.2 | ||||||
| Provides: bundled(python3dist(webencodings)) = 0.5.1 | Provides: bundled(python3dist(urllib3)) = 1.26.18 | ||||||
| } | } | ||||||
| # setuptools | # setuptools | ||||||
| # vendor.txt files not in .whl | # vendor.txt files not in .whl | ||||||
| @ -116,7 +111,7 @@ Provides: bundled(python3dist(typing-extensions)) = 4.4 | |||||||
| Provides: bundled(python3dist(zipp)) = 3.7 | Provides: bundled(python3dist(zipp)) = 3.7 | ||||||
| } | } | ||||||
| # wheel | # wheel | ||||||
| #  $ %%{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/test/wheel-*.whl wheel/vendored/vendor.txt) | #  $ %%{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/test/wheeldata/wheel-*.whl wheel/vendored/vendor.txt) | ||||||
| %global wheel_bundled_provides %{expand: | %global wheel_bundled_provides %{expand: | ||||||
| Provides: bundled(python3dist(packaging)) = 23 | Provides: bundled(python3dist(packaging)) = 23 | ||||||
| } | } | ||||||
| @ -200,6 +195,13 @@ Provides: bundled(python3dist(packaging)) = 23 | |||||||
| %global py_INSTSONAME_optimized libpython%{LDVERSION_optimized}.so.%{py_SOVERSION} | %global py_INSTSONAME_optimized libpython%{LDVERSION_optimized}.so.%{py_SOVERSION} | ||||||
| %global py_INSTSONAME_debug     libpython%{LDVERSION_debug}.so.%{py_SOVERSION} | %global py_INSTSONAME_debug     libpython%{LDVERSION_debug}.so.%{py_SOVERSION} | ||||||
| 
 | 
 | ||||||
|  | # The -O flag for the compiler, optimized builds | ||||||
|  | # https://fedoraproject.org/wiki/Changes/Python_built_with_gcc_O3 | ||||||
|  | %global optflags_optimized -O3 | ||||||
|  | # The -O flag for the compiler, debug builds | ||||||
|  | # -Wno-cpp avoids some warnings with -O0 | ||||||
|  | %global optflags_debug -O0 -Wno-cpp | ||||||
|  | 
 | ||||||
| # Disable automatic bytecompilation. The python3 binary is not yet be | # Disable automatic bytecompilation. The python3 binary is not yet be | ||||||
| # available in /usr/bin when Python is built. Also, the bytecompilation fails | # available in /usr/bin when Python is built. Also, the bytecompilation fails | ||||||
| # on files that test invalid syntax. | # on files that test invalid syntax. | ||||||
| @ -386,42 +388,18 @@ Patch397: 00397-tarfile-filter.patch | |||||||
| Patch415: 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch | Patch415: 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch | ||||||
| 
 | 
 | ||||||
| # 00422 # a353cebef737c41420dc7ae2469dd657371b8881 | # 00422 # a353cebef737c41420dc7ae2469dd657371b8881 | ||||||
| # gh-115133: Fix tests for XMLPullParser with Expat 2.6.0 | # Fix tests for XMLPullParser with Expat 2.6.0 | ||||||
| # | # | ||||||
| # Feeding the parser by too small chunks defers parsing to prevent | # Feeding the parser by too small chunks defers parsing to prevent | ||||||
| # CVE-2023-52425. Future versions of Expat may be more reactive. | # CVE-2023-52425. Future versions of Expat may be more reactive. | ||||||
| Patch422: 00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch | Patch422: 00422-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch | ||||||
| 
 |  | ||||||
| # 00435 # |  | ||||||
| # Security fix for CVE-2024-6923 |  | ||||||
| # gh-121650: Encode newlines in headers, and verify headers are sound |  | ||||||
| # |  | ||||||
| # Encode header parts that contain newlines |  | ||||||
| # |  | ||||||
| # Per RFC 2047: |  | ||||||
| # |  | ||||||
| # > [...] these encoding schemes allow the |  | ||||||
| # > encoding of arbitrary octet values, mail readers that implement this |  | ||||||
| # > decoding should also ensure that display of the decoded data on the |  | ||||||
| # > recipient's terminal will not cause unwanted side-effects |  | ||||||
| # |  | ||||||
| # It seems that the "quoted-word" scheme is a valid way to include |  | ||||||
| # a newline character in a header value, just like we already allow |  | ||||||
| # undecodable bytes or control characters. |  | ||||||
| # They do need to be properly quoted when serialized to text, though. |  | ||||||
| # |  | ||||||
| # Verify that email headers are well-formed |  | ||||||
| # |  | ||||||
| # This should fail for custom fold() implementations that aren't careful about newlines. |  | ||||||
| # Tracking bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2302255 |  | ||||||
| # Resolved upstream: https://github.com/python/cpython/issues/121650 |  | ||||||
| Patch435: 00435-CVE-2024-6923.patch |  | ||||||
| 
 | 
 | ||||||
| # 00436 # c76cc2aa3a2c30375ade4859b732ada851cc89ed | # 00436 # c76cc2aa3a2c30375ade4859b732ada851cc89ed | ||||||
| # [CVE-2024-8088] gh-122905: Sanitize names in zipfile.Path. | # [CVE-2024-8088] gh-122905: Sanitize names in zipfile.Path. | ||||||
| Patch436: 00436-cve-2024-8088-gh-122905-sanitize-names-in-zipfile-path.patch | Patch436: 00436-cve-2024-8088-gh-122905-sanitize-names-in-zipfile-path.patch | ||||||
| 
 | 
 | ||||||
| # CVE-2024-6232: Remove backtracking when parsing tarfile headers | # 00437 # | ||||||
|  | # CVE-2024-6232: gh-121285: Remove backtracking when parsing tarfile headers | ||||||
| # Resolved upstream: https://github.com/python/cpython/issues/121285 | # Resolved upstream: https://github.com/python/cpython/issues/121285 | ||||||
| Patch437: 00437-CVE-2024-6232.patch | Patch437: 00437-CVE-2024-6232.patch | ||||||
| 
 | 
 | ||||||
| @ -750,13 +728,13 @@ The debug runtime additionally supports debug builds of C-API extensions | |||||||
| # setuptools.whl does not contain the vendored.txt files | # setuptools.whl does not contain the vendored.txt files | ||||||
| if [ -f %{_rpmconfigdir}/pythonbundles.py ]; then | if [ -f %{_rpmconfigdir}/pythonbundles.py ]; then | ||||||
|   %{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/ensurepip/_bundled/pip-*.whl pip/_vendor/vendor.txt) --compare-with '%pip_bundled_provides' |   %{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/ensurepip/_bundled/pip-*.whl pip/_vendor/vendor.txt) --compare-with '%pip_bundled_provides' | ||||||
|   %{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/test/wheel-*.whl wheel/vendored/vendor.txt) --compare-with '%wheel_bundled_provides' |   %{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/test/wheeldata/wheel-*.whl wheel/vendored/vendor.txt) --compare-with '%wheel_bundled_provides' | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
| %if %{with rpmwheels} | %if %{with rpmwheels} | ||||||
| rm Lib/ensurepip/_bundled/pip-%{pip_version}-py3-none-any.whl | rm Lib/ensurepip/_bundled/pip-%{pip_version}-py3-none-any.whl | ||||||
| rm Lib/test/setuptools-%{setuptools_version}-py3-none-any.whl | rm Lib/test/wheeldata/setuptools-%{setuptools_version}-py3-none-any.whl | ||||||
| rm Lib/test/wheel-%{wheel_version}-py3-none-any.whl | rm Lib/test/wheeldata/wheel-%{wheel_version}-py3-none-any.whl | ||||||
| %endif | %endif | ||||||
| 
 | 
 | ||||||
| # Remove all exe files to ensure we are not shipping prebuilt binaries | # Remove all exe files to ensure we are not shipping prebuilt binaries | ||||||
| @ -835,6 +813,7 @@ BuildPython() { | |||||||
|   ConfName=$1 |   ConfName=$1 | ||||||
|   ExtraConfigArgs=$2 |   ExtraConfigArgs=$2 | ||||||
|   MoreCFlags=$3 |   MoreCFlags=$3 | ||||||
|  |   MoreCFlagsNodist=$4 | ||||||
| 
 | 
 | ||||||
|   # Each build is done in its own directory |   # Each build is done in its own directory | ||||||
|   ConfDir=build/$ConfName |   ConfDir=build/$ConfName | ||||||
| @ -874,7 +853,7 @@ BuildPython() { | |||||||
|   $ExtraConfigArgs \ |   $ExtraConfigArgs \ | ||||||
|   %{nil} |   %{nil} | ||||||
| 
 | 
 | ||||||
| %global flags_override EXTRA_CFLAGS="$MoreCFlags" CFLAGS_NODIST="$CFLAGS_NODIST $MoreCFlags" | %global flags_override EXTRA_CFLAGS="$MoreCFlags" CFLAGS_NODIST="$CFLAGS_NODIST $MoreCFlags $MoreCFlagsNodist" | ||||||
| 
 | 
 | ||||||
| %if %{without bootstrap} | %if %{without bootstrap} | ||||||
|   # Regenerate generated files (needs python3) |   # Regenerate generated files (needs python3) | ||||||
| @ -897,12 +876,14 @@ BuildPython() { | |||||||
| # See also: https://bugzilla.redhat.com/show_bug.cgi?id=1818857 | # See also: https://bugzilla.redhat.com/show_bug.cgi?id=1818857 | ||||||
| BuildPython debug \ | BuildPython debug \ | ||||||
|   "--without-ensurepip --with-pydebug" \ |   "--without-ensurepip --with-pydebug" \ | ||||||
|   "-O0 -Wno-cpp" |   "%{optflags_debug}" \ | ||||||
|  |   "" | ||||||
| %endif # with debug_build | %endif # with debug_build | ||||||
| 
 | 
 | ||||||
| BuildPython optimized \ | BuildPython optimized \ | ||||||
|   "--without-ensurepip %{optimizations_flag}" \ |   "--without-ensurepip %{optimizations_flag}" \ | ||||||
|   "" |   "" \ | ||||||
|  |   "%{optflags_optimized}" | ||||||
| 
 | 
 | ||||||
| # ====================================================== | # ====================================================== | ||||||
| # Installing the built code: | # Installing the built code: | ||||||
| @ -1007,7 +988,7 @@ EOF | |||||||
| %if %{with debug_build} | %if %{with debug_build} | ||||||
| InstallPython debug \ | InstallPython debug \ | ||||||
|   %{py_INSTSONAME_debug} \ |   %{py_INSTSONAME_debug} \ | ||||||
|   -O0 \ |   "%{optflags_debug}" \ | ||||||
|   %{LDVERSION_debug} |   %{LDVERSION_debug} | ||||||
| %endif # with debug_build | %endif # with debug_build | ||||||
| 
 | 
 | ||||||
| @ -1382,10 +1363,6 @@ CheckPython optimized | |||||||
| %{dynload_dir}/termios.%{SOABI_optimized}.so | %{dynload_dir}/termios.%{SOABI_optimized}.so | ||||||
| %{dynload_dir}/unicodedata.%{SOABI_optimized}.so | %{dynload_dir}/unicodedata.%{SOABI_optimized}.so | ||||||
| %{dynload_dir}/_uuid.%{SOABI_optimized}.so | %{dynload_dir}/_uuid.%{SOABI_optimized}.so | ||||||
| %{dynload_dir}/xxlimited.%{SOABI_optimized}.so |  | ||||||
| %{dynload_dir}/xxlimited_35.%{SOABI_optimized}.so |  | ||||||
| %{dynload_dir}/_xxsubinterpreters.%{SOABI_optimized}.so |  | ||||||
| %{dynload_dir}/xxsubtype.%{SOABI_optimized}.so |  | ||||||
| %{dynload_dir}/zlib.%{SOABI_optimized}.so | %{dynload_dir}/zlib.%{SOABI_optimized}.so | ||||||
| %{dynload_dir}/_zoneinfo.%{SOABI_optimized}.so | %{dynload_dir}/_zoneinfo.%{SOABI_optimized}.so | ||||||
| 
 | 
 | ||||||
| @ -1486,12 +1463,6 @@ CheckPython optimized | |||||||
| 
 | 
 | ||||||
| %{pylibdir}/zoneinfo | %{pylibdir}/zoneinfo | ||||||
| 
 | 
 | ||||||
| %dir %{pylibdir}/__phello__/ |  | ||||||
| %dir %{pylibdir}/__phello__/__pycache__/ |  | ||||||
| %{pylibdir}/__phello__/__init__.py |  | ||||||
| %{pylibdir}/__phello__/spam.py |  | ||||||
| %{pylibdir}/__phello__/__pycache__/*%{bytecode_suffixes} |  | ||||||
| 
 |  | ||||||
| %if "%{_lib}" == "lib64" | %if "%{_lib}" == "lib64" | ||||||
| %attr(0755,root,root) %dir %{_prefix}/lib/python%{pybasever} | %attr(0755,root,root) %dir %{_prefix}/lib/python%{pybasever} | ||||||
| %attr(0755,root,root) %dir %{_prefix}/lib/python%{pybasever}/site-packages | %attr(0755,root,root) %dir %{_prefix}/lib/python%{pybasever}/site-packages | ||||||
| @ -1586,7 +1557,17 @@ CheckPython optimized | |||||||
| %{dynload_dir}/_testmultiphase.%{SOABI_optimized}.so | %{dynload_dir}/_testmultiphase.%{SOABI_optimized}.so | ||||||
| %{dynload_dir}/_testsinglephase.%{SOABI_optimized}.so | %{dynload_dir}/_testsinglephase.%{SOABI_optimized}.so | ||||||
| %{dynload_dir}/_xxinterpchannels.%{SOABI_optimized}.so | %{dynload_dir}/_xxinterpchannels.%{SOABI_optimized}.so | ||||||
|  | %{dynload_dir}/_xxsubinterpreters.%{SOABI_optimized}.so | ||||||
| %{dynload_dir}/_xxtestfuzz.%{SOABI_optimized}.so | %{dynload_dir}/_xxtestfuzz.%{SOABI_optimized}.so | ||||||
|  | %{dynload_dir}/xxlimited.%{SOABI_optimized}.so | ||||||
|  | %{dynload_dir}/xxlimited_35.%{SOABI_optimized}.so | ||||||
|  | %{dynload_dir}/xxsubtype.%{SOABI_optimized}.so | ||||||
|  | 
 | ||||||
|  | %dir %{pylibdir}/__phello__/ | ||||||
|  | %dir %{pylibdir}/__phello__/__pycache__/ | ||||||
|  | %{pylibdir}/__phello__/__init__.py | ||||||
|  | %{pylibdir}/__phello__/spam.py | ||||||
|  | %{pylibdir}/__phello__/__pycache__/*%{bytecode_suffixes} | ||||||
| 
 | 
 | ||||||
| # We don't bother splitting the debug build out into further subpackages: | # We don't bother splitting the debug build out into further subpackages: | ||||||
| # if you need it, you're probably a developer. | # if you need it, you're probably a developer. | ||||||
| @ -1668,10 +1649,6 @@ CheckPython optimized | |||||||
| %{dynload_dir}/termios.%{SOABI_debug}.so | %{dynload_dir}/termios.%{SOABI_debug}.so | ||||||
| %{dynload_dir}/unicodedata.%{SOABI_debug}.so | %{dynload_dir}/unicodedata.%{SOABI_debug}.so | ||||||
| %{dynload_dir}/_uuid.%{SOABI_debug}.so | %{dynload_dir}/_uuid.%{SOABI_debug}.so | ||||||
| %{dynload_dir}/xxlimited.%{SOABI_debug}.so |  | ||||||
| %{dynload_dir}/xxlimited_35.%{SOABI_debug}.so |  | ||||||
| %{dynload_dir}/_xxsubinterpreters.%{SOABI_debug}.so |  | ||||||
| %{dynload_dir}/xxsubtype.%{SOABI_debug}.so |  | ||||||
| %{dynload_dir}/zlib.%{SOABI_debug}.so | %{dynload_dir}/zlib.%{SOABI_debug}.so | ||||||
| %{dynload_dir}/_zoneinfo.%{SOABI_debug}.so | %{dynload_dir}/_zoneinfo.%{SOABI_debug}.so | ||||||
| 
 | 
 | ||||||
| @ -1708,7 +1685,11 @@ CheckPython optimized | |||||||
| %{dynload_dir}/_testmultiphase.%{SOABI_debug}.so | %{dynload_dir}/_testmultiphase.%{SOABI_debug}.so | ||||||
| %{dynload_dir}/_testsinglephase.%{SOABI_debug}.so | %{dynload_dir}/_testsinglephase.%{SOABI_debug}.so | ||||||
| %{dynload_dir}/_xxinterpchannels.%{SOABI_debug}.so | %{dynload_dir}/_xxinterpchannels.%{SOABI_debug}.so | ||||||
|  | %{dynload_dir}/_xxsubinterpreters.%{SOABI_debug}.so | ||||||
| %{dynload_dir}/_xxtestfuzz.%{SOABI_debug}.so | %{dynload_dir}/_xxtestfuzz.%{SOABI_debug}.so | ||||||
|  | %{dynload_dir}/xxlimited.%{SOABI_debug}.so | ||||||
|  | %{dynload_dir}/xxlimited_35.%{SOABI_debug}.so | ||||||
|  | %{dynload_dir}/xxsubtype.%{SOABI_debug}.so | ||||||
| 
 | 
 | ||||||
| %{pylibdir}/_sysconfigdata_%{ABIFLAGS_debug}_linux_%{platform_triplet}.py | %{pylibdir}/_sysconfigdata_%{ABIFLAGS_debug}_linux_%{platform_triplet}.py | ||||||
| %{pylibdir}/__pycache__/_sysconfigdata_%{ABIFLAGS_debug}_linux_%{platform_triplet}%{bytecode_suffixes} | %{pylibdir}/__pycache__/_sysconfigdata_%{ABIFLAGS_debug}_linux_%{platform_triplet}%{bytecode_suffixes} | ||||||
| @ -1736,22 +1717,52 @@ CheckPython optimized | |||||||
| # ====================================================== | # ====================================================== | ||||||
| 
 | 
 | ||||||
| %changelog | %changelog | ||||||
| * Mon Oct 07 2024 Arti Agrawal <artagraw@redhat.com> - 3.12.1-4.4 | * Wed Sep 11 2024 Lumír Balhar <lbalhar@redhat.com> - 3.12.5-2.1 | ||||||
| - Security fix for CVE-2024-6232 | - Security fix for CVE-2024-6232 | ||||||
| Resolves: RHEL-57416 | Resolves: RHEL-57415 | ||||||
| 
 | 
 | ||||||
| * Fri Aug 23 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.12.1-4.3 | * Fri Aug 23 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.12.5-2 | ||||||
| - Security fix for CVE-2024-8088 | - Security fix for CVE-2024-8088 | ||||||
| Resolves: RHEL-55964 | Resolves: RHEL-55963 | ||||||
| 
 | 
 | ||||||
| * Mon Aug 12 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.12.1-4.2 | * Wed Aug 07 2024 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.12.5-1 | ||||||
|  | - Update to 3.12.5 | ||||||
| - Security fix for CVE-2024-6923 | - Security fix for CVE-2024-6923 | ||||||
| Resolves: RHEL-53087 | Resolves: RHEL-53041 | ||||||
| 
 | 
 | ||||||
| * Fri May 03 2024 Lumír Balhar <lbalhar@redhat.com> - 3.12.1-4.1 | * Thu Jul 25 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.12.4-3 | ||||||
| - Fix tests for XMLPullParser with Expat with fixed CVE | - Properly propagate the optimization flags to C extensions | ||||||
|  | 
 | ||||||
|  | * Wed Jul 17 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.12.4-2 | ||||||
|  | - Build Python with -O3 | ||||||
|  | - https://fedoraproject.org/wiki/Changes/Python_built_with_gcc_O3 | ||||||
|  | 
 | ||||||
|  | * Fri Jun 28 2024 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.12.4-1 | ||||||
|  | - Update to 3.12.4 | ||||||
|  | Resolves: RHEL-44103 | ||||||
|  | 
 | ||||||
|  | * Tue Jun 11 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.12.3-2 | ||||||
| - Enable importing of hash-based .pyc files under FIPS mode | - Enable importing of hash-based .pyc files under FIPS mode | ||||||
| Resolves: RHEL-40773 | Resolves: RHEL-40772 | ||||||
|  | 
 | ||||||
|  | * Fri May 03 2024 Lumír Balhar <lbalhar@redhat.com> - 3.12.3-1 | ||||||
|  | - Update to 3.12.3 | ||||||
|  | Related: RHEL-33690 | ||||||
|  | 
 | ||||||
|  | * Fri May 03 2024 Lumír Balhar <lbalhar@redhat.com> - 3.12.2-3 | ||||||
|  | - Move all test modules to the python3-test package, namely: | ||||||
|  |    - __phello__ | ||||||
|  |    - _xxsubinterpreters | ||||||
|  |    - xxlimited | ||||||
|  |    - xxlimited_35 | ||||||
|  |    - xxsubtype | ||||||
|  | 
 | ||||||
|  | * Fri May 03 2024 Lumír Balhar <lbalhar@redhat.com> - 3.12.2-2 | ||||||
|  | - Fix tests for XMLPullParser with Expat with fixed CVE | ||||||
|  | 
 | ||||||
|  | * Fri May 03 2024 Lumír Balhar <lbalhar@redhat.com> - 3.12.2-1 | ||||||
|  | - Update to 3.12.2 | ||||||
|  | Resolves: RHEL-33690 | ||||||
| 
 | 
 | ||||||
| * Mon Feb 19 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.12.1-4 | * Mon Feb 19 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.12.1-4 | ||||||
| - Add Red Hat configuration for CVE-2007-4559 | - Add Red Hat configuration for CVE-2007-4559 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user