SHA256
1
0
forked from pool/python310

Compare commits

...

37 Commits

Author SHA256 Message Date
6924207e1b Accepting request 1252710 from devel:languages:python:Factory
- Skip PGO with %want_reproducible_builds (bsc#1239210)

OBS-URL: https://build.opensuse.org/request/show/1252710
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=57
2025-03-16 17:58:01 +00:00
39532d51a8 - Skip PGO with %want_reproducible_builds (bsc#1239210)
OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=169
2025-03-13 10:02:26 +00:00
789fc8f6f5 Accepting request 1244096 from devel:languages:python:Factory
- Add CVE-2025-0938-sq-brackets-domain-names.patch which
  disallows square brackets ([ and ]) in domain names for parsed
  URLs (bsc#1236705, CVE-2025-0938, gh#python/cpython#105704)

OBS-URL: https://build.opensuse.org/request/show/1244096
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=56
2025-02-09 18:59:00 +00:00
18c5374a91 - Add CVE-2025-0938-sq-brackets-domain-names.patch which
disallows square brackets ([ and ]) in domain names for parsed
  URLs (bsc#1236705, CVE-2025-0938, gh#python/cpython#105704)

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=167
2025-02-06 21:23:12 +00:00
Ana Guerrero
bca08c148c Accepting request 1228381 from devel:languages:python:Factory
- Update to 3.10.16:
  - Tests
    - gh-125041: Re-enable skipped tests for zlib on the
      s390x architecture: only skip checks of the compressed
      bytes, which can be different between zlib’s software
      implementation and the hardware-accelerated implementation.
    - gh-109396: Fix test_socket.test_hmac_sha1() in FIPS
      mode. Use a longer key: FIPS mode requires at least of at
      least 112 bits. The previous key was only 32 bits. Patch by
      Victor Stinner.
  - Security
    - gh-126623: Upgrade libexpat to 2.6.4
    - gh-122792: Changed IPv4-mapped ipaddress.IPv6Address to
      consistently use the mapped IPv4 address value for deciding
      properties. Properties which have their behavior fixed are
      is_multicast, is_reserved, is_link_local, is_global, and
      is_unspecified (bsc#1233307, CVE-2024-11168).
  - Library
    - gh-124651: Properly quote template strings in venv
      activation scripts (bsc#1232241, CVE-2024-9287).
    - gh-103848: Add checks to ensure that [ bracketed ] hosts
      found by urllib.parse.urlsplit() are of IPv6 or IPvFuture
      format.
- Removed upstreamed patches:
  - CVE-2024-9287-venv_path_unquoted.patch
  - CVE-2024-11168-validation-IPv6-addrs.patch

OBS-URL: https://build.opensuse.org/request/show/1228381
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=55
2024-12-06 13:24:57 +00:00
fd35f5ac9e Fix SPEC
OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=165
2024-12-04 21:33:44 +00:00
8a5d187b75 - Update to 3.10.16:
- Tests
    - gh-125041: Re-enable skipped tests for zlib on the
      s390x architecture: only skip checks of the compressed
      bytes, which can be different between zlib’s software
      implementation and the hardware-accelerated implementation.
    - gh-109396: Fix test_socket.test_hmac_sha1() in FIPS
      mode. Use a longer key: FIPS mode requires at least of at
      least 112 bits. The previous key was only 32 bits. Patch by
      Victor Stinner.
  - Security
    - gh-126623: Upgrade libexpat to 2.6.4
    - gh-122792: Changed IPv4-mapped ipaddress.IPv6Address to
      consistently use the mapped IPv4 address value for deciding
      properties. Properties which have their behavior fixed are
      is_multicast, is_reserved, is_link_local, is_global, and
      is_unspecified (bsc#1233307, CVE-2024-11168).
  - Library
    - gh-124651: Properly quote template strings in venv
      activation scripts (bsc#1232241, CVE-2024-9287).
    - gh-103848: Add checks to ensure that [ bracketed ] hosts
      found by urllib.parse.urlsplit() are of IPv6 or IPvFuture
      format.
- Removed upstreamed patches:
  - CVE-2024-9287-venv_path_unquoted.patch
  - CVE-2024-11168-validation-IPv6-addrs.patch

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=164
2024-12-04 21:28:34 +00:00
Ana Guerrero
98a593499c Accepting request 1227182 from devel:languages:python:Factory
- Apply sphinx-72.patch only conditionally for non-SLE-15 builds.

OBS-URL: https://build.opensuse.org/request/show/1227182
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=54
2024-11-30 12:27:20 +00:00
9a60aeb3ff - Apply sphinx-72.patch only conditionally for non-SLE-15 builds.
OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=162
2024-11-28 18:17:32 +00:00
Ana Guerrero
cae840a2ef Accepting request 1224262 from devel:languages:python:Factory
- Remove -IVendor/ from python-config boo#1231795
- Add CVE-2024-11168-validation-IPv6-addrs.patch
  fixing bsc#1233307 (CVE-2024-11168,
  gh#python/cpython#103848): Improper validation of IPv6 and
  IPvFuture addresses.

OBS-URL: https://build.opensuse.org/request/show/1224262
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=53
2024-11-15 14:37:43 +00:00
622f9d4446 - Remove -IVendor/ from python-config boo#1231795
OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=160
2024-11-14 16:25:57 +00:00
7ee50cc171 - Add CVE-2024-11168-validation-IPv6-addrs.patch
fixing bsc#1233307 (CVE-2024-11168,
  gh#python/cpython#103848): Improper validation of IPv6 and
  IPvFuture addresses.

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=159
2024-11-13 14:50:14 +00:00
Ana Guerrero
87b79dfb11 Accepting request 1221276 from devel:languages:python:Factory
- Update sphinx-72.patch to include renaming :noindex: option to
  :no-index: in Sphinx 7.2 (bsc#1232750).
- While renaming drop fix-sphinx-72.patch.

OBS-URL: https://build.opensuse.org/request/show/1221276
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=52
2024-11-05 14:39:49 +00:00
fa752e2d67 - Update sphinx-72.patch to include renaming :noindex: option to
:no-index: in Sphinx 7.2 (bsc#1232750).
- While renaming drop fix-sphinx-72.patch.

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=157
2024-11-04 21:51:43 +00:00
c683cd8edc Accepting request 1220124 from devel:languages:python:Factory
- Update CVE-2024-9287-venv_path_unquoted.patch according to the
  upstream PR gh#python/cpython!126301.

OBS-URL: https://build.opensuse.org/request/show/1220124
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=51
2024-11-03 06:16:58 +00:00
2bd9540ae5 - Update CVE-2024-9287-venv_path_unquoted.patch according to the
upstream PR gh#python/cpython!126301.

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=155
2024-11-01 21:39:14 +00:00
c35476ebfa Update the patch
OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=154
2024-11-01 16:59:20 +00:00
Ana Guerrero
dfc11afc70 Accepting request 1218122 from devel:languages:python:Factory
- Add CVE-2024-9287-venv_path_unquoted.patch to properly quote
  path names provided when creating a virtual environment
  (bsc#1232241, CVE-2024-9287)
- Drop .pyc files from docdir for reproducible builds
  (bsc#1230906).

OBS-URL: https://build.opensuse.org/request/show/1218122
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=50
2024-10-25 17:19:04 +00:00
f9a24842ef - Add CVE-2024-9287-venv_path_unquoted.patch to properly quote
path names provided when creating a virtual environment
  (bsc#1232241, CVE-2024-9287)

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=152
2024-10-24 20:33:27 +00:00
6d2af095f1 Fix the changelog
OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=151
2024-10-03 15:05:34 +00:00
ff4810a8a2 - Drop .pyc files from docdir for reproducible builds
OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=150
2024-10-02 16:22:51 +00:00
Ana Guerrero
a4325ecaa9 Accepting request 1199711 from devel:languages:python:Factory
- Update to 3.10.15:
  - Tests
    - gh-112769: The tests now correctly compare zlib version
      when :const:`zlib.ZLIB_RUNTIME_VERSION` contains
      non-integer suffixes. For example zlib-ng defines the
      version as ``1.3.0.zlib-ng``.
    - gh-117187: Fix XML tests for vanilla Expat <2.6.0.
    - gh-100454: Fix SSL tests CI for OpenSSL 3.1+
  - Security
    - gh-123678: Upgrade libexpat to 2.6.3
    - gh-121957: Fixed missing audit events around interactive
      use of Python, now also properly firing for ``python -i``,
      as well as for ``python -m asyncio``. The event in question
      is ``cpython.run_stdin``.
    - gh-122133: Authenticate the socket connection for the
      ``socket.socketpair()`` fallback on platforms where
      ``AF_UNIX`` is not available like Windows. Patch by
      Gregory P. Smith <greg@krypto.org> and Seth Larson
      <seth@python.org>. Reported by Ellie <el@horse64.org>
    - gh-121285: Remove backtracking from tarfile header
      parsing for ``hdrcharset``, PAX, and GNU sparse headers
      (bsc#1230227, CVE-2024-6232).
    - gh-118486: :func:`os.mkdir` on Windows now accepts
      *mode* of ``0o700`` to restrict the new directory to
      the current user. This fixes CVE-2024-4030 affecting
      :func:`tempfile.mkdtemp` in scenarios where the base
      temporary directory is more permissive than the default.
    - gh-116741: Update bundled libexpat to 2.6.2
  - Library
    - gh-123693: Use platform-agnostic behavior when computing

OBS-URL: https://build.opensuse.org/request/show/1199711
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=49
2024-09-18 13:26:05 +00:00
805320f21a - Add sphinx-802.patch to overcome working both with the most
recent and older Sphinx versions.

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=148
2024-09-09 15:27:02 +00:00
2999469a13 - Tests
- gh-112769: The tests now correctly compare zlib version
      when :const:`zlib.ZLIB_RUNTIME_VERSION` contains
      non-integer suffixes. For example zlib-ng defines the
      version as ``1.3.0.zlib-ng``.
    - gh-117187: Fix XML tests for vanilla Expat <2.6.0.
    - gh-100454: Fix SSL tests CI for OpenSSL 3.1+
  - Security
    - gh-123678: Upgrade libexpat to 2.6.3
    - gh-121957: Fixed missing audit events around interactive
      use of Python, now also properly firing for ``python -i``,
      as well as for ``python -m asyncio``. The event in question
      is ``cpython.run_stdin``.
    - gh-122133: Authenticate the socket connection for the
      ``socket.socketpair()`` fallback on platforms where
      ``AF_UNIX`` is not available like Windows. Patch by
      Gregory P. Smith <greg@krypto.org> and Seth Larson
      <seth@python.org>. Reported by Ellie <el@horse64.org>
    - gh-121285: Remove backtracking from tarfile header
      parsing for ``hdrcharset``, PAX, and GNU sparse headers
      (bsc#1230227, CVE-2024-6232).
    - gh-118486: :func:`os.mkdir` on Windows now accepts
      *mode* of ``0o700`` to restrict the new directory to
      the current user. This fixes CVE-2024-4030 affecting
      :func:`tempfile.mkdtemp` in scenarios where the base
      temporary directory is more permissive than the default.
    - gh-116741: Update bundled libexpat to 2.6.2
  - Library
    - gh-123693: Use platform-agnostic behavior when computing
      ``zipfile.Path.name``.

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=147
2024-09-09 14:17:15 +00:00
0f267ba848 - Update to 3.10.15:
- Remove upstreamed patches:
  - CVE-2023-27043-email-parsing-errors.patch
  - CVE-2024-4032-private-IP-addrs.patch
  - CVE-2024-6923-email-hdr-inject.patch
  - CVE-2024-8088-inf-loop-zipfile_Path.patch

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=146
2024-09-09 13:51:57 +00:00
50fc7d4d42 - Add gh120226-fix-sendfile-test-kernel-610.patch to avoid
failing test_sendfile_close_peer_in_the_middle_of_receiving
  tests on Linux >= 6.10 (GH-120227).

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=145
2024-09-02 12:12:17 +00:00
b05afb7bf2 Accepting request 1197437 from devel:languages:python:Factory
- Add CVE-2024-8088-inf-loop-zipfile_Path.patch to prevent
  malformed payload to cause infinite loops in zipfile.Path
  (bsc#1229704, CVE-2024-8088).

OBS-URL: https://build.opensuse.org/request/show/1197437
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=48
2024-08-30 11:29:22 +00:00
eb0f4f61b0 Update patch
OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=143
2024-08-29 12:14:10 +00:00
be25887dfa - Add CVE-2024-8088-inf-loop-zipfile_Path.patch to prevent
malformed payload to cause infinite loops in zipfile.Path
  (bsc#1229704, CVE-2024-8088).

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=142
2024-08-29 12:04:00 +00:00
b0e622c8e8 Accepting request 1192675 from devel:languages:python:Factory
- Add CVE-2024-6923-email-hdr-inject.patch to prevent email
  header injection due to unquoted newlines (bsc#1228780,
  CVE-2024-6923).
- Adding bso1227999-reproducible-builds.patch fixing bsc#1227999
  adding reproducibility patches from gh#python/cpython!121872
  and gh#python/cpython!121883.
- %{profileopt} variable is set according to the variable
  %{do_profiling} (bsc#1227999)
- Update bluez-devel-vendor.tar.xz

OBS-URL: https://build.opensuse.org/request/show/1192675
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=47
2024-08-10 17:06:06 +00:00
ca334cc307 - Adding bso1227999-reproducible-builds.patch fixing bsc#1227999
adding reproducibility patches from gh#python/cpython!121872
  and gh#python/cpython!121883.

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=140
2024-08-07 20:30:36 +00:00
a5c76344b0 - Add CVE-2024-6923-email-hdr-inject.patch to prevent email
header injection due to unquoted newlines (bsc#1228780,
  CVE-2024-6923).
- %{profileopt} variable is set according to the variable
  %{do_profiling} (bsc#1227999)
- Update bluez-devel-vendor.tar.xz

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=139
2024-08-07 15:06:12 +00:00
6af8f5b52d Accepting request 1189131 from devel:languages:python:Factory
- Remove %suse_update_desktop_file macro as it is not useful any
  more.

- Stop using %%defattr, it seems to be breaking proper executable
  attributes on /usr/bin/ scripts (bsc#1227378).

OBS-URL: https://build.opensuse.org/request/show/1189131
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=46
2024-07-24 13:33:10 +00:00
351afad84b - Remove %suse_update_desktop_file macro as it is not useful any
more.

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=137
2024-07-22 21:25:49 +00:00
57b3bbe7c5 - Stop using %%defattr, it seems to be breaking proper executable
attributes on /usr/bin/ scripts (bsc#1227378).

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=136
2024-07-15 12:15:29 +00:00
Ana Guerrero
f7b7d9f2f6 Accepting request 1185398 from devel:languages:python:Factory
OBS-URL: https://build.opensuse.org/request/show/1185398
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python310?expand=0&rev=45
2024-07-05 17:45:12 +00:00
ef3a96a70c Accepting request 1184844 from home:dgarcia:usr-local-cpython
- Update F00251-change-user-install-location.patch to make pip and
  modern tools install directly in /usr/local when used by the user.
  bsc#1225660

OBS-URL: https://build.opensuse.org/request/show/1184844
OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=134
2024-07-04 13:17:05 +00:00
17 changed files with 693 additions and 965 deletions

View File

@ -1,461 +0,0 @@
---
Doc/library/email.utils.rst | 19 -
Lib/email/utils.py | 151 +++++++-
Lib/test/test_email/test_email.py | 187 +++++++++-
Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst | 8
4 files changed, 344 insertions(+), 21 deletions(-)
--- a/Doc/library/email.utils.rst
+++ b/Doc/library/email.utils.rst
@@ -60,13 +60,18 @@ of the new API.
begins with angle brackets, they are stripped off.
-.. function:: parseaddr(address)
+.. function:: parseaddr(address, *, strict=True)
Parse address -- which should be the value of some address-containing field such
as :mailheader:`To` or :mailheader:`Cc` -- into its constituent *realname* and
*email address* parts. Returns a tuple of that information, unless the parse
fails, in which case a 2-tuple of ``('', '')`` is returned.
+ If *strict* is true, use a strict parser which rejects malformed inputs.
+
+ .. versionchanged:: 3.13
+ Add *strict* optional parameter and reject malformed inputs by default.
+
.. function:: formataddr(pair, charset='utf-8')
@@ -84,12 +89,15 @@ of the new API.
Added the *charset* option.
-.. function:: getaddresses(fieldvalues)
+.. function:: getaddresses(fieldvalues, *, strict=True)
This method returns a list of 2-tuples of the form returned by ``parseaddr()``.
*fieldvalues* is a sequence of header field values as might be returned by
- :meth:`Message.get_all <email.message.Message.get_all>`. Here's a simple
- example that gets all the recipients of a message::
+ :meth:`Message.get_all <email.message.Message.get_all>`.
+
+ If *strict* is true, use a strict parser which rejects malformed inputs.
+
+ Here's a simple example that gets all the recipients of a message::
from email.utils import getaddresses
@@ -99,6 +107,9 @@ of the new API.
resent_ccs = msg.get_all('resent-cc', [])
all_recipients = getaddresses(tos + ccs + resent_tos + resent_ccs)
+ .. versionchanged:: 3.13
+ Add *strict* optional parameter and reject malformed inputs by default.
+
.. function:: parsedate(date)
--- a/Lib/email/utils.py
+++ b/Lib/email/utils.py
@@ -48,6 +48,7 @@ TICK = "'"
specialsre = re.compile(r'[][\\()<>@,:;".]')
escapesre = re.compile(r'[\\"]')
+
def _has_surrogates(s):
"""Return True if s contains surrogate-escaped binary data."""
# This check is based on the fact that unless there are surrogates, utf8
@@ -106,12 +107,127 @@ def formataddr(pair, charset='utf-8'):
return address
+def _iter_escaped_chars(addr):
+ pos = 0
+ escape = False
+ for pos, ch in enumerate(addr):
+ if escape:
+ yield (pos, '\\' + ch)
+ escape = False
+ elif ch == '\\':
+ escape = True
+ else:
+ yield (pos, ch)
+ if escape:
+ yield (pos, '\\')
+
+
+def _strip_quoted_realnames(addr):
+ """Strip real names between quotes."""
+ if '"' not in addr:
+ # Fast path
+ return addr
+
+ start = 0
+ open_pos = None
+ result = []
+ for pos, ch in _iter_escaped_chars(addr):
+ if ch == '"':
+ if open_pos is None:
+ open_pos = pos
+ else:
+ if start != open_pos:
+ result.append(addr[start:open_pos])
+ start = pos + 1
+ open_pos = None
-def getaddresses(fieldvalues):
- """Return a list of (REALNAME, EMAIL) for each fieldvalue."""
- all = COMMASPACE.join(str(v) for v in fieldvalues)
- a = _AddressList(all)
- return a.addresslist
+ if start < len(addr):
+ result.append(addr[start:])
+
+ return ''.join(result)
+
+
+supports_strict_parsing = True
+
+def getaddresses(fieldvalues, *, strict=True):
+ """Return a list of (REALNAME, EMAIL) or ('','') for each fieldvalue.
+
+ When parsing fails for a fieldvalue, a 2-tuple of ('', '') is returned in
+ its place.
+
+ If strict is true, use a strict parser which rejects malformed inputs.
+ """
+
+ # If strict is true, if the resulting list of parsed addresses is greater
+ # than the number of fieldvalues in the input list, a parsing error has
+ # occurred and consequently a list containing a single empty 2-tuple [('',
+ # '')] is returned in its place. This is done to avoid invalid output.
+ #
+ # Malformed input: getaddresses(['alice@example.com <bob@example.com>'])
+ # Invalid output: [('', 'alice@example.com'), ('', 'bob@example.com')]
+ # Safe output: [('', '')]
+
+ if not strict:
+ all = COMMASPACE.join(str(v) for v in fieldvalues)
+ a = _AddressList(all)
+ return a.addresslist
+
+ fieldvalues = [str(v) for v in fieldvalues]
+ fieldvalues = _pre_parse_validation(fieldvalues)
+ addr = COMMASPACE.join(fieldvalues)
+ a = _AddressList(addr)
+ result = _post_parse_validation(a.addresslist)
+
+ # Treat output as invalid if the number of addresses is not equal to the
+ # expected number of addresses.
+ n = 0
+ for v in fieldvalues:
+ # When a comma is used in the Real Name part it is not a deliminator.
+ # So strip those out before counting the commas.
+ v = _strip_quoted_realnames(v)
+ # Expected number of addresses: 1 + number of commas
+ n += 1 + v.count(',')
+ if len(result) != n:
+ return [('', '')]
+
+ return result
+
+
+def _check_parenthesis(addr):
+ # Ignore parenthesis in quoted real names.
+ addr = _strip_quoted_realnames(addr)
+
+ opens = 0
+ for pos, ch in _iter_escaped_chars(addr):
+ if ch == '(':
+ opens += 1
+ elif ch == ')':
+ opens -= 1
+ if opens < 0:
+ return False
+ return (opens == 0)
+
+
+def _pre_parse_validation(email_header_fields):
+ accepted_values = []
+ for v in email_header_fields:
+ if not _check_parenthesis(v):
+ v = "('', '')"
+ accepted_values.append(v)
+
+ return accepted_values
+
+
+def _post_parse_validation(parsed_email_header_tuples):
+ accepted_values = []
+ # The parser would have parsed a correctly formatted domain-literal
+ # The existence of an [ after parsing indicates a parsing failure
+ for v in parsed_email_header_tuples:
+ if '[' in v[1]:
+ v = ('', '')
+ accepted_values.append(v)
+
+ return accepted_values
def _format_timetuple_and_zone(timetuple, zone):
@@ -205,16 +321,33 @@ def parsedate_to_datetime(data):
tzinfo=datetime.timezone(datetime.timedelta(seconds=tz)))
-def parseaddr(addr):
+def parseaddr(addr, *, strict=True):
"""
Parse addr into its constituent realname and email address parts.
Return a tuple of realname and email address, unless the parse fails, in
which case return a 2-tuple of ('', '').
+
+ If strict is True, use a strict parser which rejects malformed inputs.
"""
- addrs = _AddressList(addr).addresslist
- if not addrs:
- return '', ''
+ if not strict:
+ addrs = _AddressList(addr).addresslist
+ if not addrs:
+ return ('', '')
+ return addrs[0]
+
+ if isinstance(addr, list):
+ addr = addr[0]
+
+ if not isinstance(addr, str):
+ return ('', '')
+
+ addr = _pre_parse_validation([addr])[0]
+ addrs = _post_parse_validation(_AddressList(addr).addresslist)
+
+ if not addrs or len(addrs) > 1:
+ return ('', '')
+
return addrs[0]
--- a/Lib/test/test_email/test_email.py
+++ b/Lib/test/test_email/test_email.py
@@ -16,6 +16,7 @@ from unittest.mock import patch
import email
import email.policy
+import email.utils
from email.charset import Charset
from email.generator import Generator, DecodedGenerator, BytesGenerator
@@ -3288,15 +3289,137 @@ Foo
[('Al Person', 'aperson@dom.ain'),
('Bud Person', 'bperson@dom.ain')])
+ def test_parsing_errors(self):
+ """Test for parsing errors from CVE-2023-27043 and CVE-2019-16056"""
+ alice = 'alice@example.org'
+ bob = 'bob@example.com'
+ empty = ('', '')
+
+ # Test utils.getaddresses() and utils.parseaddr() on malformed email
+ # addresses: default behavior (strict=True) rejects malformed address,
+ # and strict=False which tolerates malformed address.
+ for invalid_separator, expected_non_strict in (
+ ('(', [(f'<{bob}>', alice)]),
+ (')', [('', alice), empty, ('', bob)]),
+ ('<', [('', alice), empty, ('', bob), empty]),
+ ('>', [('', alice), empty, ('', bob)]),
+ ('[', [('', f'{alice}[<{bob}>]')]),
+ (']', [('', alice), empty, ('', bob)]),
+ ('@', [empty, empty, ('', bob)]),
+ (';', [('', alice), empty, ('', bob)]),
+ (':', [('', alice), ('', bob)]),
+ ('.', [('', alice + '.'), ('', bob)]),
+ ('"', [('', alice), ('', f'<{bob}>')]),
+ ):
+ address = f'{alice}{invalid_separator}<{bob}>'
+ with self.subTest(address=address):
+ self.assertEqual(utils.getaddresses([address]),
+ [empty])
+ self.assertEqual(utils.getaddresses([address], strict=False),
+ expected_non_strict)
+
+ self.assertEqual(utils.parseaddr([address]),
+ empty)
+ self.assertEqual(utils.parseaddr([address], strict=False),
+ ('', address))
+
+ # Comma (',') is treated differently depending on strict parameter.
+ # Comma without quotes.
+ address = f'{alice},<{bob}>'
+ self.assertEqual(utils.getaddresses([address]),
+ [('', alice), ('', bob)])
+ self.assertEqual(utils.getaddresses([address], strict=False),
+ [('', alice), ('', bob)])
+ self.assertEqual(utils.parseaddr([address]),
+ empty)
+ self.assertEqual(utils.parseaddr([address], strict=False),
+ ('', address))
+
+ # Real name between quotes containing comma.
+ address = '"Alice, alice@example.org" <bob@example.com>'
+ expected_strict = ('Alice, alice@example.org', 'bob@example.com')
+ self.assertEqual(utils.getaddresses([address]), [expected_strict])
+ self.assertEqual(utils.getaddresses([address], strict=False), [expected_strict])
+ self.assertEqual(utils.parseaddr([address]), expected_strict)
+ self.assertEqual(utils.parseaddr([address], strict=False),
+ ('', address))
+
+ # Valid parenthesis in comments.
+ address = 'alice@example.org (Alice)'
+ expected_strict = ('Alice', 'alice@example.org')
+ self.assertEqual(utils.getaddresses([address]), [expected_strict])
+ self.assertEqual(utils.getaddresses([address], strict=False), [expected_strict])
+ self.assertEqual(utils.parseaddr([address]), expected_strict)
+ self.assertEqual(utils.parseaddr([address], strict=False),
+ ('', address))
+
+ # Invalid parenthesis in comments.
+ address = 'alice@example.org )Alice('
+ self.assertEqual(utils.getaddresses([address]), [empty])
+ self.assertEqual(utils.getaddresses([address], strict=False),
+ [('', 'alice@example.org'), ('', ''), ('', 'Alice')])
+ self.assertEqual(utils.parseaddr([address]), empty)
+ self.assertEqual(utils.parseaddr([address], strict=False),
+ ('', address))
+
+ # Two addresses with quotes separated by comma.
+ address = '"Jane Doe" <jane@example.net>, "John Doe" <john@example.net>'
+ self.assertEqual(utils.getaddresses([address]),
+ [('Jane Doe', 'jane@example.net'),
+ ('John Doe', 'john@example.net')])
+ self.assertEqual(utils.getaddresses([address], strict=False),
+ [('Jane Doe', 'jane@example.net'),
+ ('John Doe', 'john@example.net')])
+ self.assertEqual(utils.parseaddr([address]), empty)
+ self.assertEqual(utils.parseaddr([address], strict=False),
+ ('', address))
+
+ # Test email.utils.supports_strict_parsing attribute
+ self.assertEqual(email.utils.supports_strict_parsing, True)
+
def test_getaddresses_nasty(self):
- eq = self.assertEqual
- eq(utils.getaddresses(['foo: ;']), [('', '')])
- eq(utils.getaddresses(
- ['[]*-- =~$']),
- [('', ''), ('', ''), ('', '*--')])
- eq(utils.getaddresses(
- ['foo: ;', '"Jason R. Mastaler" <jason@dom.ain>']),
- [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')])
+ for addresses, expected in (
+ (['"Sürname, Firstname" <to@example.com>'],
+ [('Sürname, Firstname', 'to@example.com')]),
+
+ (['foo: ;'],
+ [('', '')]),
+
+ (['foo: ;', '"Jason R. Mastaler" <jason@dom.ain>'],
+ [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]),
+
+ ([r'Pete(A nice \) chap) <pete(his account)@silly.test(his host)>'],
+ [('Pete (A nice ) chap his account his host)', 'pete@silly.test')]),
+
+ (['(Empty list)(start)Undisclosed recipients :(nobody(I know))'],
+ [('', '')]),
+
+ (['Mary <@machine.tld:mary@example.net>, , jdoe@test . example'],
+ [('Mary', 'mary@example.net'), ('', ''), ('', 'jdoe@test.example')]),
+
+ (['John Doe <jdoe@machine(comment). example>'],
+ [('John Doe (comment)', 'jdoe@machine.example')]),
+
+ (['"Mary Smith: Personal Account" <smith@home.example>'],
+ [('Mary Smith: Personal Account', 'smith@home.example')]),
+
+ (['Undisclosed recipients:;'],
+ [('', '')]),
+
+ ([r'<boss@nil.test>, "Giant; \"Big\" Box" <bob@example.net>'],
+ [('', 'boss@nil.test'), ('Giant; "Big" Box', 'bob@example.net')]),
+ ):
+ with self.subTest(addresses=addresses):
+ self.assertEqual(utils.getaddresses(addresses),
+ expected)
+ self.assertEqual(utils.getaddresses(addresses, strict=False),
+ expected)
+
+ addresses = ['[]*-- =~$']
+ self.assertEqual(utils.getaddresses(addresses),
+ [('', '')])
+ self.assertEqual(utils.getaddresses(addresses, strict=False),
+ [('', ''), ('', ''), ('', '*--')])
def test_getaddresses_embedded_comment(self):
"""Test proper handling of a nested comment"""
@@ -3485,6 +3608,54 @@ multipart/report
m = cls(*constructor, policy=email.policy.default)
self.assertIs(m.policy, email.policy.default)
+ def test_iter_escaped_chars(self):
+ self.assertEqual(list(utils._iter_escaped_chars(r'a\\b\"c\\"d')),
+ [(0, 'a'),
+ (2, '\\\\'),
+ (3, 'b'),
+ (5, '\\"'),
+ (6, 'c'),
+ (8, '\\\\'),
+ (9, '"'),
+ (10, 'd')])
+ self.assertEqual(list(utils._iter_escaped_chars('a\\')),
+ [(0, 'a'), (1, '\\')])
+
+ def test_strip_quoted_realnames(self):
+ def check(addr, expected):
+ self.assertEqual(utils._strip_quoted_realnames(addr), expected)
+
+ check('"Jane Doe" <jane@example.net>, "John Doe" <john@example.net>',
+ ' <jane@example.net>, <john@example.net>')
+ check(r'"Jane \"Doe\"." <jane@example.net>',
+ ' <jane@example.net>')
+
+ # special cases
+ check(r'before"name"after', 'beforeafter')
+ check(r'before"name"', 'before')
+ check(r'b"name"', 'b') # single char
+ check(r'"name"after', 'after')
+ check(r'"name"a', 'a') # single char
+ check(r'"name"', '')
+
+ # no change
+ for addr in (
+ 'Jane Doe <jane@example.net>, John Doe <john@example.net>',
+ 'lone " quote',
+ ):
+ self.assertEqual(utils._strip_quoted_realnames(addr), addr)
+
+
+ def test_check_parenthesis(self):
+ addr = 'alice@example.net'
+ self.assertTrue(utils._check_parenthesis(f'{addr} (Alice)'))
+ self.assertFalse(utils._check_parenthesis(f'{addr} )Alice('))
+ self.assertFalse(utils._check_parenthesis(f'{addr} (Alice))'))
+ self.assertFalse(utils._check_parenthesis(f'{addr} ((Alice)'))
+
+ # Ignore real name between quotes
+ self.assertTrue(utils._check_parenthesis(f'")Alice((" {addr}'))
+
# Test the iterator/generators
class TestIterators(TestEmailBase):
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst
@@ -0,0 +1,8 @@
+:func:`email.utils.getaddresses` and :func:`email.utils.parseaddr` now
+return ``('', '')`` 2-tuples in more situations where invalid email
+addresses are encountered instead of potentially inaccurate values. Add
+optional *strict* parameter to these two functions: use ``strict=False`` to
+get the old behavior, accept malformed inputs.
+``getattr(email.utils, 'supports_strict_parsing', False)`` can be use to check
+if the *strict* paramater is available. Patch by Thomas Dwyer and Victor
+Stinner to improve the CVE-2023-27043 fix.

View File

@ -45,7 +45,7 @@
def test_simple_xml_chunk_5(self):
self.test_simple_xml(chunk_size=5, flush=True)
@@ -1648,6 +1652,9 @@ class XMLPullParserTest(unittest.TestCas
@@ -1647,6 +1651,9 @@ class XMLPullParserTest(unittest.TestCas
self.assert_event_tags(parser, [('end', 'doc')])

View File

@ -1,376 +0,0 @@
From 0740166e60b8cdae9448220beb28721f0126ee03 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <encukou@gmail.com>
Date: Wed, 24 Apr 2024 14:29:30 +0200
Subject: [PATCH 1/2] gh-113171: gh-65056: Fix "private" (non-global) IP
address ranges (GH-113179) (GH-113186) (GH-118177)
* GH-113171: Fix "private" (non-global) IP address ranges (GH-113179)
The _private_networks variables, used by various is_private
implementations, were missing some ranges and at the same time had
overly strict ranges (where there are more specific ranges considered
globally reachable by the IANA registries).
This patch updates the ranges with what was missing or otherwise
incorrect.
100.64.0.0/10 is left alone, for now, as it's been made special in [1].
The _address_exclude_many() call returns 8 networks for IPv4, 121
networks for IPv6.
[1] https://github.com/python/cpython/issues/61602
* GH-65056: Improve the IP address' is_global/is_private documentation (GH-113186)
It wasn't clear what the semantics of is_global/is_private are and, when
one gets to the bottom of it, it's not quite so simple (hence the
exceptions listed).
(cherry picked from commit 2a4cbf17af19a01d942f9579342f77c39fbd23c4)
(cherry picked from commit 40d75c2b7f5c67e254d0a025e0f2e2c7ada7f69f)
---------
(cherry picked from commit f86b17ac511e68192ba71f27e752321a3252cee3)
Co-authored-by: Jakub Stasiak <jakub@stasiak.at>
---
Doc/library/ipaddress.rst | 43 +++-
Doc/whatsnew/3.10.rst | 9
Lib/ipaddress.py | 99 +++++++---
Lib/test/test_ipaddress.py | 52 +++++
Misc/NEWS.d/next/Library/2024-03-14-01-38-44.gh-issue-113171.VFnObz.rst | 9
5 files changed, 187 insertions(+), 25 deletions(-)
create mode 100644 Misc/NEWS.d/next/Library/2024-03-14-01-38-44.gh-issue-113171.VFnObz.rst
--- a/Doc/library/ipaddress.rst
+++ b/Doc/library/ipaddress.rst
@@ -188,18 +188,53 @@ write code that handles both IP versions
.. attribute:: is_private
- ``True`` if the address is allocated for private networks. See
+ ``True`` if the address is defined as not globally reachable by
iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
- (for IPv6).
+ (for IPv6) with the following exceptions:
+
+ * ``is_private`` is ``False`` for the shared address space (``100.64.0.0/10``)
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
+ semantics of the underlying IPv4 addresses and the following condition holds
+ (see :attr:`IPv6Address.ipv4_mapped`)::
+
+ address.is_private == address.ipv4_mapped.is_private
+
+ ``is_private`` has value opposite to :attr:`is_global`, except for the shared address space
+ (``100.64.0.0/10`` range) where they are both ``False``.
+
+ .. versionchanged:: 3.10.15
+
+ Fixed some false positives and false negatives.
+
+ * ``192.0.0.0/24`` is considered private with the exception of ``192.0.0.9/32`` and
+ ``192.0.0.10/32`` (previously: only the ``192.0.0.0/29`` sub-range was considered private).
+ * ``64:ff9b:1::/48`` is considered private.
+ * ``2002::/16`` is considered private.
+ * There are exceptions within ``2001::/23`` (otherwise considered private): ``2001:1::1/128``,
+ ``2001:1::2/128``, ``2001:3::/32``, ``2001:4:112::/48``, ``2001:20::/28``, ``2001:30::/28``.
+ The exceptions are not considered private.
.. attribute:: is_global
- ``True`` if the address is allocated for public networks. See
+ ``True`` if the address is defined as globally reachable by
iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
- (for IPv6).
+ (for IPv6) with the following exception:
+
+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
+ semantics of the underlying IPv4 addresses and the following condition holds
+ (see :attr:`IPv6Address.ipv4_mapped`)::
+
+ address.is_global == address.ipv4_mapped.is_global
+
+ ``is_global`` has value opposite to :attr:`is_private`, except for the shared address space
+ (``100.64.0.0/10`` range) where they are both ``False``.
.. versionadded:: 3.4
+ .. versionchanged:: 3.10.15
+
+ Fixed some false positives and false negatives, see :attr:`is_private` for details.
+
.. attribute:: is_unspecified
``True`` if the address is unspecified. See :RFC:`5735` (for IPv4)
--- a/Doc/whatsnew/3.10.rst
+++ b/Doc/whatsnew/3.10.rst
@@ -2348,3 +2348,12 @@ tarfile
:exc:`DeprecationWarning`.
In Python 3.14, the default will switch to ``'data'``.
(Contributed by Petr Viktorin in :pep:`706`.)
+
+Notable changes in 3.10.15
+==========================
+
+ipaddress
+---------
+
+* Fixed ``is_global`` and ``is_private`` behavior in ``IPv4Address``,
+ ``IPv6Address``, ``IPv4Network`` and ``IPv6Network``.
--- a/Lib/ipaddress.py
+++ b/Lib/ipaddress.py
@@ -1323,18 +1323,41 @@ class IPv4Address(_BaseV4, _BaseAddress)
@property
@functools.lru_cache()
def is_private(self):
- """Test if this address is allocated for private networks.
-
- Returns:
- A boolean, True if the address is reserved per
- iana-ipv4-special-registry.
-
- """
- return any(self in net for net in self._constants._private_networks)
+ """``True`` if the address is defined as not globally reachable by
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
+ (for IPv6) with the following exceptions:
+
+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
+ semantics of the underlying IPv4 addresses and the following condition holds
+ (see :attr:`IPv6Address.ipv4_mapped`)::
+
+ address.is_private == address.ipv4_mapped.is_private
+
+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
+ IPv4 range where they are both ``False``.
+ """
+ return (
+ any(self in net for net in self._constants._private_networks)
+ and all(self not in net for net in self._constants._private_networks_exceptions)
+ )
@property
@functools.lru_cache()
def is_global(self):
+ """``True`` if the address is defined as globally reachable by
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
+ (for IPv6) with the following exception:
+
+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
+ semantics of the underlying IPv4 addresses and the following condition holds
+ (see :attr:`IPv6Address.ipv4_mapped`)::
+
+ address.is_global == address.ipv4_mapped.is_global
+
+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
+ IPv4 range where they are both ``False``.
+ """
return self not in self._constants._public_network and not self.is_private
@property
@@ -1538,13 +1561,15 @@ class _IPv4Constants:
_public_network = IPv4Network('100.64.0.0/10')
+ # Not globally reachable address blocks listed on
+ # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
_private_networks = [
IPv4Network('0.0.0.0/8'),
IPv4Network('10.0.0.0/8'),
IPv4Network('127.0.0.0/8'),
IPv4Network('169.254.0.0/16'),
IPv4Network('172.16.0.0/12'),
- IPv4Network('192.0.0.0/29'),
+ IPv4Network('192.0.0.0/24'),
IPv4Network('192.0.0.170/31'),
IPv4Network('192.0.2.0/24'),
IPv4Network('192.168.0.0/16'),
@@ -1555,6 +1580,11 @@ class _IPv4Constants:
IPv4Network('255.255.255.255/32'),
]
+ _private_networks_exceptions = [
+ IPv4Network('192.0.0.9/32'),
+ IPv4Network('192.0.0.10/32'),
+ ]
+
_reserved_network = IPv4Network('240.0.0.0/4')
_unspecified_address = IPv4Address('0.0.0.0')
@@ -1996,27 +2026,42 @@ class IPv6Address(_BaseV6, _BaseAddress)
@property
@functools.lru_cache()
def is_private(self):
- """Test if this address is allocated for private networks.
+ """``True`` if the address is defined as not globally reachable by
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
+ (for IPv6) with the following exceptions:
+
+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
+ semantics of the underlying IPv4 addresses and the following condition holds
+ (see :attr:`IPv6Address.ipv4_mapped`)::
- Returns:
- A boolean, True if the address is reserved per
- iana-ipv6-special-registry, or is ipv4_mapped and is
- reserved in the iana-ipv4-special-registry.
+ address.is_private == address.ipv4_mapped.is_private
+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
+ IPv4 range where they are both ``False``.
"""
ipv4_mapped = self.ipv4_mapped
if ipv4_mapped is not None:
return ipv4_mapped.is_private
- return any(self in net for net in self._constants._private_networks)
+ return (
+ any(self in net for net in self._constants._private_networks)
+ and all(self not in net for net in self._constants._private_networks_exceptions)
+ )
@property
def is_global(self):
- """Test if this address is allocated for public networks.
+ """``True`` if the address is defined as globally reachable by
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
+ (for IPv6) with the following exception:
+
+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
+ semantics of the underlying IPv4 addresses and the following condition holds
+ (see :attr:`IPv6Address.ipv4_mapped`)::
- Returns:
- A boolean, true if the address is not reserved per
- iana-ipv6-special-registry.
+ address.is_global == address.ipv4_mapped.is_global
+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
+ IPv4 range where they are both ``False``.
"""
return not self.is_private
@@ -2257,19 +2302,31 @@ class _IPv6Constants:
_multicast_network = IPv6Network('ff00::/8')
+ # Not globally reachable address blocks listed on
+ # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
_private_networks = [
IPv6Network('::1/128'),
IPv6Network('::/128'),
IPv6Network('::ffff:0:0/96'),
+ IPv6Network('64:ff9b:1::/48'),
IPv6Network('100::/64'),
IPv6Network('2001::/23'),
- IPv6Network('2001:2::/48'),
IPv6Network('2001:db8::/32'),
- IPv6Network('2001:10::/28'),
+ # IANA says N/A, let's consider it not globally reachable to be safe
+ IPv6Network('2002::/16'),
IPv6Network('fc00::/7'),
IPv6Network('fe80::/10'),
]
+ _private_networks_exceptions = [
+ IPv6Network('2001:1::1/128'),
+ IPv6Network('2001:1::2/128'),
+ IPv6Network('2001:3::/32'),
+ IPv6Network('2001:4:112::/48'),
+ IPv6Network('2001:20::/28'),
+ IPv6Network('2001:30::/28'),
+ ]
+
_reserved_networks = [
IPv6Network('::/8'), IPv6Network('100::/8'),
IPv6Network('200::/7'), IPv6Network('400::/6'),
--- a/Lib/test/test_ipaddress.py
+++ b/Lib/test/test_ipaddress.py
@@ -2263,6 +2263,10 @@ class IpaddrUnitTest(unittest.TestCase):
self.assertEqual(True, ipaddress.ip_address(
'172.31.255.255').is_private)
self.assertEqual(False, ipaddress.ip_address('172.32.0.0').is_private)
+ self.assertFalse(ipaddress.ip_address('192.0.0.0').is_global)
+ self.assertTrue(ipaddress.ip_address('192.0.0.9').is_global)
+ self.assertTrue(ipaddress.ip_address('192.0.0.10').is_global)
+ self.assertFalse(ipaddress.ip_address('192.0.0.255').is_global)
self.assertEqual(True,
ipaddress.ip_address('169.254.100.200').is_link_local)
@@ -2278,6 +2282,40 @@ class IpaddrUnitTest(unittest.TestCase):
self.assertEqual(False, ipaddress.ip_address('128.0.0.0').is_loopback)
self.assertEqual(True, ipaddress.ip_network('0.0.0.0').is_unspecified)
+ def testPrivateNetworks(self):
+ self.assertEqual(True, ipaddress.ip_network("0.0.0.0/0").is_private)
+ self.assertEqual(False, ipaddress.ip_network("1.0.0.0/8").is_private)
+
+ self.assertEqual(True, ipaddress.ip_network("0.0.0.0/8").is_private)
+ self.assertEqual(True, ipaddress.ip_network("10.0.0.0/8").is_private)
+ self.assertEqual(True, ipaddress.ip_network("127.0.0.0/8").is_private)
+ self.assertEqual(True, ipaddress.ip_network("169.254.0.0/16").is_private)
+ self.assertEqual(True, ipaddress.ip_network("172.16.0.0/12").is_private)
+ self.assertEqual(True, ipaddress.ip_network("192.0.0.0/29").is_private)
+ self.assertEqual(False, ipaddress.ip_network("192.0.0.9/32").is_private)
+ self.assertEqual(True, ipaddress.ip_network("192.0.0.170/31").is_private)
+ self.assertEqual(True, ipaddress.ip_network("192.0.2.0/24").is_private)
+ self.assertEqual(True, ipaddress.ip_network("192.168.0.0/16").is_private)
+ self.assertEqual(True, ipaddress.ip_network("198.18.0.0/15").is_private)
+ self.assertEqual(True, ipaddress.ip_network("198.51.100.0/24").is_private)
+ self.assertEqual(True, ipaddress.ip_network("203.0.113.0/24").is_private)
+ self.assertEqual(True, ipaddress.ip_network("240.0.0.0/4").is_private)
+ self.assertEqual(True, ipaddress.ip_network("255.255.255.255/32").is_private)
+
+ self.assertEqual(False, ipaddress.ip_network("::/0").is_private)
+ self.assertEqual(False, ipaddress.ip_network("::ff/128").is_private)
+
+ self.assertEqual(True, ipaddress.ip_network("::1/128").is_private)
+ self.assertEqual(True, ipaddress.ip_network("::/128").is_private)
+ self.assertEqual(True, ipaddress.ip_network("::ffff:0:0/96").is_private)
+ self.assertEqual(True, ipaddress.ip_network("100::/64").is_private)
+ self.assertEqual(True, ipaddress.ip_network("2001:2::/48").is_private)
+ self.assertEqual(False, ipaddress.ip_network("2001:3::/48").is_private)
+ self.assertEqual(True, ipaddress.ip_network("2001:db8::/32").is_private)
+ self.assertEqual(True, ipaddress.ip_network("2001:10::/28").is_private)
+ self.assertEqual(True, ipaddress.ip_network("fc00::/7").is_private)
+ self.assertEqual(True, ipaddress.ip_network("fe80::/10").is_private)
+
def testReservedIpv6(self):
self.assertEqual(True, ipaddress.ip_network('ffff::').is_multicast)
@@ -2351,6 +2389,20 @@ class IpaddrUnitTest(unittest.TestCase):
self.assertEqual(True, ipaddress.ip_address('0::0').is_unspecified)
self.assertEqual(False, ipaddress.ip_address('::1').is_unspecified)
+ self.assertFalse(ipaddress.ip_address('64:ff9b:1::').is_global)
+ self.assertFalse(ipaddress.ip_address('2001::').is_global)
+ self.assertTrue(ipaddress.ip_address('2001:1::1').is_global)
+ self.assertTrue(ipaddress.ip_address('2001:1::2').is_global)
+ self.assertFalse(ipaddress.ip_address('2001:2::').is_global)
+ self.assertTrue(ipaddress.ip_address('2001:3::').is_global)
+ self.assertFalse(ipaddress.ip_address('2001:4::').is_global)
+ self.assertTrue(ipaddress.ip_address('2001:4:112::').is_global)
+ self.assertFalse(ipaddress.ip_address('2001:10::').is_global)
+ self.assertTrue(ipaddress.ip_address('2001:20::').is_global)
+ self.assertTrue(ipaddress.ip_address('2001:30::').is_global)
+ self.assertFalse(ipaddress.ip_address('2001:40::').is_global)
+ self.assertFalse(ipaddress.ip_address('2002::').is_global)
+
# some generic IETF reserved addresses
self.assertEqual(True, ipaddress.ip_address('100::').is_reserved)
self.assertEqual(True, ipaddress.ip_network('4000::1/128').is_reserved)
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-03-14-01-38-44.gh-issue-113171.VFnObz.rst
@@ -0,0 +1,9 @@
+Fixed various false positives and false negatives in
+
+* :attr:`ipaddress.IPv4Address.is_private` (see these docs for details)
+* :attr:`ipaddress.IPv4Address.is_global`
+* :attr:`ipaddress.IPv6Address.is_private`
+* :attr:`ipaddress.IPv6Address.is_global`
+
+Also in the corresponding :class:`ipaddress.IPv4Network` and :class:`ipaddress.IPv6Network`
+attributes.

View File

@ -0,0 +1,127 @@
From d91e2c740890837edafaee24d68112b776cda9c5 Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <seth@python.org>
Date: Fri, 31 Jan 2025 11:41:34 -0600
Subject: [PATCH] gh-105704: Disallow square brackets (`[` and `]`) in domain
names for parsed URLs (GH-129418)
* gh-105704: Disallow square brackets ( and ) in domain names for parsed URLs
* Use Sphinx references
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
* Add mismatched bracket test cases, fix news format
* Add more test coverage for ports
---------
(cherry picked from commit d89a5f6a6e65511a5f6e0618c4c30a7aa5aba56a)
Co-authored-by: Seth Michael Larson <seth@python.org>
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
---
Lib/test/test_urlparse.py | 37 +++++++++-
Lib/urllib/parse.py | 20 ++++-
Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst | 4 +
3 files changed, 58 insertions(+), 3 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst
--- a/Lib/test/test_urlparse.py
+++ b/Lib/test/test_urlparse.py
@@ -1149,16 +1149,51 @@ class UrlParseTestCase(unittest.TestCase
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af::2309::fae7:1234]/Path?Query')
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af:2309::fae7:1234:2342:438e:192.0.2.146]/Path?Query')
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@]v6a.ip[/Path')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]/')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix/')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]?')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix?')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]/')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix/')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]?')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix?')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:a')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:a')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:a1')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:a1')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:1a')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:1a')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:/')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:?')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://user@prefix.[v6a.ip]')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://user@[v6a.ip].suffix')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip]')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://]v6a.ip[')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://]v6a.ip')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip[')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip].suffix')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix]v6a.ip[suffix')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix]v6a.ip')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip[suffix')
def test_splitting_bracketed_hosts(self):
- p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]/path?query')
+ p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]:1234/path?query')
self.assertEqual(p1.hostname, 'v6a.ip')
self.assertEqual(p1.username, 'user')
self.assertEqual(p1.path, '/path')
+ self.assertEqual(p1.port, 1234)
p2 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7%test]/path?query')
self.assertEqual(p2.hostname, '0439:23af:2309::fae7%test')
self.assertEqual(p2.username, 'user')
self.assertEqual(p2.path, '/path')
+ self.assertIs(p2.port, None)
p3 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7:1234:192.0.2.146%test]/path?query')
self.assertEqual(p3.hostname, '0439:23af:2309::fae7:1234:192.0.2.146%test')
self.assertEqual(p3.username, 'user')
--- a/Lib/urllib/parse.py
+++ b/Lib/urllib/parse.py
@@ -442,6 +442,23 @@ def _checknetloc(netloc):
raise ValueError("netloc '" + netloc + "' contains invalid " +
"characters under NFKC normalization")
+def _check_bracketed_netloc(netloc):
+ # Note that this function must mirror the splitting
+ # done in NetlocResultMixins._hostinfo().
+ hostname_and_port = netloc.rpartition('@')[2]
+ before_bracket, have_open_br, bracketed = hostname_and_port.partition('[')
+ if have_open_br:
+ # No data is allowed before a bracket.
+ if before_bracket:
+ raise ValueError("Invalid IPv6 URL")
+ hostname, _, port = bracketed.partition(']')
+ # No data is allowed after the bracket but before the port delimiter.
+ if port and not port.startswith(":"):
+ raise ValueError("Invalid IPv6 URL")
+ else:
+ hostname, _, port = hostname_and_port.partition(':')
+ _check_bracketed_host(hostname)
+
# Valid bracketed hosts are defined in
# https://www.rfc-editor.org/rfc/rfc3986#page-49 and https://url.spec.whatwg.org/
def _check_bracketed_host(hostname):
@@ -505,8 +522,7 @@ def urlsplit(url, scheme='', allow_fragm
(']' in netloc and '[' not in netloc)):
raise ValueError("Invalid IPv6 URL")
if '[' in netloc and ']' in netloc:
- bracketed_host = netloc.partition('[')[2].partition(']')[0]
- _check_bracketed_host(bracketed_host)
+ _check_bracketed_netloc(netloc)
if allow_fragments and '#' in url:
url, fragment = url.split('#', 1)
if '?' in url:
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst
@@ -0,0 +1,4 @@
+When using :func:`urllib.parse.urlsplit` and :func:`urllib.parse.urlparse` host
+parsing would not reject domain names containing square brackets (``[`` and
+``]``). Square brackets are only valid for IPv6 and IPvFuture hosts according to
+`RFC 3986 Section 3.2.2 <https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2>`__.

View File

@ -13,8 +13,10 @@ Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
Lib/site.py | 9 ++++++++-
2 files changed, 21 insertions(+), 3 deletions(-)
--- a/Lib/distutils/command/install.py
+++ b/Lib/distutils/command/install.py
Index: Python-3.10.14/Lib/distutils/command/install.py
===================================================================
--- Python-3.10.14.orig/Lib/distutils/command/install.py
+++ Python-3.10.14/Lib/distutils/command/install.py
@@ -441,8 +441,19 @@ class install(Command):
raise DistutilsOptionError(
"must not supply exec-prefix without prefix")
@ -37,8 +39,10 @@ Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
else:
if self.exec_prefix is None:
--- a/Lib/site.py
+++ b/Lib/site.py
Index: Python-3.10.14/Lib/site.py
===================================================================
--- Python-3.10.14.orig/Lib/site.py
+++ Python-3.10.14/Lib/site.py
@@ -390,8 +390,15 @@ def getsitepackages(prefixes=None):
return sitepackages
@ -56,3 +60,128 @@ Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
for sitedir in getsitepackages(prefixes):
if os.path.isdir(sitedir):
addsitedir(sitedir, known_paths)
Index: Python-3.10.14/Lib/sysconfig.py
===================================================================
--- Python-3.10.14.orig/Lib/sysconfig.py
+++ Python-3.10.14/Lib/sysconfig.py
@@ -117,6 +117,19 @@ if _HAS_USER_BASE:
},
}
+# 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')
@@ -136,6 +149,16 @@ _variable_rx = r"([a-zA-Z][a-zA-Z0-9_]+)
_findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)"
_findvar2_rx = r"\${([A-Za-z][A-Za-z0-9_]*)}"
+# 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']
+
+# 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']
+
def _safe_realpath(path):
try:
@@ -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'):
Index: Python-3.10.14/Lib/test/test_sysconfig.py
===================================================================
--- Python-3.10.14.orig/Lib/test/test_sysconfig.py
+++ Python-3.10.14/Lib/test/test_sysconfig.py
@@ -105,8 +105,19 @@ class TestSysConfig(unittest.TestCase):
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 @@ class TestSysConfig(unittest.TestCase):
self.assertTrue(os.path.isfile(config_h), config_h)
def test_get_scheme_names(self):
- wanted = ['nt', 'posix_home', 'posix_prefix']
+ wanted = ['nt', 'posix_home', 'posix_prefix', 'rpm_prefix']
if HAS_USER_BASE:
wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
@@ -274,6 +285,8 @@ class TestSysConfig(unittest.TestCase):
cmd = "-c", "import sysconfig; print(sysconfig.get_platform())"
self.assertEqual(py.call_real(*cmd), py.call_link(*cmd))
+ @unittest.skipIf('RPM_BUILD_ROOT' not in os.environ,
+ "Test doesn't expect Fedora's paths")
def test_user_similar(self):
# Issue #8759: make sure the posix scheme for the users
# is similar to the global posix_prefix one

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9c50481faa8c2832329ba0fc8868d0a606a680fc4f60ec48d26ce8e076751fda
size 19600188

View File

@ -1,16 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEz9yiRbEEPPKl+Xhl/+h0BBaL2EcFAmX76AkACgkQ/+h0BBaL
2EeKvhAAuN+7X3iFv8tYwUTbKJT9x9fLsADI5wOn5j8xuDiXQCOMzsqqyB1RSdEd
tbCQXg9XJj1bVHc4DY337vUix9jvFcTqbQqlzUm/peX4buY2bKkZu2quti1iWSJf
IN26jDYO2TobPvGdvNiH2Hceqe1dc5tU7iYEfaLR5ImgO4aGgK6x4DiLdmFqo2bk
ZZWZLkXbwenrSdLVmUZLP5Gg2dsfMkbfFpydau9Zk3RVl6mVYATwzJaY9K5otC0K
7kc+nKPwkTxKAjndbznjsVrWK0Xcr4hrlMHs4Re2Nrdqa2mVd1jAAFO5xETJJtd7
YqL6mQuJ9wQfEEq2QWz1hEi67l8g8VeEgzYQOjZ6pTxwYYt0YDfKBjRtRCWuJ11c
w6Q+pniGcgIHAMkQGjZds88CwAdIiyG7IAIT2ovW+xVxH/JqLPHeRsHMKYx4DPqL
2y23Tchw+gBUvmbwCdObXWL1eq5R3Xz3ikkdX/I6zknmEvgPTi5N59C1IQqh0W/6
8uMrHOdELz9I5Fd+zGTJ8iyh/wrecMiIx+HOsBTYv/FYbMVnQUshUBOiD70geUb5
uSeHyxl/P7VK/0phbxOznU4oDot2fHPmZRK3q+K67J9L16q7pEou1AJAw8E7ed5C
Ywf+y2tdxsuqChQK/OA6uuqW6rXjZPuCoG5Bn6YIEuU769LsHcY=
=1PBR
-----END PGP SIGNATURE-----

3
Python-3.10.16.tar.xz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bfb249609990220491a1b92850a07135ed0831e41738cf681d63cf01b2a8fbd1
size 19610392

View File

@ -0,0 +1 @@
{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICzDCCAlKgAwIBAgIUH4wr+RBSLHxmoLeVWQFWtLrOickwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjQxMjAzMTgzMzQ0WhcNMjQxMjAzMTg0MzQ0WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDu7neWfjmWCoWs4toOwMe5ZS5m/Qod/IAYGdai04Qjx+fJ2JKIML8OXa376wmCRg+1mE5N75M5g55sjeH6AW5KOCAXEwggFtMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUVxcoODLOP6ce+ffWUlBZ8dQpAtAwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wIgYDVR0RAQH/BBgwFoEUcGFibG9nc2FsQHB5dGhvbi5vcmcwKQYKKwYBBAGDvzABAQQbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMCsGCisGAQQBg78wAQgEHQwbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMIGJBgorBgEEAdZ5AgQCBHsEeQB3AHUA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGTjcy6WQAABAMARjBEAiAWKkpOltF6fngTPFPiPrjo6Mnx7DvjTjhy+I9C8a1E8AIgDFHJXkaNO/cRHZCEycDJfdcJrMlDEI+iTAc9GbhJreMwCgYIKoZIzj0EAwMDaAAwZQIwRlcLZ+KTrMXkSOqoeZkRtIMzrMhiRvjoMfcYt7d3zX+t+fDtaywsYIu0WSWNtwLuAjEAk1LM0s1c13zn/l9B9I8YMDJxCiUY2ed5AK523TIy75cmH+IYO7XODOD86YSkytvS"}, "tlogEntries": [{"logIndex": "153123526", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1733250825", "inclusionPromise": {"signedEntryTimestamp": "MEUCIBb+3OGEfIJgweBH+795X/kmenmW5L6lzTaW5mU9DN++AiEAni2MKnETeAsGhc8u0W/Y5AuhYKd14TdRvoUw/bWhzjs="}, "inclusionProof": {"logIndex": "31219264", "rootHash": "EEDRbQekcBvIu2A3f37wAtzpj3Tu+lPYLi9AUyS4FBY=", "treeSize": "31219265", "hashes": ["jy1RZw1zMvGOhV5pYK21mUnw/3hfyXoogDNhzfMT8uA=", "t7CZ1TCAQBidKeIL1f3M7Y3VwBYB2DQeG1Sp8X8Mepc=", "LIvgEWJ5UP1rLp6WPJ2TzjrHAa5MpLpXOdj/yoZvLcM=", "XjayhjKU3shP7q7lhmhKDv3Vpi4gJgAPCu0KlEzc9Qo=", "go1dmexQYS5etu69upRRX7IFvuA0rIcT9aYjMstmPIU=", "AYwr74Bm2w383UnS7DdbZUUAhusq28JoxKpWrQ7OvGQ=", "u+yWmGIR6sAH32wiSy22mz1Yf+jfPdBTjFbyRISuTZw=", "3eFC7Gp4fWecybDOAw9uUTrM1xB7YRYRAGsfYkiQbV8=", "1uKk2qjOliHMiTk906jrchP8mXWsRG8apaU1sa0lfh0=", "oOecFfN3YqDOkbijS/ej1WF5Da/Gt/AZNhbwE9uoOE8=", "4lUF0YOu9XkIDXKXA0wMSzd6VeDY3TZAgmoOeWmS2+Y=", "gf+9m552B3PnkWnO0o4KdVvjcT3WVHLrCbf1DoVYKFw="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n31219265\nEEDRbQekcBvIu2A3f37wAtzpj3Tu+lPYLi9AUyS4FBY=\n\n\u2014 rekor.sigstore.dev wNI9ajBFAiAnUUia2onArhzOpQclqAm9wBFu32/qoYagpd3PkWeELgIhAPUWvc2y6UP8V2I/ABP9HtsQi208X3nuSI8xunycnmZl\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJiZmIyNDk2MDk5OTAyMjA0OTFhMWI5Mjg1MGEwNzEzNWVkMDgzMWU0MTczOGNmNjgxZDYzY2YwMWIyYThmYmQxIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUQyYW4xbTUvSWl4clZsYVlpcUMxQmpuamc3eG55MTBxVWw5WHhIM2hJSkNRSWhBS1l4YzRNeTNYTndscEdEU25QTTBjU1gxM3ljMGNnN3BTVVZCS2RrOHZMaiIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjZSRU5EUVd4TFowRjNTVUpCWjBsVlNEUjNjaXRTUWxOTVNIaHRiMHhsVmxkUlJsZDBUSEpQYVdOcmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFJlRTFxUVhwTlZHZDZUWHBSTUZkb1kwNU5hbEY0VFdwQmVrMVVaekJOZWxFd1YycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZFZFRkdVpWZG1hbTFYUTI5WGN6UjBiMDkzVFdVMVdsTTFiUzlSYjJRdlNVRlpSMlFLWVdrd05GRnFlQ3RtU2pKS1MwbE5URGhQV0dFek56WjNiVU5TWnlzeGJVVTFUamMxVFRWbk5UVnphbVZJTmtGWE5VdFBRMEZZUlhkblowWjBUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZXZUdOdkNrOUVURTlRTm1ObEsyWm1WMVZzUWxvNFpGRndRWFJCZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBsbldVUldVakJTUVZGSUwwSkNaM2RHYjBWVlkwZEdhV0pIT1c1ak1rWnpVVWhDTldSSGFIWmlhVFYyWTIxamQwdFJXVXRMZDFsQ1FrRkhSQXAyZWtGQ1FWRlJZbUZJVWpCalNFMDJUSGs1YUZreVRuWmtWelV3WTNrMWJtSXlPVzVpUjFWMVdUSTVkRTFEYzBkRGFYTkhRVkZSUW1jM09IZEJVV2RGQ2toUmQySmhTRkl3WTBoTk5reDVPV2haTWs1MlpGYzFNR041Tlc1aU1qbHVZa2RWZFZreU9YUk5TVWRLUW1kdmNrSm5SVVZCWkZvMVFXZFJRMEpJYzBVS1pWRkNNMEZJVlVFelZEQjNZWE5pU0VWVVNtcEhValJqYlZkak0wRnhTa3RZY21wbFVFc3pMMmcwY0hsblF6aHdOMjgwUVVGQlIxUnFZM2syVjFGQlFRcENRVTFCVW1wQ1JVRnBRVmRMYTNCUGJIUkdObVp1WjFSUVJsQnBVSEpxYnpaTmJuZzNSSFpxVkdwb2VTdEpPVU00WVRGRk9FRkpaMFJHU0VwWWEyRk9Dazh2WTFKSVdrTkZlV05FU21aa1kwcHlUV3hFUlVrcmFWUkJZemxIWW1oS2NtVk5kME5uV1VsTGIxcEplbW93UlVGM1RVUmhRVUYzV2xGSmQxSnNZMHdLV2l0TFZISk5XR3RUVDNGdlpWcHJVblJKVFhweVRXaHBVblpxYjAxbVkxbDBOMlF6ZWxncmRDdG1SSFJoZVhkeldVbDFNRmRUVjA1MGQweDFRV3BGUVFwck1VeE5NSE14WXpFemVtNHZiRGxDT1VrNFdVMUVTbmhEYVZWWk1tVmtOVUZMTlRJelZFbDVOelZqYlVnclNWbFBOMWhQUkU5RU9EWlpVMnQ1ZEhaVENpMHRMUzB0UlU1RUlFTkZVbFJKUmtsRFFWUkZMUzB0TFMwSyJ9fX19"}]}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "v7JJYJmQIgSRobkoUKBxNe0IMeQXOM9oHWPPAbKo+9E="}, "signature": "MEYCIQD2an1m5/IixrVlaYiqC1Bjnjg7xny10qUl9XxH3hIJCQIhAKYxc4My3XNwlpGDSnPM0cSX13yc0cg7pSUVBKdk8vLj"}}

BIN
bluez-devel-vendor.tar.xz (Stored with Git LFS)

Binary file not shown.

View File

@ -0,0 +1,37 @@
From ac2b8869724d7a57d9b5efbdce2f20423214e8bb Mon Sep 17 00:00:00 2001
From: "Bernhard M. Wiedemann" <bwiedemann@suse.de>
Date: Tue, 16 Jul 2024 21:39:33 +0200
Subject: [PATCH] Allow to override build date with SOURCE_DATE_EPOCH
to make builds reproducible.
See https://reproducible-builds.org/ for why this is good
and https://reproducible-builds.org/specs/source-date-epoch/
for the definition of this variable.
---
Doc/conf.py | 3 ++-
Doc/library/functions.rst | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
--- a/Doc/conf.py
+++ b/Doc/conf.py
@@ -89,7 +89,8 @@ html_short_title = '%s Documentation' %
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
-html_last_updated_fmt = '%b %d, %Y'
+html_time = int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))
+html_last_updated_fmt = time.strftime('%b %d, %Y (%H:%M UTC)', time.gmtime(html_time))
# Path to find HTML templates.
templates_path = ['tools/templates']
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -1320,7 +1320,7 @@ are always available. They are listed h
(where :func:`open` is declared), :mod:`os`, :mod:`os.path`, :mod:`tempfile`,
and :mod:`shutil`.
- .. audit-event:: open file,mode,flags open
+ .. audit-event:: open path,mode,flags open
The ``mode`` and ``flags`` arguments may have been modified or inferred from
the original call.

View File

@ -29,7 +29,7 @@
Create a Python.framework rather than a traditional Unix install. Optional
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -3731,7 +3731,7 @@ C API
@@ -3810,7 +3810,7 @@ C API
-----
- bpo-43795: The list in :ref:`stable-abi-list` now shows the public name

View File

@ -0,0 +1,35 @@
From 1b3f6523a5c83323cdc44031b33a1c062e5dc698 Mon Sep 17 00:00:00 2001
From: Xi Ruoyao <xry111@xry111.site>
Date: Fri, 7 Jun 2024 23:51:32 +0800
Subject: [PATCH] gh-120226: Fix
test_sendfile_close_peer_in_the_middle_of_receiving on Linux >= 6.10
(GH-120227)
The worst case is that the kernel buffers 17 pages with a page size of 64k.
(cherry picked from commit a7584245661102a5768c643fbd7db8395fd3c90e)
Co-authored-by: Xi Ruoyao <xry111@xry111.site>
---
Lib/test/test_asyncio/test_sendfile.py | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
--- a/Lib/test/test_asyncio/test_sendfile.py
+++ b/Lib/test/test_asyncio/test_sendfile.py
@@ -93,13 +93,10 @@ class MyProto(asyncio.Protocol):
class SendfileBase:
- # 256 KiB plus small unaligned to buffer chunk
- # Newer versions of Windows seems to have increased its internal
- # buffer and tries to send as much of the data as it can as it
- # has some form of buffering for this which is less than 256KiB
- # on newer server versions and Windows 11.
- # So DATA should be larger than 256 KiB to make this test reliable.
- DATA = b"x" * (1024 * 256 + 1)
+ # Linux >= 6.10 seems buffering up to 17 pages of data.
+ # So DATA should be large enough to make this test reliable even with a
+ # 64 KiB page configuration.
+ DATA = b"x" * (1024 * 17 * 64 + 1)
# Reduce socket buffer size to test on relative small data sets.
BUF_SIZE = 4 * 1024 # 4 KiB

View File

@ -1,3 +1,213 @@
-------------------------------------------------------------------
Mon Mar 10 15:44:31 UTC 2025 - Bernhard Wiedemann <bwiedemann@suse.com>
- Skip PGO with %want_reproducible_builds (bsc#1239210)
-------------------------------------------------------------------
Tue Feb 4 14:43:13 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
- Add CVE-2025-0938-sq-brackets-domain-names.patch which
disallows square brackets ([ and ]) in domain names for parsed
URLs (bsc#1236705, CVE-2025-0938, gh#python/cpython#105704)
-------------------------------------------------------------------
Wed Dec 4 21:23:20 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Update to 3.10.16:
- Tests
- gh-125041: Re-enable skipped tests for zlib on the
s390x architecture: only skip checks of the compressed
bytes, which can be different between zlibs software
implementation and the hardware-accelerated implementation.
- gh-109396: Fix test_socket.test_hmac_sha1() in FIPS
mode. Use a longer key: FIPS mode requires at least of at
least 112 bits. The previous key was only 32 bits. Patch by
Victor Stinner.
- Security
- gh-126623: Upgrade libexpat to 2.6.4
- gh-122792: Changed IPv4-mapped ipaddress.IPv6Address to
consistently use the mapped IPv4 address value for deciding
properties. Properties which have their behavior fixed are
is_multicast, is_reserved, is_link_local, is_global, and
is_unspecified (bsc#1233307, CVE-2024-11168).
- Library
- gh-124651: Properly quote template strings in venv
activation scripts (bsc#1232241, CVE-2024-9287).
- gh-103848: Add checks to ensure that [ bracketed ] hosts
found by urllib.parse.urlsplit() are of IPv6 or IPvFuture
format.
- Removed upstreamed patches:
- CVE-2024-9287-venv_path_unquoted.patch
- CVE-2024-11168-validation-IPv6-addrs.patch
-------------------------------------------------------------------
Thu Nov 14 07:06:20 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Remove -IVendor/ from python-config boo#1231795
- Apply sphinx-72.patch only conditionally for non-SLE-15 builds.
-------------------------------------------------------------------
Wed Nov 13 13:25:01 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Add CVE-2024-11168-validation-IPv6-addrs.patch
fixing bsc#1233307 (CVE-2024-11168,
gh#python/cpython#103848): Improper validation of IPv6 and
IPvFuture addresses.
-------------------------------------------------------------------
Mon Nov 4 21:49:20 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Update sphinx-72.patch to include renaming :noindex: option to
:no-index: in Sphinx 7.2 (bsc#1232750).
- While renaming drop fix-sphinx-72.patch.
-------------------------------------------------------------------
Fri Nov 1 21:38:45 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Update CVE-2024-9287-venv_path_unquoted.patch according to the
upstream PR gh#python/cpython!126301.
-------------------------------------------------------------------
Thu Oct 24 16:09:00 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Add CVE-2024-9287-venv_path_unquoted.patch to properly quote
path names provided when creating a virtual environment
(bsc#1232241, CVE-2024-9287)
-------------------------------------------------------------------
Wed Oct 2 16:18:29 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Drop .pyc files from docdir for reproducible builds
(bsc#1230906).
-------------------------------------------------------------------
Mon Sep 9 13:41:07 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Update to 3.10.15:
- Tests
- gh-112769: The tests now correctly compare zlib version
when :const:`zlib.ZLIB_RUNTIME_VERSION` contains
non-integer suffixes. For example zlib-ng defines the
version as ``1.3.0.zlib-ng``.
- gh-117187: Fix XML tests for vanilla Expat <2.6.0.
- gh-100454: Fix SSL tests CI for OpenSSL 3.1+
- Security
- gh-123678: Upgrade libexpat to 2.6.3
- gh-121957: Fixed missing audit events around interactive
use of Python, now also properly firing for ``python -i``,
as well as for ``python -m asyncio``. The event in question
is ``cpython.run_stdin``.
- gh-122133: Authenticate the socket connection for the
``socket.socketpair()`` fallback on platforms where
``AF_UNIX`` is not available like Windows. Patch by
Gregory P. Smith <greg@krypto.org> and Seth Larson
<seth@python.org>. Reported by Ellie <el@horse64.org>
- gh-121285: Remove backtracking from tarfile header
parsing for ``hdrcharset``, PAX, and GNU sparse headers
(bsc#1230227, CVE-2024-6232).
- gh-118486: :func:`os.mkdir` on Windows now accepts
*mode* of ``0o700`` to restrict the new directory to
the current user. This fixes CVE-2024-4030 affecting
:func:`tempfile.mkdtemp` in scenarios where the base
temporary directory is more permissive than the default.
- gh-116741: Update bundled libexpat to 2.6.2
- Library
- gh-123693: Use platform-agnostic behavior when computing
``zipfile.Path.name``.
- gh-123270: Applied a more surgical fix for malformed
payloads in :class:`zipfile.Path` causing infinite loops
(gh-122905) without breaking contents using legitimate
characters (bsc#1229704, CVE-2024-8088).
- gh-123067: Fix quadratic complexity in parsing ``"``-quoted
cookie values with backslashes by :mod:`http.cookies`
(bsc#1229596, CVE-2024-7592).
- gh-122905: :class:`zipfile.Path` objects now sanitize names
from the zipfile.
- gh-121650: :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.; CVE-2024-6923, bsc#1228780).
- gh-113171: Fixed various false positives and false negatives in
* :attr:`ipaddress.IPv4Address.is_private` (see these docs for details)
* :attr:`ipaddress.IPv4Address.is_global`
* :attr:`ipaddress.IPv6Address.is_private`
* :attr:`ipaddress.IPv6Address.is_global`
Also in the corresponding :class:`ipaddress.IPv4Network` and
:class:`ipaddress.IPv6Network` attributes.
Fixes bsc#1226448 (CVE-2024-4032).
- gh-102988: :func:`email.utils.getaddresses` and
:func:`email.utils.parseaddr` now return ``('', '')`` 2-tuples in more
situations where invalid email addresses are encountered instead of
potentially inaccurate values. Add optional *strict* parameter to these
two functions: use ``strict=False`` to get the old behavior, accept
malformed inputs. ``getattr(email.utils, 'supports_strict_parsing',
False)`` can be use to check if the *strict* paramater is available. Patch
by Thomas Dwyer and Victor Stinner to improve the
CVE-2023-27043 fix (bsc#1210638).
- gh-67693: Fix :func:`urllib.parse.urlunparse` and
:func:`urllib.parse.urlunsplit` for URIs with path starting with multiple
slashes and no authority. Based on patch by Ashwin Ramaswami.
- Core and Builtins
- gh-112275: A deadlock involving ``pystate.c``'s
``HEAD_LOCK`` in ``posixmodule.c`` at fork is now
fixed. Patch by ChuBoning based on previous Python 3.12 fix
by Victor Stinner.
- Remove upstreamed patches:
- CVE-2023-27043-email-parsing-errors.patch
- CVE-2024-4032-private-IP-addrs.patch
- CVE-2024-6923-email-hdr-inject.patch
- CVE-2024-8088-inf-loop-zipfile_Path.patch
- Add sphinx-802.patch to overcome working both with the most
recent and older Sphinx versions.
-------------------------------------------------------------------
Mon Sep 2 09:44:26 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Add gh120226-fix-sendfile-test-kernel-610.patch to avoid
failing test_sendfile_close_peer_in_the_middle_of_receiving
tests on Linux >= 6.10 (GH-120227).
-------------------------------------------------------------------
Wed Aug 28 16:54:34 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Add CVE-2024-8088-inf-loop-zipfile_Path.patch to prevent
malformed payload to cause infinite loops in zipfile.Path
(bsc#1229704, CVE-2024-8088).
-------------------------------------------------------------------
Wed Aug 7 13:40:44 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Add CVE-2024-6923-email-hdr-inject.patch to prevent email
header injection due to unquoted newlines (bsc#1228780,
CVE-2024-6923).
- Adding bso1227999-reproducible-builds.patch fixing bsc#1227999
adding reproducibility patches from gh#python/cpython!121872
and gh#python/cpython!121883.
- %{profileopt} variable is set according to the variable
%{do_profiling} (bsc#1227999)
- Update bluez-devel-vendor.tar.xz
-------------------------------------------------------------------
Mon Jul 22 21:20:55 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Remove %suse_update_desktop_file macro as it is not useful any
more.
-------------------------------------------------------------------
Mon Jul 15 12:14:57 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Stop using %%defattr, it seems to be breaking proper executable
attributes on /usr/bin/ scripts (bsc#1227378).
-------------------------------------------------------------------
Tue Jul 2 10:31:26 UTC 2024 - Daniel Garcia <daniel.garcia@suse.com>
- Update F00251-change-user-install-location.patch to make pip and
modern tools install directly in /usr/local when used by the user.
bsc#1225660
-------------------------------------------------------------------
Tue Jun 25 21:57:40 UTC 2024 - Matej Cepl <mcepl@cepl.eu>

View File

@ -1,7 +1,7 @@
#
# spec file for package python310
#
# Copyright (c) 2024 SUSE LLC
# Copyright (c) 2025 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@ -36,6 +36,12 @@
%bcond_without general
%endif
%if 0%{?do_profiling} && !0%{?want_reproducible_builds}
%bcond_without profileopt
%else
%bcond_with profileopt
%endif
%define python_pkg_name python310
%if "%{python_pkg_name}" == "%{primary_python}"
%define primary_interpreter 1
@ -101,15 +107,14 @@ Obsoletes: python39%{?1:-%{1}}
# pyexpat.cpython-35m-armv7-linux-gnueabihf
# _md5.cpython-38m-x86_64-linux-gnu.so
%define dynlib() %{sitedir}/lib-dynload/%{1}.cpython-%{abi_tag}-%{archname}-%{_os}%{?_gnu}%{?armsuffix}.so
%bcond_without profileopt
Name: %{python_pkg_name}%{psuffix}
Version: 3.10.14
Version: 3.10.16
Release: 0
Summary: Python 3 Interpreter
License: Python-2.0
URL: https://www.python.org/
Source0: https://www.python.org/ftp/python/%{folderversion}/%{tarname}.tar.xz
Source1: https://www.python.org/ftp/python/%{folderversion}/%{tarname}.tar.xz.asc
Source1: https://www.python.org/ftp/python/%{folderversion}/%{tarname}.tar.xz.sigstore
Source2: baselibs.conf
Source3: README.SUSE
Source7: macros.python3
@ -173,11 +178,6 @@ Patch18: bpo-37596-make-set-marshalling.patch
# PATCH-FIX-UPSTREAM gh-78214-marshal_stabilize_FLAG_REF.patch bsc#1213463 mcepl@suse.com
# marshal: Stabilize FLAG_REF usage
Patch19: gh-78214-marshal_stabilize_FLAG_REF.patch
# PATCH-FIX-UPSTREAM CVE-2023-27043-email-parsing-errors.patch bsc#1210638 mcepl@suse.com
# Detect email address parsing errors and return empty tuple to
# indicate the parsing error (old API), from gh#python/cpython!105127
# Patch carries a REGRESSION (gh#python/cpython#106669), so it has been also partially REVERTED
Patch20: CVE-2023-27043-email-parsing-errors.patch
# PATCH-FIX-UPSTREAM fix-sphinx-72.patch gh#python/cpython#97950
# This is a patch with a lot of PR combined to make the doc work with
# sphinx 7.2
@ -191,13 +191,22 @@ Patch20: CVE-2023-27043-email-parsing-errors.patch
# * gh#python/cpython#104163
# * gh#python/cpython#104221
# * gh#python/cpython#107246
Patch21: fix-sphinx-72.patch
Patch21: sphinx-72.patch
# PATCH-FIX-UPSTREAM CVE-2023-52425-libexpat-2.6.0-backport.patch gh#python/cpython#117187 mcepl@suse.com
# Make the test suite work with libexpat < 2.6.0
Patch22: CVE-2023-52425-libexpat-2.6.0-backport.patch
# PATCH-FIX-UPSTREAM CVE-2024-4032-private-IP-addrs.patch bsc#1226448 mcepl@suse.com
# rearrange definition of private v global IP addresses
Patch23: CVE-2024-4032-private-IP-addrs.patch
# PATCH-FIX-UPSTREAM bso1227999-reproducible-builds.patch bsc#1227999 mcepl@suse.com
# reproducibility patches
Patch24: bso1227999-reproducible-builds.patch
# PATCH-FIX-UPSTREAM gh120226-fix-sendfile-test-kernel-610.patch gh#python/cpython#120226 mcepl@suse.com
# Fix test_sendfile_close_peer_in_the_middle_of_receiving on Linux >= 6.10 (GH-120227)
Patch27: gh120226-fix-sendfile-test-kernel-610.patch
# PATCH-FIX-UPSTREAM sphinx-802.patch mcepl@suse.com
# status_iterator method moved between the Sphinx versions
Patch28: sphinx-802.patch
# PATCH-FIX-UPSTREAM CVE-2025-0938-sq-brackets-domain-names.patch bsc#1236705 mcepl@suse.com
# functions `urllib.parse.urlsplit` and `urlparse` accept domain names including square brackets
Patch29: CVE-2025-0938-sq-brackets-domain-names.patch
BuildRequires: autoconf-archive
BuildRequires: automake
BuildRequires: fdupes
@ -243,7 +252,6 @@ BuildRequires: gettext
BuildRequires: readline-devel
BuildRequires: sqlite-devel
BuildRequires: timezone
BuildRequires: update-desktop-files
BuildRequires: pkgconfig(ncurses)
BuildRequires: pkgconfig(tk)
BuildRequires: pkgconfig(x11)
@ -473,10 +481,16 @@ other applications.
%patch -p1 -P 17
%patch -p1 -P 18
%patch -p1 -P 19
%patch -p1 -P 20
%if ! 0%{?sle_version} || 0%{?sle_version} >= 160000
%patch -p1 -P 21
%endif
%patch -p1 -P 22
%patch -p1 -P 23
%patch -p1 -P 24
%patch -p1 -P 27
%patch -p1 -P 28
%patch -p1 -P 29
# drop Autoconf version requirement
sed -i 's/^AC_PREREQ/dnl AC_PREREQ/' configure.ac
@ -708,7 +722,6 @@ done
cp %{SOURCE19} idle%{python_version}.desktop
sed -i -e 's:idle3:idle%{python_version}:g' idle%{python_version}.desktop
install -m 644 -D -t %{buildroot}%{_datadir}/applications idle%{python_version}.desktop
%suse_update_desktop_file idle%{python_version}
cp %{SOURCE20} idle%{python_version}.appdata.xml
sed -i -e 's:idle3.desktop:idle%{python_version}.desktop:g' idle%{python_version}.appdata.xml
@ -786,6 +799,9 @@ install -m 755 -D Tools/gdb/libpython.py %{buildroot}%{_datadir}/gdb/auto-load/%
# install devel files to /config
#cp Makefile Makefile.pre.in Makefile.pre $RPM_BUILD_ROOT%{sitedir}/config-%{python_abi}/
# Remove -IVendor/ from python-config boo#1231795
sed -i 's/-IVendor\///' %{buildroot}%{_bindir}/python%{python_abi}-config
# RPM macros
%if %{primary_interpreter}
mkdir -p %{buildroot}%{_rpmconfigdir}/macros.d/
@ -814,27 +830,28 @@ LD_LIBRARY_PATH=. ./python -O -c "from py_compile import compile; compile('$FAIL
echo %{sitedir}/_import_failed > %{buildroot}/%{sitedir}/site-packages/zzzz-import-failed-hooks.pth
%endif
# For the purposes of reproducibility, it is necessary to eliminate any *.pyc files inside documentation dirs
if [ -d %{buildroot}%{_defaultdocdir} ] ; then
find %{buildroot}%{_defaultdocdir} -type f -name \*.pyc -ls -exec rm -vf '{}' \;
fi
%if %{with general}
%files -n %{python_pkg_name}-tk
%defattr(644, root, root, 755)
%{sitedir}/tkinter
%exclude %{sitedir}/tkinter/test
%{dynlib _tkinter}
%files -n %{python_pkg_name}-curses
%defattr(644, root, root, 755)
%{sitedir}/curses
%{dynlib _curses}
%{dynlib _curses_panel}
%files -n %{python_pkg_name}-dbm
%defattr(644, root, root, 755)
%{sitedir}/dbm
%{dynlib _dbm}
%{dynlib _gdbm}
%files -n %{python_pkg_name}
%defattr(644, root, root, 755)
%dir %{sitedir}
%dir %{sitedir}/lib-dynload
%{sitedir}/sqlite3
@ -846,7 +863,6 @@ echo %{sitedir}/_import_failed > %{buildroot}/%{sitedir}/site-packages/zzzz-impo
%endif
%files -n %{python_pkg_name}-idle
%defattr(644, root, root, 755)
%{sitedir}/idlelib
%dir %{_sysconfdir}/idle%{python_version}
%config %{_sysconfdir}/idle%{python_version}/*
@ -884,11 +900,9 @@ echo %{sitedir}/_import_failed > %{buildroot}/%{sitedir}/site-packages/zzzz-impo
%postun -n libpython%{so_version} -p /sbin/ldconfig
%files -n libpython%{so_version}
%defattr(644, root,root)
%{_libdir}/libpython%{python_abi}.so.%{so_major}.%{so_minor}
%files -n %{python_pkg_name}-tools
%defattr(644, root, root, 755)
%{sitedir}/turtledemo
%if %{primary_interpreter}
%{_bindir}/2to3
@ -897,7 +911,6 @@ echo %{sitedir}/_import_failed > %{buildroot}/%{sitedir}/site-packages/zzzz-impo
%doc %{_docdir}/%{name}/Tools
%files -n %{python_pkg_name}-devel
%defattr(644, root, root, 755)
%{_libdir}/libpython%{python_abi}.so
%if %{primary_interpreter}
%{_libdir}/libpython3.so
@ -905,7 +918,6 @@ echo %{sitedir}/_import_failed > %{buildroot}/%{sitedir}/site-packages/zzzz-impo
%{_libdir}/pkgconfig/*
%{_includedir}/python%{python_abi}
%{sitedir}/config-%{python_abi}-*
%defattr(755, root, root)
%{_bindir}/python%{python_abi}-config
%if %{primary_interpreter}
%{_bindir}/python3-config
@ -918,7 +930,6 @@ echo %{sitedir}/_import_failed > %{buildroot}/%{sitedir}/site-packages/zzzz-impo
%{_datadir}/gdb/auto-load/%{_libdir}/libpython%{python_abi}.so.%{so_major}.%{so_minor}-gdb.py
%files -n %{python_pkg_name}-testsuite
%defattr(644, root, root, 755)
%{sitedir}/test
%{sitedir}/*/test
%{sitedir}/*/tests
@ -935,7 +946,6 @@ echo %{sitedir}/_import_failed > %{buildroot}/%{sitedir}/site-packages/zzzz-impo
%dir %{sitedir}/tkinter
%files -n %{python_pkg_name}-base
%defattr(644, root, root, 755)
# docs
%dir %{_docdir}/%{name}
%doc %{_docdir}/%{name}/README.rst

View File

@ -1,76 +1,77 @@
---
Doc/c-api/bytearray.rst | 2
Doc/c-api/bytes.rst | 2
Doc/c-api/capsule.rst | 2
Doc/c-api/complex.rst | 2
Doc/c-api/concrete.rst | 6 -
Doc/c-api/dict.rst | 4
Doc/c-api/exceptions.rst | 6 -
Doc/c-api/file.rst | 2
Doc/c-api/float.rst | 2
Doc/c-api/function.rst | 2
Doc/c-api/import.rst | 4
Doc/c-api/init.rst | 14 +--
Doc/c-api/intro.rst | 8 -
Doc/c-api/list.rst | 6 -
Doc/c-api/long.rst | 4
Doc/c-api/mapping.rst | 2
Doc/c-api/memoryview.rst | 2
Doc/c-api/method.rst | 4
Doc/c-api/module.rst | 2
Doc/c-api/none.rst | 2
Doc/c-api/number.rst | 12 +-
Doc/c-api/object.rst | 12 +-
Doc/c-api/sequence.rst | 4
Doc/c-api/set.rst | 6 -
Doc/c-api/structures.rst | 4
Doc/c-api/tuple.rst | 2
Doc/c-api/type.rst | 2
Doc/c-api/typeobj.rst | 4
Doc/conf.py | 5 +
Doc/extending/newtypes.rst | 2
Doc/library/_thread.rst | 2
Doc/library/binascii.rst | 6 -
Doc/library/cmath.rst | 2
Doc/library/copy.rst | 2
Doc/library/copyreg.rst | 4
Doc/library/dis.rst | 2
Doc/library/exceptions.rst | 10 +-
Doc/library/fnmatch.rst | 4
Doc/library/functions.rst | 10 +-
Doc/library/http.client.rst | 2
Doc/library/imp.rst | 2
Doc/library/internet.rst | 2
Doc/library/locale.rst | 4
Doc/library/marshal.rst | 4
Doc/library/os.path.rst | 2
Doc/library/os.rst | 4
Doc/library/pdb.rst | 4
Doc/library/posix.rst | 2
Doc/library/pprint.rst | 4
Doc/library/pwd.rst | 2
Doc/library/pyexpat.rst | 2
Doc/library/runpy.rst | 4
Doc/library/shelve.rst | 6 -
Doc/library/site.rst | 6 -
Doc/library/socket.rst | 4
Doc/library/stdtypes.rst | 146 ++++++++++++++++----------------
Doc/library/sys.rst | 2
Doc/library/traceback.rst | 2
Doc/library/types.rst | 2
Doc/reference/compound_stmts.rst | 90 +++++++++----------
Doc/reference/datamodel.rst | 154 +++++++++++++++++-----------------
Doc/reference/executionmodel.rst | 2
Doc/reference/expressions.rst | 134 ++++++++++++++---------------
Doc/reference/simple_stmts.rst | 74 ++++++++--------
Doc/reference/toplevel_components.rst | 10 +-
Doc/tools/extensions/pyspecific.py | 25 +++++
Doc/tutorial/classes.rst | 2
Doc/tutorial/controlflow.rst | 2
Doc/tutorial/inputoutput.rst | 6 -
Doc/tutorial/modules.rst | 4
Doc/tutorial/stdlib.rst | 2
71 files changed, 457 insertions(+), 427 deletions(-)
Doc/c-api/bytearray.rst | 2
Doc/c-api/bytes.rst | 2
Doc/c-api/capsule.rst | 2
Doc/c-api/complex.rst | 2
Doc/c-api/concrete.rst | 6 -
Doc/c-api/dict.rst | 4
Doc/c-api/exceptions.rst | 6 -
Doc/c-api/file.rst | 2
Doc/c-api/float.rst | 2
Doc/c-api/function.rst | 2
Doc/c-api/import.rst | 4
Doc/c-api/init.rst | 14 +--
Doc/c-api/intro.rst | 8 -
Doc/c-api/list.rst | 6 -
Doc/c-api/long.rst | 4
Doc/c-api/mapping.rst | 2
Doc/c-api/memoryview.rst | 2
Doc/c-api/method.rst | 4
Doc/c-api/module.rst | 2
Doc/c-api/none.rst | 2
Doc/c-api/number.rst | 12 +-
Doc/c-api/object.rst | 12 +-
Doc/c-api/sequence.rst | 4
Doc/c-api/set.rst | 6 -
Doc/c-api/structures.rst | 4
Doc/c-api/tuple.rst | 2
Doc/c-api/type.rst | 2
Doc/c-api/typeobj.rst | 4
Doc/conf.py | 5 +
Doc/extending/newtypes.rst | 2
Doc/library/_thread.rst | 2
Doc/library/binascii.rst | 6 -
Doc/library/cmath.rst | 2
Doc/library/copy.rst | 2
Doc/library/copyreg.rst | 4
Doc/library/dis.rst | 2
Doc/library/email.compat32-message.rst | 1
Doc/library/exceptions.rst | 10 +-
Doc/library/fnmatch.rst | 4
Doc/library/functions.rst | 10 +-
Doc/library/http.client.rst | 2
Doc/library/imp.rst | 2
Doc/library/internet.rst | 2
Doc/library/locale.rst | 4
Doc/library/marshal.rst | 4
Doc/library/os.path.rst | 2
Doc/library/os.rst | 4
Doc/library/pdb.rst | 4
Doc/library/posix.rst | 2
Doc/library/pprint.rst | 4
Doc/library/pwd.rst | 2
Doc/library/pyexpat.rst | 2
Doc/library/runpy.rst | 4
Doc/library/shelve.rst | 6 -
Doc/library/site.rst | 6 -
Doc/library/socket.rst | 4
Doc/library/stdtypes.rst | 146 +++++++++++++++----------------
Doc/library/sys.rst | 2
Doc/library/traceback.rst | 2
Doc/library/types.rst | 2
Doc/reference/compound_stmts.rst | 90 +++++++++----------
Doc/reference/datamodel.rst | 154 ++++++++++++++++-----------------
Doc/reference/executionmodel.rst | 2
Doc/reference/expressions.rst | 134 ++++++++++++++--------------
Doc/reference/simple_stmts.rst | 74 +++++++--------
Doc/reference/toplevel_components.rst | 10 +-
Doc/tools/extensions/pyspecific.py | 25 +++++
Doc/tutorial/classes.rst | 2
Doc/tutorial/controlflow.rst | 2
Doc/tutorial/inputoutput.rst | 6 -
Doc/tutorial/modules.rst | 4
Doc/tutorial/stdlib.rst | 2
72 files changed, 458 insertions(+), 427 deletions(-)
--- a/Doc/c-api/bytearray.rst
+++ b/Doc/c-api/bytearray.rst
@ -727,6 +728,16 @@
Pushes a slice object on the stack. *argc* must be 2 or 3. If it is 2,
``slice(TOS1, TOS)`` is pushed; if it is 3, ``slice(TOS2, TOS1, TOS)`` is
--- a/Doc/library/email.compat32-message.rst
+++ b/Doc/library/email.compat32-message.rst
@@ -7,6 +7,7 @@
:synopsis: The base class representing email messages in a fashion
backward compatible with Python 3.2
:noindex:
+ :no-index:
The :class:`Message` class is very similar to the
--- a/Doc/library/exceptions.rst
+++ b/Doc/library/exceptions.rst
@@ -4,8 +4,8 @@ Built-in Exceptions
@ -915,7 +926,7 @@
Open a new pseudo-terminal pair. Return a pair of file descriptors
``(master, slave)`` for the pty and the tty, respectively. The new file
@@ -2637,7 +2637,7 @@ features:
@@ -2644,7 +2644,7 @@ features:
possible and call :func:`lstat` on the result. This does not apply to
dangling symlinks or junction points, which will raise the usual exceptions.

21
sphinx-802.patch Normal file
View File

@ -0,0 +1,21 @@
---
Doc/tools/extensions/pyspecific.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/Doc/tools/extensions/pyspecific.py
+++ b/Doc/tools/extensions/pyspecific.py
@@ -27,7 +27,13 @@ try:
except ImportError:
from sphinx.environment import NoUri
from sphinx.locale import _ as sphinx_gettext
-from sphinx.util import status_iterator, logging
+try:
+ from sphinx.util.display import status_iterator
+except ImportError:
+ # This method was moved into sphinx.util.display in Sphinx 6.1.0. Before
+ # that it resided in sphinx.util.
+ from sphinx.util import status_iterator
+from sphinx.util import logging
from sphinx.util.nodes import split_explicit_title
from sphinx.writers.text import TextWriter, TextTranslator
from sphinx.writers.latex import LaTeXTranslator