From 7ccba948f368b39bc6bcd27c8c6430375d630daba60cda1f13d3d9dc28c05900 Mon Sep 17 00:00:00 2001 From: Matej Cepl Date: Tue, 16 Apr 2024 20:26:40 +0000 Subject: [PATCH] - Modify CVE-2023-27043-email-parsing-errors.patch to fix the unicode string handling in email.utils.parseaddr() (bsc#1222537). OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python?expand=0&rev=407 --- CVE-2023-27043-email-parsing-errors.patch | 576 +++++++++++----------- bsc1222537-py2-email-addr-parse.patch | 32 -- python-base.changes | 5 +- python-base.spec | 7 +- python-doc.changes | 5 +- python-doc.spec | 7 +- python.changes | 5 +- python.spec | 7 +- 8 files changed, 302 insertions(+), 342 deletions(-) delete mode 100644 bsc1222537-py2-email-addr-parse.patch diff --git a/CVE-2023-27043-email-parsing-errors.patch b/CVE-2023-27043-email-parsing-errors.patch index 6de152c..40573d0 100644 --- a/CVE-2023-27043-email-parsing-errors.patch +++ b/CVE-2023-27043-email-parsing-errors.patch @@ -1,14 +1,13 @@ --- - Doc/library/email.utils.rst | 19 - - Lib/email/utils.py | 151 +++++++- - Lib/test/test_email/test_email.py | 187 +++++++++- + Doc/library/email.utils.rst | 19 + Lib/email/test/test_email.py | 192 +++++++++- + Lib/email/test/test_email_renamed.py | 50 ++ + Lib/email/utils.py | 155 +++++++- Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst | 8 - 4 files changed, 344 insertions(+), 21 deletions(-) + 5 files changed, 393 insertions(+), 31 deletions(-) -Index: Python-2.7.18/Doc/library/email.utils.rst -=================================================================== ---- Python-2.7.18.orig/Doc/library/email.utils.rst -+++ Python-2.7.18/Doc/library/email.utils.rst +--- a/Doc/library/email.utils.rst ++++ b/Doc/library/email.utils.rst @@ -21,13 +21,18 @@ There are several useful utilities provi begins with angle brackets, they are stripped off. @@ -58,10 +57,284 @@ Index: Python-2.7.18/Doc/library/email.utils.rst .. function:: parsedate(date) -Index: Python-2.7.18/Lib/email/utils.py -=================================================================== ---- Python-2.7.18.orig/Lib/email/utils.py -+++ Python-2.7.18/Lib/email/utils.py +--- a/Lib/email/test/test_email.py ++++ b/Lib/email/test/test_email.py +@@ -1,3 +1,4 @@ ++# -*- coding: utf-8 -*- + # Copyright (C) 2001-2010 Python Software Foundation + # Contact: email-sig@python.org + # email package unit tests +@@ -2414,15 +2415,142 @@ 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 ( ++ ('(', [('<%s>' % bob, alice)]), ++ (')', [('', alice), empty, ('', bob)]), ++ ('<', [('', alice), empty, ('', bob), empty]), ++ ('>', [('', alice), empty, ('', bob)]), ++ ('[', [('', '%s[<%s>]' % (alice, bob))]), ++ (']', [('', alice), empty, ('', bob)]), ++ ('@', [empty, empty, ('', bob)]), ++ (';', [('', alice), empty, ('', bob)]), ++ (':', [('', alice), ('', bob)]), ++ ('.', [('', alice + '.'), ('', bob)]), ++ ('"', [('', alice), ('', '<%s>' % bob)]), ++ ): ++ address = '%s%s<%s>' % (alice, invalid_separator, bob) ++ 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 = '%s,<%s>' % (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" ' ++ 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" , "John Doe" ' ++ 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 Utils.supports_strict_parsing attribute ++ self.assertEqual(Utils.supports_strict_parsing, True) ++ ++ def test_parsing_unicode_str(self): ++ email_in = "Honza Novák " ++ self.assertEqual(Utils.parseaddr("Honza str Novák "), ++ ('Honza str Nov\xc3\xa1k', 'honza@example.com')) ++ self.assertEqual(Utils.parseaddr(u"Honza unicode Novák "), ++ (u'Honza unicode Nov\xe1k', u'honza@example.com')) ++ + def test_getaddresses_nasty(self): +- eq = self.assertEqual +- eq(Utils.getaddresses(['foo: ;']), [('', '')]) +- eq(Utils.getaddresses( +- ['[]*-- =~$']), +- [('', ''), ('', ''), ('', '*--')]) +- eq(Utils.getaddresses( +- ['foo: ;', '"Jason R. Mastaler" ']), +- [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]) ++ for addresses, expected in ( ++ ([u'"Sürname, Firstname" '], ++ [(u'Sürname, Firstname', 'to@example.com')]), ++ ++ (['foo: ;'], ++ [('', '')]), ++ ++ (['foo: ;', '"Jason R. Mastaler" '], ++ [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]), ++ ++ ([r'Pete(A nice \) chap) '], ++ [('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 '], ++ [('John Doe (comment)', 'jdoe@machine.example')]), ++ ++ (['"Mary Smith: Personal Account" '], ++ [('Mary Smith: Personal Account', 'smith@home.example')]), ++ ++ (['Undisclosed recipients:;'], ++ [('', '')]), ++ ++ ([r', "Giant; \"Big\" Box" '], ++ [('', 'boss@nil.test'), ('Giant; "Big" Box', 'bob@example.net')]), ++ ): ++ 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""" +@@ -2430,6 +2558,54 @@ Foo + addrs = Utils.getaddresses(['User ((nested comment)) ']) + eq(addrs[0][1], 'foo@bar.com') + ++ 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" , "John Doe" ', ++ ' , ') ++ check(r'"Jane \"Doe\"." ', ++ ' ') ++ ++ # 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 , John Doe ', ++ 'lone " quote', ++ ): ++ self.assertEqual(Utils._strip_quoted_realnames(addr), addr) ++ ++ def test_check_parenthesis(self): ++ addr = 'alice@example.net' ++ self.assertTrue(Utils._check_parenthesis('%s (Alice)' % addr)) ++ self.assertFalse(Utils._check_parenthesis('%s )Alice(' % addr)) ++ self.assertFalse(Utils._check_parenthesis('%s (Alice))' % addr)) ++ self.assertFalse(Utils._check_parenthesis('%s ((Alice)' % addr)) ++ ++ # Ignore real name between quotes ++ self.assertTrue(Utils._check_parenthesis('")Alice((" %s' % addr)) ++ ++ + def test_make_msgid_collisions(self): + # Test make_msgid uniqueness, even with multiple threads + class MsgidsThread(Thread): +--- a/Lib/email/test/test_email_renamed.py ++++ b/Lib/email/test/test_email_renamed.py +@@ -1,3 +1,4 @@ ++# -*- coding: utf-8 -*- + # Copyright (C) 2001-2007 Python Software Foundation + # Contact: email-sig@python.org + # email package unit tests +@@ -2276,14 +2277,47 @@ Foo + ('Bud Person', 'bperson@dom.ain')]) + + def test_getaddresses_nasty(self): +- eq = self.assertEqual +- eq(utils.getaddresses(['foo: ;']), [('', '')]) +- eq(utils.getaddresses( +- ['[]*-- =~$']), +- [('', ''), ('', ''), ('', '*--')]) +- eq(utils.getaddresses( +- ['foo: ;', '"Jason R. Mastaler" ']), +- [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]) ++ for addresses, expected in ( ++ ([u'"Sürname, Firstname" '], ++ [(u'Sürname, Firstname', 'to@example.com')]), ++ ++ (['foo: ;'], ++ [('', '')]), ++ ++ (['foo: ;', '"Jason R. Mastaler" '], ++ [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]), ++ ++ ([r'Pete(A nice \) chap) '], ++ [('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 '], ++ [('John Doe (comment)', 'jdoe@machine.example')]), ++ ++ (['"Mary Smith: Personal Account" '], ++ [('Mary Smith: Personal Account', 'smith@home.example')]), ++ ++ (['Undisclosed recipients:;'], ++ [('', '')]), ++ ++ ([r', "Giant; \"Big\" Box" '], ++ [('', 'boss@nil.test'), ('Giant; "Big" Box', 'bob@example.net')]), ++ ): ++ 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""" +--- a/Lib/email/utils.py ++++ b/Lib/email/utils.py @@ -100,15 +100,93 @@ def formataddr(pair): return address @@ -190,7 +463,7 @@ Index: Python-2.7.18/Lib/email/utils.py + if isinstance(addr, list): + addr = addr[0] + -+ if not isinstance(addr, str): ++ if not isinstance(addr, basestring): + return ('', '') + + addr = _pre_parse_validation([addr])[0] @@ -242,10 +515,8 @@ Index: Python-2.7.18/Lib/email/utils.py # rfc822.unquote() doesn't properly de-backslash-ify in Python pre-2.3. def unquote(str): """Remove quotes from a string.""" -Index: Python-2.7.18/Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst -=================================================================== --- /dev/null -+++ Python-2.7.18/Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst ++++ 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 @@ -255,276 +526,3 @@ Index: Python-2.7.18/Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-10298 +``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. -Index: Python-2.7.18/Lib/email/test/test_email.py -=================================================================== ---- Python-2.7.18.orig/Lib/email/test/test_email.py -+++ Python-2.7.18/Lib/email/test/test_email.py -@@ -1,3 +1,4 @@ -+# -*- coding: utf-8 -*- - # Copyright (C) 2001-2010 Python Software Foundation - # Contact: email-sig@python.org - # email package unit tests -@@ -2414,15 +2415,135 @@ 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 ( -+ ('(', [('<%s>' % bob, alice)]), -+ (')', [('', alice), empty, ('', bob)]), -+ ('<', [('', alice), empty, ('', bob), empty]), -+ ('>', [('', alice), empty, ('', bob)]), -+ ('[', [('', '%s[<%s>]' % (alice, bob))]), -+ (']', [('', alice), empty, ('', bob)]), -+ ('@', [empty, empty, ('', bob)]), -+ (';', [('', alice), empty, ('', bob)]), -+ (':', [('', alice), ('', bob)]), -+ ('.', [('', alice + '.'), ('', bob)]), -+ ('"', [('', alice), ('', '<%s>' % bob)]), -+ ): -+ address = '%s%s<%s>' % (alice, invalid_separator, bob) -+ 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 = '%s,<%s>' % (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" ' -+ 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" , "John Doe" ' -+ 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 Utils.supports_strict_parsing attribute -+ self.assertEqual(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 R. Mastaler', 'jason@dom.ain')]) -+ for addresses, expected in ( -+ ([u'"Sürname, Firstname" '], -+ [(u'Sürname, Firstname', 'to@example.com')]), -+ -+ (['foo: ;'], -+ [('', '')]), -+ -+ (['foo: ;', '"Jason R. Mastaler" '], -+ [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]), -+ -+ ([r'Pete(A nice \) chap) '], -+ [('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 '], -+ [('John Doe (comment)', 'jdoe@machine.example')]), -+ -+ (['"Mary Smith: Personal Account" '], -+ [('Mary Smith: Personal Account', 'smith@home.example')]), -+ -+ (['Undisclosed recipients:;'], -+ [('', '')]), -+ -+ ([r', "Giant; \"Big\" Box" '], -+ [('', 'boss@nil.test'), ('Giant; "Big" Box', 'bob@example.net')]), -+ ): -+ 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""" -@@ -2430,6 +2551,54 @@ Foo - addrs = Utils.getaddresses(['User ((nested comment)) ']) - eq(addrs[0][1], 'foo@bar.com') - -+ 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" , "John Doe" ', -+ ' , ') -+ check(r'"Jane \"Doe\"." ', -+ ' ') -+ -+ # 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 , John Doe ', -+ 'lone " quote', -+ ): -+ self.assertEqual(Utils._strip_quoted_realnames(addr), addr) -+ -+ def test_check_parenthesis(self): -+ addr = 'alice@example.net' -+ self.assertTrue(Utils._check_parenthesis('%s (Alice)' % addr)) -+ self.assertFalse(Utils._check_parenthesis('%s )Alice(' % addr)) -+ self.assertFalse(Utils._check_parenthesis('%s (Alice))' % addr)) -+ self.assertFalse(Utils._check_parenthesis('%s ((Alice)' % addr)) -+ -+ # Ignore real name between quotes -+ self.assertTrue(Utils._check_parenthesis('")Alice((" %s' % addr)) -+ -+ - def test_make_msgid_collisions(self): - # Test make_msgid uniqueness, even with multiple threads - class MsgidsThread(Thread): -Index: Python-2.7.18/Lib/email/test/test_email_renamed.py -=================================================================== ---- Python-2.7.18.orig/Lib/email/test/test_email_renamed.py -+++ Python-2.7.18/Lib/email/test/test_email_renamed.py -@@ -1,3 +1,4 @@ -+# -*- coding: utf-8 -*- - # Copyright (C) 2001-2007 Python Software Foundation - # Contact: email-sig@python.org - # email package unit tests -@@ -2276,14 +2277,47 @@ Foo - ('Bud Person', 'bperson@dom.ain')]) - - def test_getaddresses_nasty(self): -- eq = self.assertEqual -- eq(utils.getaddresses(['foo: ;']), [('', '')]) -- eq(utils.getaddresses( -- ['[]*-- =~$']), -- [('', ''), ('', ''), ('', '*--')]) -- eq(utils.getaddresses( -- ['foo: ;', '"Jason R. Mastaler" ']), -- [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]) -+ for addresses, expected in ( -+ ([u'"Sürname, Firstname" '], -+ [(u'Sürname, Firstname', 'to@example.com')]), -+ -+ (['foo: ;'], -+ [('', '')]), -+ -+ (['foo: ;', '"Jason R. Mastaler" '], -+ [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]), -+ -+ ([r'Pete(A nice \) chap) '], -+ [('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 '], -+ [('John Doe (comment)', 'jdoe@machine.example')]), -+ -+ (['"Mary Smith: Personal Account" '], -+ [('Mary Smith: Personal Account', 'smith@home.example')]), -+ -+ (['Undisclosed recipients:;'], -+ [('', '')]), -+ -+ ([r', "Giant; \"Big\" Box" '], -+ [('', 'boss@nil.test'), ('Giant; "Big" Box', 'bob@example.net')]), -+ ): -+ 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""" diff --git a/bsc1222537-py2-email-addr-parse.patch b/bsc1222537-py2-email-addr-parse.patch deleted file mode 100644 index a17f7e1..0000000 --- a/bsc1222537-py2-email-addr-parse.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- - Lib/email/test/test_email.py | 7 +++++++ - Lib/email/utils.py | 2 +- - 2 files changed, 8 insertions(+), 1 deletion(-) - ---- a/Lib/email/test/test_email.py -+++ b/Lib/email/test/test_email.py -@@ -2502,6 +2502,13 @@ Foo - # Test Utils.supports_strict_parsing attribute - self.assertEqual(Utils.supports_strict_parsing, True) - -+ def test_parsing_unicode_str(self): -+ email_in = "Honza Novák " -+ self.assertEqual(Utils.parseaddr("Honza str Novák "), -+ ('Honza str Nov\xc3\xa1k', 'honza@example.com')) -+ self.assertEqual(Utils.parseaddr(u"Honza unicode Novák "), -+ (u'Honza unicode Nov\xe1k', u'honza@example.com')) -+ - def test_getaddresses_nasty(self): - for addresses, expected in ( - ([u'"Sürname, Firstname" '], ---- a/Lib/email/utils.py -+++ b/Lib/email/utils.py -@@ -307,7 +307,7 @@ def parseaddr(addr, strict=True): - if isinstance(addr, list): - addr = addr[0] - -- if not isinstance(addr, str): -+ if not isinstance(addr, basestring): - return ('', '') - - addr = _pre_parse_validation([addr])[0] diff --git a/python-base.changes b/python-base.changes index 8a8562c..45656c2 100644 --- a/python-base.changes +++ b/python-base.changes @@ -2,8 +2,9 @@ Tue Apr 16 15:39:24 UTC 2024 - Matej Cepl - Switch on tests again. -- Add bsc1222537-py2-email-addr-parse.patch to fix the unicode - string handling in email.utils.parseaddr() (bsc#1222537). +- Modify CVE-2023-27043-email-parsing-errors.patch to fix the + unicode string handling in email.utils.parseaddr() + (bsc#1222537). ------------------------------------------------------------------- Mon Mar 18 09:54:20 UTC 2024 - Matej Cepl diff --git a/python-base.spec b/python-base.spec index a6519e9..d4d36ba 100644 --- a/python-base.spec +++ b/python-base.spec @@ -154,7 +154,8 @@ Patch75: CVE-2023-24329-blank-URL-bypass.patch Patch76: PygmentsBridge-trime_doctest_flags.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) +# indicate the parsing error (old API), modified for fixing bsc#1222537, +# so that email.utils.parseaddr accepts unicode string Patch77: CVE-2023-27043-email-parsing-errors.patch # PATCH-FIX-UPSTREAM CVE-2022-48565-plistlib-XML-vulns.patch bsc#1214685 mcepl@suse.com # Reject entity declarations in plists @@ -167,9 +168,6 @@ Patch80: CVE-2022-48566-compare_digest-more-constant.patch # PATCH-FIX-UPSTREAM CVE-2022-48560-after-free-heappushpop.patch bsc#1214675 mcepl@suse.com # fix use after free in heapq.heappushpop() Patch81: CVE-2022-48560-after-free-heappushpop.patch -# PATCH-FIX-UPSTREAM bsc1222537-py2-email-addr-parse.patch bsc#1222537 mcepl@suse.com -# email.utils.parseaddr should accept unicode string -Patch82: bsc1222537-py2-email-addr-parse.patch # COMMON-PATCH-END %define python_version %(echo %{tarversion} | head -c 3) BuildRequires: automake @@ -327,7 +325,6 @@ other applications. %patch -P 79 -p1 %patch -P 80 -p1 %patch -P 81 -p1 -%patch -P 82 -p1 # For patch 66 cp -v %{SOURCE66} Lib/test/recursion.tar diff --git a/python-doc.changes b/python-doc.changes index 8a8562c..45656c2 100644 --- a/python-doc.changes +++ b/python-doc.changes @@ -2,8 +2,9 @@ Tue Apr 16 15:39:24 UTC 2024 - Matej Cepl - Switch on tests again. -- Add bsc1222537-py2-email-addr-parse.patch to fix the unicode - string handling in email.utils.parseaddr() (bsc#1222537). +- Modify CVE-2023-27043-email-parsing-errors.patch to fix the + unicode string handling in email.utils.parseaddr() + (bsc#1222537). ------------------------------------------------------------------- Mon Mar 18 09:54:20 UTC 2024 - Matej Cepl diff --git a/python-doc.spec b/python-doc.spec index db492e6..661658f 100644 --- a/python-doc.spec +++ b/python-doc.spec @@ -150,7 +150,8 @@ Patch75: CVE-2023-24329-blank-URL-bypass.patch Patch76: PygmentsBridge-trime_doctest_flags.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) +# indicate the parsing error (old API), modified for fixing bsc#1222537, +# so that email.utils.parseaddr accepts unicode string Patch77: CVE-2023-27043-email-parsing-errors.patch # PATCH-FIX-UPSTREAM CVE-2022-48565-plistlib-XML-vulns.patch bsc#1214685 mcepl@suse.com # Reject entity declarations in plists @@ -163,9 +164,6 @@ Patch80: CVE-2022-48566-compare_digest-more-constant.patch # PATCH-FIX-UPSTREAM CVE-2022-48560-after-free-heappushpop.patch bsc#1214675 mcepl@suse.com # fix use after free in heapq.heappushpop() Patch81: CVE-2022-48560-after-free-heappushpop.patch -# PATCH-FIX-UPSTREAM bsc1222537-py2-email-addr-parse.patch bsc#1222537 mcepl@suse.com -# email.utils.parseaddr should accept unicode string -Patch82: bsc1222537-py2-email-addr-parse.patch # COMMON-PATCH-END Provides: pyth_doc = %{version} Provides: pyth_ps = %{version} @@ -258,7 +256,6 @@ Python, and Macintosh Module Reference in PDF format. %patch -P 79 -p1 %patch -P 80 -p1 %patch -P 81 -p1 -%patch -P 82 -p1 # For patch 66 cp -v %{SOURCE66} Lib/test/recursion.tar diff --git a/python.changes b/python.changes index 8a8562c..45656c2 100644 --- a/python.changes +++ b/python.changes @@ -2,8 +2,9 @@ Tue Apr 16 15:39:24 UTC 2024 - Matej Cepl - Switch on tests again. -- Add bsc1222537-py2-email-addr-parse.patch to fix the unicode - string handling in email.utils.parseaddr() (bsc#1222537). +- Modify CVE-2023-27043-email-parsing-errors.patch to fix the + unicode string handling in email.utils.parseaddr() + (bsc#1222537). ------------------------------------------------------------------- Mon Mar 18 09:54:20 UTC 2024 - Matej Cepl diff --git a/python.spec b/python.spec index 305ff71..30932f8 100644 --- a/python.spec +++ b/python.spec @@ -150,7 +150,8 @@ Patch75: CVE-2023-24329-blank-URL-bypass.patch Patch76: PygmentsBridge-trime_doctest_flags.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) +# indicate the parsing error (old API), modified for fixing bsc#1222537, +# so that email.utils.parseaddr accepts unicode string Patch77: CVE-2023-27043-email-parsing-errors.patch # PATCH-FIX-UPSTREAM CVE-2022-48565-plistlib-XML-vulns.patch bsc#1214685 mcepl@suse.com # Reject entity declarations in plists @@ -163,9 +164,6 @@ Patch80: CVE-2022-48566-compare_digest-more-constant.patch # PATCH-FIX-UPSTREAM CVE-2022-48560-after-free-heappushpop.patch bsc#1214675 mcepl@suse.com # fix use after free in heapq.heappushpop() Patch81: CVE-2022-48560-after-free-heappushpop.patch -# PATCH-FIX-UPSTREAM bsc1222537-py2-email-addr-parse.patch bsc#1222537 mcepl@suse.com -# email.utils.parseaddr should accept unicode string -Patch82: bsc1222537-py2-email-addr-parse.patch # COMMON-PATCH-END BuildRequires: automake BuildRequires: db-devel @@ -378,7 +376,6 @@ that rely on earlier non-verification behavior. %patch -P 79 -p1 %patch -P 80 -p1 %patch -P 81 -p1 -%patch -P 82 -p1 # For patch 66 cp -v %{SOURCE66} Lib/test/recursion.tar