@@ -477,17 +477,24 @@ binascii.a2b_base64
477477 /
478478 *
479479 strict_mode: bool = False
480+ ignorechars: object = None
480481
481482Decode a line of base64 data.
482483
483484 strict_mode
484485 When set to True, bytes that are not part of the base64 standard are not allowed.
485486 The same applies to excess data after padding (= / ==).
487+ ignorechars
488+ A bytes-like object specifying characters to ignore during decoding.
489+ When provided, only characters in this set will be silently ignored;
490+ other non-base64 characters will cause an error. When None (the default),
491+ all non-base64 characters are silently ignored (unless strict_mode is True).
486492[clinic start generated code]*/
487493
488494static PyObject *
489- binascii_a2b_base64_impl (PyObject * module , Py_buffer * data , int strict_mode )
490- /*[clinic end generated code: output=5409557788d4f975 input=13c797187acc9c40]*/
495+ binascii_a2b_base64_impl (PyObject * module , Py_buffer * data , int strict_mode ,
496+ PyObject * ignorechars )
497+ /*[clinic end generated code: output=7d2b92b6f1de3ccc input=485946ff2e8960c6]*/
491498{
492499 assert (data -> len >= 0 );
493500
@@ -496,10 +503,30 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode)
496503 binascii_state * state = NULL ;
497504 char padding_started = 0 ;
498505
506+ /* Handle ignorechars parameter */
507+ Py_buffer ignorechars_buf = {0 };
508+ int has_ignorechars = 0 ;
509+ unsigned char ignorechars_table [256 ] = {0 }; /* Lookup table for ignored chars */
510+
511+ if (ignorechars != Py_None ) {
512+ if (PyObject_GetBuffer (ignorechars , & ignorechars_buf , PyBUF_SIMPLE ) < 0 ) {
513+ return NULL ;
514+ }
515+ has_ignorechars = 1 ;
516+ /* Build lookup table for O(1) character checking */
517+ const unsigned char * ic = (const unsigned char * )ignorechars_buf .buf ;
518+ for (Py_ssize_t j = 0 ; j < ignorechars_buf .len ; j ++ ) {
519+ ignorechars_table [ic [j ]] = 1 ;
520+ }
521+ }
522+
499523 /* Allocate the buffer */
500524 Py_ssize_t bin_len = ((ascii_len + 3 )/4 )* 3 ; /* Upper bound, corrected later */
501525 PyBytesWriter * writer = PyBytesWriter_Create (bin_len );
502526 if (writer == NULL ) {
527+ if (has_ignorechars ) {
528+ PyBuffer_Release (& ignorechars_buf );
529+ }
503530 return NULL ;
504531 }
505532 unsigned char * bin_data = PyBytesWriter_GetData (writer );
@@ -517,8 +544,9 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode)
517544 /* Fast path: use optimized decoder for complete quads.
518545 * This works for both strict and non-strict mode for valid input.
519546 * The fast path stops at padding, invalid chars, or incomplete groups.
547+ * Skip fast path when ignorechars is provided, as we need to check each char.
520548 */
521- if (ascii_len >= 4 ) {
549+ if (ascii_len >= 4 && ! has_ignorechars ) {
522550 Py_ssize_t fast_chars = base64_decode_fast (ascii_data , (Py_ssize_t )ascii_len ,
523551 bin_data , table_a2b_base64 );
524552 if (fast_chars > 0 ) {
@@ -533,6 +561,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode)
533561 int pads = 0 ;
534562 for (; i < ascii_len ; i ++ ) {
535563 unsigned char this_ch = ascii_data [i ];
564+ unsigned char orig_ch = this_ch ; /* Save original for ignorechars check */
536565
537566 /* Check for pad sequences and ignore
538567 ** the invalid ones.
@@ -567,7 +596,20 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode)
567596
568597 this_ch = table_a2b_base64 [this_ch ];
569598 if (this_ch >= 64 ) {
570- if (strict_mode ) {
599+ /* Non-base64 character found */
600+ if (has_ignorechars ) {
601+ /* When ignorechars is provided, only skip if char is in the set */
602+ if (ignorechars_table [orig_ch ]) {
603+ continue ; /* Character is in ignorechars, skip it */
604+ }
605+ /* Character not in ignorechars, raise error */
606+ state = get_binascii_state (module );
607+ if (state ) {
608+ PyErr_SetString (state -> Error , "Only base64 data is allowed" );
609+ }
610+ goto error_end ;
611+ }
612+ else if (strict_mode ) {
571613 state = get_binascii_state (module );
572614 if (state ) {
573615 PyErr_SetString (state -> Error , "Only base64 data is allowed" );
@@ -634,9 +676,15 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode)
634676 }
635677
636678done :
679+ if (has_ignorechars ) {
680+ PyBuffer_Release (& ignorechars_buf );
681+ }
637682 return PyBytesWriter_FinishWithPointer (writer , bin_data );
638683
639684error_end :
685+ if (has_ignorechars ) {
686+ PyBuffer_Release (& ignorechars_buf );
687+ }
640688 PyBytesWriter_Discard (writer );
641689 return NULL ;
642690}
0 commit comments