From 52d83e9fa67b7b4cd246f34ecac9689b8cdf266d Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Sun, 31 Jan 2021 18:31:28 +0200 Subject: [PATCH 01/23] Added handling for excess data in binascii.a2b_base64 --- Modules/binascii.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Modules/binascii.c b/Modules/binascii.c index 1f3248b6049b31..d308a161db3ed3 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -466,10 +466,16 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data) */ if (this_ch == BASE64_PAD) { if (quad_pos >= 2 && quad_pos + ++pads >= 4) { - /* A pad sequence means no more input. - ** We've already interpreted the data - ** from the quad at this point. + /* A pad sequence means we should not parse more input. + ** We've already interpreted the data from the quad at this point. + ** An error should raise if there's excess data after the padding. */ + if (i + 1 < ascii_len) { + binascii_state *state = PyModule_GetState(module); + PyErr_SetString(state->Error, "Excess data after padding is not allowed"); + goto error_end; + } + goto done; } continue; @@ -522,6 +528,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data) } else { PyErr_SetString(state->Error, "Incorrect padding"); } + error_end: _PyBytesWriter_Dealloc(&writer); return NULL; } From 557bce8b6bad1387e8f6fc886f9e8fa42c3031bb Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sun, 31 Jan 2021 18:24:55 +0000 Subject: [PATCH 02/23] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst diff --git a/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst b/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst new file mode 100644 index 00000000000000..0b02f6ceeac898 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst @@ -0,0 +1 @@ +Added handling for excess data in binascii.a2b_base64 \ No newline at end of file From 6ed5193a3d302e1200cf729bf5eb88d195c3cd72 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Sat, 13 Mar 2021 14:29:18 +0200 Subject: [PATCH 03/23] Added if-state guard --- Modules/binascii.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/binascii.c b/Modules/binascii.c index d308a161db3ed3..9a04809ec4305b 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -472,7 +472,9 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data) */ if (i + 1 < ascii_len) { binascii_state *state = PyModule_GetState(module); - PyErr_SetString(state->Error, "Excess data after padding is not allowed"); + if (state) { + PyErr_SetString(state->Error, "Excess data after padding is not allowed"); + } goto error_end; } From c7b723f4c776be794d3e7626fad62694434e3bb5 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Wed, 31 Mar 2021 01:10:30 +0300 Subject: [PATCH 04/23] Implemented the strict mode logic Also documented the new argument. --- Modules/binascii.c | 17 +++++++++++++---- Modules/clinic/binascii.c.h | 35 ++++++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/Modules/binascii.c b/Modules/binascii.c index 9a04809ec4305b..25ffe30eb389a6 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -433,12 +433,14 @@ binascii.a2b_base64 data: ascii_buffer / + * + strict_mode: bool(accept={int}) = False Decode a line of base64 data. [clinic start generated code]*/ static PyObject * -binascii_a2b_base64_impl(PyObject *module, Py_buffer *data) +binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) /*[clinic end generated code: output=0628223f19fd3f9b input=5872acf6e1cac243]*/ { assert(data->len >= 0); @@ -468,12 +470,12 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data) 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. - ** An error should raise if there's excess data after the padding. + ** in strict mode, an error should raise if there's excess data after the padding. */ - if (i + 1 < ascii_len) { + if (strict_mode && i + 1 < ascii_len) { binascii_state *state = PyModule_GetState(module); if (state) { - PyErr_SetString(state->Error, "Excess data after padding is not allowed"); + PyErr_SetString(state->Error, "Excess data after padding is not allowed when using strict mode"); } goto error_end; } @@ -485,6 +487,13 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data) this_ch = table_a2b_base64[this_ch]; if (this_ch >= 64) { + if (strict_mode) { + binascii_state *state = PyModule_GetState(module); + if (state) { + PyErr_SetString(state->Error, "Only base64 data is allowed when using strict mode"); + } + goto error_end; + } continue; } pads = 0; diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h index ae1c4574325c56..18e5ae8590a163 100644 --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -87,27 +87,48 @@ binascii_b2a_uu(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj } PyDoc_STRVAR(binascii_a2b_base64__doc__, -"a2b_base64($module, data, /)\n" +"a2b_base64($module, data, /, *, strict_mode=False)\n" "--\n" "\n" -"Decode a line of base64 data."); +"Decode a line of base64 data.\n" +"\n" +" strict_mode\n" +" When set to True, bytes that are not part of the base64 standard are not allowed.\n" +" The same applies to excess data after padding (= / ==)."); #define BINASCII_A2B_BASE64_METHODDEF \ - {"a2b_base64", (PyCFunction)binascii_a2b_base64, METH_O, binascii_a2b_base64__doc__}, + {"a2b_base64", (PyCFunction)(void(*)(void))binascii_a2b_base64, METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base64__doc__}, static PyObject * -binascii_a2b_base64_impl(PyObject *module, Py_buffer *data); +binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode); static PyObject * -binascii_a2b_base64(PyObject *module, PyObject *arg) +binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "strict_mode", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "a2b_base64", 0}; + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; + int strict_mode = 0; - if (!ascii_buffer_converter(arg, &data)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { goto exit; } - return_value = binascii_a2b_base64_impl(module, &data); + if (!ascii_buffer_converter(args[0], &data)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + strict_mode = _PyLong_AsInt(args[1]); + if (strict_mode == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_kwonly: + return_value = binascii_a2b_base64_impl(module, &data, strict_mode); exit: /* Cleanup for data */ From f6283d9787f763ee925c9a97e0731d345379be40 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Wed, 7 Apr 2021 18:20:36 +0300 Subject: [PATCH 05/23] =?UTF-8?q?Trying=20to=20fix=20the=20"Check=20if=20g?= =?UTF-8?q?enerated=20files=20are=20up=20to=20date"=20failure=20Never=20di?= =?UTF-8?q?d=20it=20before=20=F0=9F=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Modules/binascii.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/binascii.c b/Modules/binascii.c index 25ffe30eb389a6..5fb30eb61fa200 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -441,7 +441,7 @@ Decode a line of base64 data. static PyObject * binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) -/*[clinic end generated code: output=0628223f19fd3f9b input=5872acf6e1cac243]*/ +/*[clinic end generated code: output=5409557788d4f975 input=5872acf6e1cac243]*/ { assert(data->len >= 0); From cedbb856cb14e13fe5bfc7581fcb49653e071869 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Wed, 7 Apr 2021 21:57:32 +0300 Subject: [PATCH 06/23] Generated function signatures using clinic (This time did it properly) --- Modules/binascii.c | 6 +++++- Modules/clinic/binascii.c.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Modules/binascii.c b/Modules/binascii.c index 5fb30eb61fa200..fe6f749ba18b31 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -437,11 +437,15 @@ binascii.a2b_base64 strict_mode: bool(accept={int}) = False Decode a line of base64 data. + + strict_mode + When set to True, bytes that are not part of the base64 standard are not allowed. + The same applies to excess data after padding (= / ==). [clinic start generated code]*/ static PyObject * binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) -/*[clinic end generated code: output=5409557788d4f975 input=5872acf6e1cac243]*/ +/*[clinic end generated code: output=5409557788d4f975 input=3a30c4e3528317c6]*/ { assert(data->len >= 0); diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h index 18e5ae8590a163..a9240046a59110 100644 --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -767,4 +767,4 @@ binascii_b2a_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj return return_value; } -/*[clinic end generated code: output=95a0178f30801b89 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0f261ee49971f5ca input=a9049054013a1b77]*/ From 69c96d54e4c1a4992f00cbb0a8f895292b158296 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Mon, 12 Apr 2021 18:21:21 +0300 Subject: [PATCH 07/23] Handle data in the middle of the padding in strict mode --- Modules/binascii.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Modules/binascii.c b/Modules/binascii.c index fe6f749ba18b31..c1c7e77b7c289f 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -451,6 +451,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) const unsigned char *ascii_data = data->buf; size_t ascii_len = data->len; + char padding_started = 0; /* Allocate the buffer */ Py_ssize_t bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */ @@ -471,6 +472,8 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) ** 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. @@ -500,6 +503,15 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) } continue; } + + // Characters that are not '=', in the middle of the padding, are not allowed + if (strict_mode && padding_started) { + binascii_state *state = PyModule_GetState(module); + if (state) { + PyErr_SetString(state->Error, "Malformed padding in strict mode"); + } + goto error_end; + } pads = 0; switch (quad_pos) { From 3718ebd1c0ee0a8ec4b38f8884ea7a04290670a4 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Mon, 12 Apr 2021 19:00:01 +0300 Subject: [PATCH 08/23] Added a test for strict mode --- Lib/test/test_binascii.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index 4d1bf2cce1f1e3..8e161df86c05b1 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -114,6 +114,38 @@ def addnoise(line): # empty strings. TBD: shouldn't it raise an exception instead ? self.assertEqual(binascii.a2b_base64(self.type2test(fillers)), b'') + def test_base64_strict_mode(self): + # Test base64 with strict mode on + def assertExcessData(data): + with self.assertRaisesRegex(binascii.Error, r'(?i)Excess data'): + binascii.a2b_base64(self.type2test(data), strict_mode=True) + + def assertNonBase64Data(data): + with self.assertRaisesRegex(binascii.Error, r'(?i)Only base64 data'): + binascii.a2b_base64(self.type2test(data), strict_mode=True) + + def assertMalformedPadding(data): + with self.assertRaisesRegex(binascii.Error, r'(?i)Malformed padding'): + binascii.a2b_base64(self.type2test(data), strict_mode=True) + + # Test excess data exceptions + assertExcessData(b'ab==a') + assertExcessData(b'ab===') + assertExcessData(b'ab==:') + assertExcessData(b'abc=a') + assertExcessData(b'abc=:') + assertExcessData(b'ab==\n') + + # Test non-base64 data exceptions + assertNonBase64Data(b'ab:(){:|:&};:==') + assertNonBase64Data(b'a\nb==') + assertNonBase64Data(b'a\x00b==') + + # Test malformed padding + assertMalformedPadding(b'ab=c=') + assertMalformedPadding(b'ab=ab==') + + def test_base64errors(self): # Test base64 with invalid padding def assertIncorrectPadding(data): From d0b60e23dd5edaf2efa7a1b10192783381529dd2 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Sat, 10 Jul 2021 11:58:23 +0300 Subject: [PATCH 09/23] Added a test for invalid data as the first character --- Lib/test/test_binascii.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index 8e161df86c05b1..cf26f2ee8bfeb7 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -137,6 +137,7 @@ def assertMalformedPadding(data): assertExcessData(b'ab==\n') # Test non-base64 data exceptions + assertNonBase64Data(b'\nab==') assertNonBase64Data(b'ab:(){:|:&};:==') assertNonBase64Data(b'a\nb==') assertNonBase64Data(b'a\x00b==') From afb95dba830961aceda9070d69eb727405fbdd8d Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Sat, 10 Jul 2021 13:05:25 +0300 Subject: [PATCH 10/23] Disallowed leading padding in strict mode --- Modules/binascii.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/binascii.c b/Modules/binascii.c index c1c7e77b7c289f..a11dcd16196fdc 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -462,6 +462,10 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) return NULL; unsigned char *bin_data_start = bin_data; + if (strict_mode && ascii_len > 0 && ascii_data[0] == '=') { + goto malformed_padding; + } + int quad_pos = 0; unsigned char leftchar = 0; int pads = 0; @@ -506,6 +510,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) // Characters that are not '=', in the middle of the padding, are not allowed if (strict_mode && padding_started) { + malformed_padding: binascii_state *state = PyModule_GetState(module); if (state) { PyErr_SetString(state->Error, "Malformed padding in strict mode"); From 3c5758b63211d2a8a037db018f0632674b179365 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Sat, 10 Jul 2021 13:18:04 +0300 Subject: [PATCH 11/23] Added tests for padding-only input --- Lib/test/test_binascii.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index cf26f2ee8bfeb7..90604037d48bbc 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -143,6 +143,9 @@ def assertMalformedPadding(data): assertNonBase64Data(b'a\x00b==') # Test malformed padding + assertMalformedPadding(b'=') + assertMalformedPadding(b'==') + assertMalformedPadding(b'===') assertMalformedPadding(b'ab=c=') assertMalformedPadding(b'ab=ab==') From 5f8df5b7768e62919db79e772de027be5206b093 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Sat, 10 Jul 2021 16:01:43 +0300 Subject: [PATCH 12/23] Added tests to validate the default behavior. Also, made the tests more generic. --- Lib/test/test_binascii.py | 51 +++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index 90604037d48bbc..8e7afb910630a7 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -116,38 +116,41 @@ def addnoise(line): def test_base64_strict_mode(self): # Test base64 with strict mode on - def assertExcessData(data): - with self.assertRaisesRegex(binascii.Error, r'(?i)Excess data'): - binascii.a2b_base64(self.type2test(data), strict_mode=True) + def _assertRegexTemplate(assert_regex: str, data: bytes, non_strict_mode_expected_result: bytes): + with self.assertRaisesRegex(binascii.Error, assert_regex): + binascii.a2b_base64(self.type2test(data), strict_mode=True) + assert binascii.a2b_base64(self.type2test(data), strict_mode=False) == non_strict_mode_expected_result + assert binascii.a2b_base64(self.type2test(data)) == non_strict_mode_expected_result - def assertNonBase64Data(data): - with self.assertRaisesRegex(binascii.Error, r'(?i)Only base64 data'): - binascii.a2b_base64(self.type2test(data), strict_mode=True) + def assertExcessData(data, non_strict_mode_expected_result: bytes): + _assertRegexTemplate(r'(?i)Excess data', data, non_strict_mode_expected_result) - def assertMalformedPadding(data): - with self.assertRaisesRegex(binascii.Error, r'(?i)Malformed padding'): - binascii.a2b_base64(self.type2test(data), strict_mode=True) + def assertNonBase64Data(data, non_strict_mode_expected_result: bytes): + _assertRegexTemplate(r'(?i)Only base64 data', data, non_strict_mode_expected_result) + + def assertMalformedPadding(data, non_strict_mode_expected_result: bytes): + _assertRegexTemplate(r'(?i)Malformed padding', data, non_strict_mode_expected_result) # Test excess data exceptions - assertExcessData(b'ab==a') - assertExcessData(b'ab===') - assertExcessData(b'ab==:') - assertExcessData(b'abc=a') - assertExcessData(b'abc=:') - assertExcessData(b'ab==\n') + 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') # Test non-base64 data exceptions - assertNonBase64Data(b'\nab==') - assertNonBase64Data(b'ab:(){:|:&};:==') - assertNonBase64Data(b'a\nb==') - assertNonBase64Data(b'a\x00b==') + assertNonBase64Data(b'\nab==', b'i') + assertNonBase64Data(b'ab:(){:|:&};:==', b'i') + assertNonBase64Data(b'a\nb==', b'i') + assertNonBase64Data(b'a\x00b==', b'i') # Test malformed padding - assertMalformedPadding(b'=') - assertMalformedPadding(b'==') - assertMalformedPadding(b'===') - assertMalformedPadding(b'ab=c=') - assertMalformedPadding(b'ab=ab==') + assertMalformedPadding(b'=', b'') + assertMalformedPadding(b'==', b'') + assertMalformedPadding(b'===', b'') + assertMalformedPadding(b'ab=c=', b'i\xb7') + assertMalformedPadding(b'ab=ab==', b'i\xb6\x9b') def test_base64errors(self): From 644dbaf5871237da50aa08444e60a6a9b119dce9 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Sat, 10 Jul 2021 16:12:58 +0300 Subject: [PATCH 13/23] Described the changed of this pull request --- .../next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst b/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst index 0b02f6ceeac898..5eb7f2b1f407bc 100644 --- a/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst +++ b/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst @@ -1 +1,3 @@ -Added handling for excess data in binascii.a2b_base64 \ No newline at end of file +Added a new optional `strict_mode` parameter to binascii.a2b_base64. +When `scrict_mode` is set to `True`, the a2b_base64 function will accept only valid base64 content. +More details about what "valid base64 content" is - can be found in the function's documentation. \ No newline at end of file From 464484cd1e51d7db33a8235dbd3e5fe81fbad0fb Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Sat, 10 Jul 2021 16:18:19 +0300 Subject: [PATCH 14/23] Modified syntax of RST --- .../next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst b/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst index 5eb7f2b1f407bc..19ef510e6a7874 100644 --- a/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst +++ b/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst @@ -1,3 +1,3 @@ -Added a new optional `strict_mode` parameter to binascii.a2b_base64. -When `scrict_mode` is set to `True`, the a2b_base64 function will accept only valid base64 content. -More details about what "valid base64 content" is - can be found in the function's documentation. \ No newline at end of file +| Added a new optional :code:`strict_mode` parameter to `binascii.a2b_base64`. +| When :code:`scrict_mode` is set to :code:`True`, the `a2b_base64` function will accept only valid base64 content. +| More details about what "valid base64 content" is, can be found in the function's documentation. \ No newline at end of file From e1ccf8aed107746bf52c21f3cf632760dd183ce2 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Sat, 10 Jul 2021 21:52:08 +0300 Subject: [PATCH 15/23] Updated the docs to explain the strict_mode parameter --- Doc/library/binascii.rst | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index 2c0c1bce5d7f8f..17337fa7f3d7bf 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -50,11 +50,23 @@ The :mod:`binascii` module defines the following functions: Added the *backtick* parameter. -.. function:: a2b_base64(string) +.. function:: a2b_base64(string, strict_mode=False) Convert a block of base64 data back to binary and return the binary data. More than one line may be passed at a time. + If `strict_mode` is true, only valid base64 data will be converted. Invalid base64 + data will raise :exc:`binascii.Error`. + + Valid base64: + * Conforms to :rfc:`3548`. + * Contains only characters from the base64 alphabet. + * Contains no excess data after padding (including excess padding, newlines, etc.). + * Does not start with a padding. + + .. versionchanged:: 3.11 + Added the *strict_mode* parameter. + .. function:: b2a_base64(data, *, newline=True) From d6a5cbfbc688711f6f53596e1722865455eb7957 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Fri, 16 Jul 2021 19:10:53 +0300 Subject: [PATCH 16/23] Moved declaration of state to the beginning to prevent multiple declaraions under the same scope. This should fix the build errors. --- Modules/binascii.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Modules/binascii.c b/Modules/binascii.c index a11dcd16196fdc..f01bb2b2f0aadb 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -451,6 +451,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) const unsigned char *ascii_data = data->buf; size_t ascii_len = data->len; + binascii_state *state = NULL; char padding_started = 0; /* Allocate the buffer */ @@ -463,7 +464,12 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) unsigned char *bin_data_start = bin_data; if (strict_mode && ascii_len > 0 && ascii_data[0] == '=') { - goto malformed_padding; + malformed_padding: + state = PyModule_GetState(module); + if (state) { + PyErr_SetString(state->Error, "Malformed padding in strict mode"); + } + goto error_end; } int quad_pos = 0; @@ -484,7 +490,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) ** in strict mode, an error should raise if there's excess data after the padding. */ if (strict_mode && i + 1 < ascii_len) { - binascii_state *state = PyModule_GetState(module); + state = PyModule_GetState(module); if (state) { PyErr_SetString(state->Error, "Excess data after padding is not allowed when using strict mode"); } @@ -499,7 +505,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) this_ch = table_a2b_base64[this_ch]; if (this_ch >= 64) { if (strict_mode) { - binascii_state *state = PyModule_GetState(module); + state = PyModule_GetState(module); if (state) { PyErr_SetString(state->Error, "Only base64 data is allowed when using strict mode"); } @@ -510,12 +516,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) // Characters that are not '=', in the middle of the padding, are not allowed if (strict_mode && padding_started) { - malformed_padding: - binascii_state *state = PyModule_GetState(module); - if (state) { - PyErr_SetString(state->Error, "Malformed padding in strict mode"); - } - goto error_end; + goto malformed_padding; } pads = 0; @@ -543,7 +544,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) } if (quad_pos != 0) { - binascii_state *state = PyModule_GetState(module); + state = PyModule_GetState(module); if (state == NULL) { /* error already set, from PyModule_GetState */ } else if (quad_pos == 1) { From 08aa26c3435cbc9f599eab7e5d6a87b717294dbd Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Fri, 16 Jul 2021 20:00:39 +0300 Subject: [PATCH 17/23] Corrected the RST syntax for argument in docs (italic) --- Doc/library/binascii.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index 17337fa7f3d7bf..fd5df69e852dc1 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -55,7 +55,7 @@ The :mod:`binascii` module defines the following functions: Convert a block of base64 data back to binary and return the binary data. More than one line may be passed at a time. - If `strict_mode` is true, only valid base64 data will be converted. Invalid base64 + If *strict_mode* is true, only valid base64 data will be converted. Invalid base64 data will raise :exc:`binascii.Error`. Valid base64: From 2f1990e1e3bc4fcc024ae1fd982221da813b42e9 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Fri, 16 Jul 2021 20:47:22 +0300 Subject: [PATCH 18/23] Corrected the RST syntax for argument in news (italic) --- .../next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst b/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst index 19ef510e6a7874..f96139960df909 100644 --- a/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst +++ b/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst @@ -1,3 +1,3 @@ -| Added a new optional :code:`strict_mode` parameter to `binascii.a2b_base64`. -| When :code:`scrict_mode` is set to :code:`True`, the `a2b_base64` function will accept only valid base64 content. +| Added a new optional :code:`strict_mode` parameter to *binascii.a2b_base64*. +| When :code:`scrict_mode` is set to :code:`True`, the *a2b_base64* function will accept only valid base64 content. | More details about what "valid base64 content" is, can be found in the function's documentation. \ No newline at end of file From fa959bd54f692807a6268f20403b4f56119bf302 Mon Sep 17 00:00:00 2001 From: Idan Moral Date: Fri, 16 Jul 2021 21:15:35 +0300 Subject: [PATCH 19/23] Removed whitespace that lead to build failure --- Lib/test/test_binascii.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index 8e7afb910630a7..27960ac6024d79 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -118,7 +118,7 @@ def test_base64_strict_mode(self): # Test base64 with strict mode on def _assertRegexTemplate(assert_regex: str, data: bytes, non_strict_mode_expected_result: bytes): with self.assertRaisesRegex(binascii.Error, assert_regex): - binascii.a2b_base64(self.type2test(data), strict_mode=True) + binascii.a2b_base64(self.type2test(data), strict_mode=True) assert binascii.a2b_base64(self.type2test(data), strict_mode=False) == non_strict_mode_expected_result assert binascii.a2b_base64(self.type2test(data)) == non_strict_mode_expected_result From a60a8c6ec438763b8403d80fb7130276b649e769 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Sun, 18 Jul 2021 16:16:02 -0700 Subject: [PATCH 20/23] use self.assertEqual instead of assert == --- Lib/test/test_binascii.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index 27960ac6024d79..e5d301a71be525 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -119,8 +119,10 @@ def test_base64_strict_mode(self): def _assertRegexTemplate(assert_regex: str, data: bytes, non_strict_mode_expected_result: bytes): with self.assertRaisesRegex(binascii.Error, assert_regex): binascii.a2b_base64(self.type2test(data), strict_mode=True) - assert binascii.a2b_base64(self.type2test(data), strict_mode=False) == non_strict_mode_expected_result - assert binascii.a2b_base64(self.type2test(data)) == non_strict_mode_expected_result + self.assertEqual(binascii.a2b_base64(self.type2test(data), strict_mode=False), + non_strict_mode_expected_result) + self.assertEqual(binascii.a2b_base64(self.type2test(data)), + non_strict_mode_expected_result) def assertExcessData(data, non_strict_mode_expected_result: bytes): _assertRegexTemplate(r'(?i)Excess data', data, non_strict_mode_expected_result) From 03072726fe040ec0057d5d3ac0b995cc58918e35 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Sun, 18 Jul 2021 16:35:33 -0700 Subject: [PATCH 21/23] remove leadg `| ` characters in NEWS --- .../next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst b/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst index f96139960df909..f49e7a84cc5375 100644 --- a/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst +++ b/Misc/NEWS.d/next/Library/2021-01-31-18-24-54.bpo-43086.2_P-SH.rst @@ -1,3 +1,3 @@ -| Added a new optional :code:`strict_mode` parameter to *binascii.a2b_base64*. -| When :code:`scrict_mode` is set to :code:`True`, the *a2b_base64* function will accept only valid base64 content. -| More details about what "valid base64 content" is, can be found in the function's documentation. \ No newline at end of file +Added a new optional :code:`strict_mode` parameter to *binascii.a2b_base64*. +When :code:`scrict_mode` is set to :code:`True`, the *a2b_base64* function will accept only valid base64 content. +More details about what "valid base64 content" is, can be found in the function's documentation. From d26e1ebc086f50f8bc9f2d1ae85600d8279ca9b1 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Sun, 18 Jul 2021 16:40:46 -0700 Subject: [PATCH 22/23] Simplify the error messages. No need to mention "strict mode" within the error message. --- Modules/binascii.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/binascii.c b/Modules/binascii.c index edeaa66f507ae3..50f25b406a924e 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -467,7 +467,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) malformed_padding: state = get_binascii_state(module); if (state) { - PyErr_SetString(state->Error, "Malformed padding in strict mode"); + PyErr_SetString(state->Error, "Leading padding not allowed"); } goto error_end; } @@ -492,7 +492,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) if (strict_mode && i + 1 < ascii_len) { state = get_binascii_state(module); if (state) { - PyErr_SetString(state->Error, "Excess data after padding is not allowed when using strict mode"); + PyErr_SetString(state->Error, "Excess data after padding"); } goto error_end; } @@ -507,7 +507,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode) if (strict_mode) { state = get_binascii_state(module); if (state) { - PyErr_SetString(state->Error, "Only base64 data is allowed when using strict mode"); + PyErr_SetString(state->Error, "Only base64 data is allowed"); } goto error_end; } From 652e7f4e6395947c0e558647a7c46c927f544a7f Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Sun, 18 Jul 2021 16:57:22 -0700 Subject: [PATCH 23/23] update test for error message (Leading vs Malformed) --- Lib/test/test_binascii.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index e5d301a71be525..74438d837852c8 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -131,7 +131,7 @@ def assertNonBase64Data(data, non_strict_mode_expected_result: bytes): _assertRegexTemplate(r'(?i)Only base64 data', data, non_strict_mode_expected_result) def assertMalformedPadding(data, non_strict_mode_expected_result: bytes): - _assertRegexTemplate(r'(?i)Malformed padding', data, non_strict_mode_expected_result) + _assertRegexTemplate(r'(?i)Leading padding', data, non_strict_mode_expected_result) # Test excess data exceptions assertExcessData(b'ab==a', b'i') pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy