@@ -433,18 +433,26 @@ binascii.a2b_base64
433433
434434 data: ascii_buffer
435435 /
436+ *
437+ strict_mode: bool(accept={int}) = False
436438
437439Decode a line of base64 data.
440+
441+ strict_mode
442+ When set to True, bytes that are not part of the base64 standard are not allowed.
443+ The same applies to excess data after padding (= / ==).
438444[clinic start generated code]*/
439445
440446static PyObject *
441- binascii_a2b_base64_impl (PyObject * module , Py_buffer * data )
442- /*[clinic end generated code: output=0628223f19fd3f9b input=5872acf6e1cac243 ]*/
447+ binascii_a2b_base64_impl (PyObject * module , Py_buffer * data , int strict_mode )
448+ /*[clinic end generated code: output=5409557788d4f975 input=3a30c4e3528317c6 ]*/
443449{
444450 assert (data -> len >= 0 );
445451
446452 const unsigned char * ascii_data = data -> buf ;
447453 size_t ascii_len = data -> len ;
454+ binascii_state * state = NULL ;
455+ char padding_started = 0 ;
448456
449457 /* Allocate the buffer */
450458 Py_ssize_t bin_len = ((ascii_len + 3 )/4 )* 3 ; /* Upper bound, corrected later */
@@ -455,6 +463,15 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data)
455463 return NULL ;
456464 unsigned char * bin_data_start = bin_data ;
457465
466+ if (strict_mode && ascii_len > 0 && ascii_data [0 ] == '=' ) {
467+ malformed_padding :
468+ state = get_binascii_state (module );
469+ if (state ) {
470+ PyErr_SetString (state -> Error , "Leading padding not allowed" );
471+ }
472+ goto error_end ;
473+ }
474+
458475 int quad_pos = 0 ;
459476 unsigned char leftchar = 0 ;
460477 int pads = 0 ;
@@ -465,20 +482,42 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data)
465482 ** the invalid ones.
466483 */
467484 if (this_ch == BASE64_PAD ) {
485+ padding_started = 1 ;
486+
468487 if (quad_pos >= 2 && quad_pos + ++ pads >= 4 ) {
469- /* A pad sequence means no more input.
470- ** We've already interpreted the data
471- ** from the quad at this point .
488+ /* A pad sequence means we should not parse more input.
489+ ** We've already interpreted the data from the quad at this point.
490+ ** in strict mode, an error should raise if there's excess data after the padding .
472491 */
492+ if (strict_mode && i + 1 < ascii_len ) {
493+ state = get_binascii_state (module );
494+ if (state ) {
495+ PyErr_SetString (state -> Error , "Excess data after padding" );
496+ }
497+ goto error_end ;
498+ }
499+
473500 goto done ;
474501 }
475502 continue ;
476503 }
477504
478505 this_ch = table_a2b_base64 [this_ch ];
479506 if (this_ch >= 64 ) {
507+ if (strict_mode ) {
508+ state = get_binascii_state (module );
509+ if (state ) {
510+ PyErr_SetString (state -> Error , "Only base64 data is allowed" );
511+ }
512+ goto error_end ;
513+ }
480514 continue ;
481515 }
516+
517+ // Characters that are not '=', in the middle of the padding, are not allowed
518+ if (strict_mode && padding_started ) {
519+ goto malformed_padding ;
520+ }
482521 pads = 0 ;
483522
484523 switch (quad_pos ) {
@@ -505,7 +544,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data)
505544 }
506545
507546 if (quad_pos != 0 ) {
508- binascii_state * state = get_binascii_state (module );
547+ state = get_binascii_state (module );
509548 if (state == NULL ) {
510549 /* error already set, from get_binascii_state */
511550 } else if (quad_pos == 1 ) {
@@ -522,6 +561,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data)
522561 } else {
523562 PyErr_SetString (state -> Error , "Incorrect padding" );
524563 }
564+ error_end :
525565 _PyBytesWriter_Dealloc (& writer );
526566 return NULL ;
527567 }
0 commit comments