Sync from SUSE:ALP:Source:Standard:1.0 python311 revision 55e37eb2b84ad153e90618a704f31d01

This commit is contained in:
2026-04-28 15:56:40 +02:00
parent be3c367e84
commit 12f9528bf9
3 changed files with 239 additions and 0 deletions
+7
View File
@@ -1,3 +1,10 @@
-------------------------------------------------------------------
Wed Apr 15 18:00:50 UTC 2026 - Matej Cepl <mcepl@cepl.eu>
- Add CVE-2026-3446-base64-padding.patch preventing ignoring
excess Base64 data after the first padded quad (bsc#1261970,
CVE-2026-3446, gh#python/cpython#145264).
-------------------------------------------------------------------
Thu Apr 2 13:55:57 UTC 2026 - Matej Cepl <mcepl@cepl.eu>
+3
View File
@@ -215,6 +215,9 @@ Patch41: CVE-2026-4519-webbrowser-open-dashes.patch
# PATCH-FIX-UPSTREAM CVE-2026-3479-pkgutil_get_data.patch bsc#1259989 mcepl@suse.com
# pkgutil.get_data() reject invalid resource arguments
Patch42: CVE-2026-3479-pkgutil_get_data.patch
# PATCH-FIX-UPSTREAM CVE-2026-3446-base64-padding.patch bsc#1261970 mcepl@suse.com
# Do not ignore excess Base64 data after the first padded quad
Patch43: CVE-2026-3446-base64-padding.patch
### END OF PATCHES
BuildRequires: autoconf-archive
BuildRequires: automake
+229
View File
@@ -0,0 +1,229 @@
From bd4ab523ba664863d40470cc718c566158adfa31 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka <storchaka@gmail.com>
Date: Tue, 24 Mar 2026 01:20:26 +0200
Subject: [PATCH] [3.14] gh-145264: Do not ignore excess Base64 data after the
first padded quad (GH-145267) (GH-146326)
Base64 decoder (see binascii.a2b_base64(), base64.b64decode(), etc)
no longer ignores excess data after the first padded quad in non-strict
(default) mode. Instead, in conformance with RFC 4648, it ignores the
pad character, "=", if it is present before the end of the encoded data.
(cherry picked from commit 4561f6418a691b3e89aef0901f53fe0dfb7f7c0e)
(cherry picked from commit e31c55121620189a0d1a07b689762d8ca9c1b7fa)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
---
Lib/test/test_binascii.py | 33 +++
Misc/NEWS.d/next/Library/2026-02-26-20-13-16.gh-issue-145264.4pggX_.rst | 4
Modules/binascii.c | 90 +++++-----
3 files changed, 78 insertions(+), 49 deletions(-)
create mode 100644 Misc/NEWS.d/next/Library/2026-02-26-20-13-16.gh-issue-145264.4pggX_.rst
Index: Python-3.11.15/Lib/test/test_binascii.py
===================================================================
--- Python-3.11.15.orig/Lib/test/test_binascii.py 2026-04-16 01:25:00.019387400 +0200
+++ Python-3.11.15/Lib/test/test_binascii.py 2026-04-16 01:37:02.691981027 +0200
@@ -132,13 +132,20 @@
def assertDiscontinuousPadding(data, non_strict_mode_expected_result: bytes):
_assertRegexTemplate(r'(?i)Discontinuous padding', data, non_strict_mode_expected_result)
+ def assertExcessPadding(data, non_strict_mode_expected_result: bytes):
+ _assertRegexTemplate(r'(?i)Excess padding', data, non_strict_mode_expected_result)
+
# Test excess data exceptions
- assertExcessData(b'ab==a', b'i')
- assertExcessData(b'ab===', b'i')
- assertExcessData(b'ab==:', b'i')
- assertExcessData(b'abc=a', b'i\xb7')
- assertExcessData(b'abc=:', b'i\xb7')
- assertExcessData(b'ab==\n', b'i')
+ assertExcessPadding(b'ab===', b'i')
+ assertExcessPadding(b'ab====', b'i')
+ assertNonBase64Data(b'ab==:', b'i')
+ assertExcessData(b'abc=a', b'i\xb7\x1a')
+ assertNonBase64Data(b'abc=:', b'i\xb7')
+ assertNonBase64Data(b'ab==\n', b'i')
+ assertExcessPadding(b'abc==', b'i\xb7')
+ assertExcessPadding(b'abc===', b'i\xb7')
+ assertExcessPadding(b'abc====', b'i\xb7')
+ assertExcessPadding(b'abc=====', b'i\xb7')
# Test non-base64 data exceptions
assertNonBase64Data(b'\nab==', b'i')
@@ -153,6 +160,20 @@
assertDiscontinuousPadding(b'ab=c=', b'i\xb7')
assertDiscontinuousPadding(b'ab=ab==', b'i\xb6\x9b')
+ def test_base64_excess_data(self):
+ # Test excess data exceptions
+ def assertExcessData(data, expected):
+ assert_regex = r'(?i)Excess data'
+ data = self.type2test(data)
+ with self.assertRaisesRegex(binascii.Error, assert_regex):
+ binascii.a2b_base64(data, strict_mode=True)
+ self.assertEqual(binascii.a2b_base64(data, strict_mode=False),
+ expected)
+ self.assertEqual(binascii.a2b_base64(data), expected)
+
+ assertExcessData(b'ab==c=', b'i\xb7')
+ assertExcessData(b'ab==cd', b'i\xb7\x1d')
+ assertExcessData(b'abc=d', b'i\xb7\x1d')
def test_base64errors(self):
# Test base64 with invalid padding
Index: Python-3.11.15/Misc/NEWS.d/next/Library/2026-02-26-20-13-16.gh-issue-145264.4pggX_.rst
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ Python-3.11.15/Misc/NEWS.d/next/Library/2026-02-26-20-13-16.gh-issue-145264.4pggX_.rst 2026-04-16 01:25:07.716277511 +0200
@@ -0,0 +1,4 @@
+Base64 decoder (see :func:`binascii.a2b_base64`, :func:`base64.b64decode`, etc) no
+longer ignores excess data after the first padded quad in non-strict
+(default) mode. Instead, in conformance with :rfc:`4648`, section 3.3, it now ignores
+the pad character, "=", if it is present before the end of the encoded data.
Index: Python-3.11.15/Modules/binascii.c
===================================================================
--- Python-3.11.15.orig/Modules/binascii.c 2026-03-03 01:52:57.000000000 +0100
+++ Python-3.11.15/Modules/binascii.c 2026-04-16 01:33:46.756241326 +0200
@@ -393,7 +393,6 @@
const unsigned char *ascii_data = data->buf;
size_t ascii_len = data->len;
binascii_state *state = NULL;
- char padding_started = 0;
/* Allocate the buffer */
Py_ssize_t bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */
@@ -404,14 +403,6 @@
return NULL;
unsigned char *bin_data_start = bin_data;
- if (strict_mode && ascii_len > 0 && ascii_data[0] == '=') {
- state = get_binascii_state(module);
- if (state) {
- PyErr_SetString(state->Error, "Leading padding not allowed");
- }
- goto error_end;
- }
-
int quad_pos = 0;
unsigned char leftchar = 0;
int pads = 0;
@@ -422,28 +413,34 @@
** the invalid ones.
*/
if (this_ch == BASE64_PAD) {
- padding_started = 1;
-
- if (quad_pos >= 2 && quad_pos + ++pads >= 4) {
- /* A pad sequence means we should not parse more input.
- ** We've already interpreted the data from the quad at this point.
- ** in strict mode, an error should raise if there's excess data after the padding.
- */
- if (strict_mode && i + 1 < ascii_len) {
- state = get_binascii_state(module);
- if (state) {
- PyErr_SetString(state->Error, "Excess data after padding");
- }
- goto error_end;
- }
-
- goto done;
+ pads++;
+ if (quad_pos >= 2 && quad_pos + pads <= 4) {
+ continue;
}
- continue;
+ // See RFC 4648, section-3.3: "specifications MAY ignore the
+ // pad character, "=", treating it as non-alphabet data, if
+ // it is present before the end of the encoded data" and
+ // "the excess pad characters MAY also be ignored."
+ if (!strict_mode) {
+ continue;
+ }
+ if (quad_pos == 1) {
+ /* Set an error below. */
+ break;
+ }
+ state = get_binascii_state(module);
+ if (state) {
+ PyErr_SetString(state->Error,
+ (quad_pos == 0 && i == 0)
+ ? "Leading padding not allowed"
+ : "Excess padding not allowed");
+ }
+ goto error_end;
}
this_ch = table_a2b_base64[this_ch];
if (this_ch >= 64) {
+ // See RFC 4648, section-3.3.
if (strict_mode) {
state = get_binascii_state(module);
if (state) {
@@ -454,11 +451,14 @@
continue;
}
- // Characters that are not '=', in the middle of the padding, are not allowed
- if (strict_mode && padding_started) {
+ // Characters that are not '=', in the middle of the padding, are
+ // not allowed (except when they are). See RFC 4648, section-3.3.
+ if (pads && strict_mode) {
state = get_binascii_state(module);
if (state) {
- PyErr_SetString(state->Error, "Discontinuous padding not allowed");
+ PyErr_SetString(state->Error, (quad_pos + pads == 4)
+ ? "Excess data after padding"
+ : "Discontinuous padding not allowed");
}
goto error_end;
}
@@ -487,31 +487,35 @@
}
}
- if (quad_pos != 0) {
+ if (quad_pos == 1) {
+ /* There is exactly one extra valid, non-padding, base64 character.
+ * * This is an invalid length, as there is no possible input that
+ ** could encoded into such a base64 string.
+ */
state = get_binascii_state(module);
- if (state == NULL) {
- /* error already set, from get_binascii_state */
- } else if (quad_pos == 1) {
- /*
- ** There is exactly one extra valid, non-padding, base64 character.
- ** This is an invalid length, as there is no possible input that
- ** could encoded into such a base64 string.
- */
+ if (state) {
PyErr_Format(state->Error,
"Invalid base64-encoded string: "
"number of data characters (%zd) cannot be 1 more "
"than a multiple of 4",
(bin_data - bin_data_start) / 3 * 4 + 1);
- } else {
+ }
+ goto error_end;
+ }
+
+ if (quad_pos != 0 && quad_pos + pads < 4) {
+ state = get_binascii_state(module);
+ if (state) {
PyErr_SetString(state->Error, "Incorrect padding");
}
- error_end:
- _PyBytesWriter_Dealloc(&writer);
- return NULL;
+ goto error_end;
}
-done:
return _PyBytesWriter_Finish(&writer, bin_data);
+
+error_end:
+ _PyBytesWriter_Dealloc(&writer);
+ return NULL;
}