Строгое декодирование Python2 base64 по-прежнему молча игнорирует недопустимые символы

#python #python-2.7 #base64

#python #python-2.7 #base64

Вопрос:

По какой-то причине я не могу вывести следующий фрагмент с ошибкой, хотя должен.

Вызывая функцию декодирования python2 base64 decodestring с непечатаемыми символами, я ожидаю, что будет вызвано исключение, однако:

 In [1]: import base64

In [2]: base64.decodestring("x01x01x01")
Out[2]: ''
  

Для сравнения, использование метода класса string дает тот же результат:

 In [7]: "x01x01x01".decode("base64")
Out[7]: ''
  

Однако выполнение эквивалента для hex действительно обеспечит ожидаемое поведение (обратите внимание, что был добавлен дополнительный символ для выравнивания до кратных двум, как и ожидалось шестнадцатеричным декодером):

 In [9]: "x01x01x01x01".decode("hex")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-1e73b7069a1d> in <module>()
----> 1 "x01x01x01x01".decode("hex")

/usr/lib/python2.7/encodings/hex_codec.pyc in hex_decode(input, errors)
     40     """
     41     assert errors == 'strict'
---> 42     output = binascii.a2b_hex(input)
     43     return (output, len(input))
     44

TypeError: Non-hexadecimal digit found
  

Несколько других попыток доказали, что обнаруженное поведение заключается в том, что декодер base64, в частности, игнорирует любые недопустимые символы вместо того, чтобы выдавать ошибку. Такое поведение наблюдается, хотя документально подтверждено, что декодер поддерживает только режим строгой обработки ошибок по умолчанию:

 In [11]: "x01x01x01".decode("base64", errors="ignore")
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-11-e0b65726a302> in <module>()
----> 1 "x01x01x01".decode("base64", errors="ignore")

/usr/lib/python2.7/encodings/base64_codec.pyc in base64_decode(input, errors)
     39
     40     """
---> 41     assert errors == 'strict'
     42     output = base64.decodestring(input)
     43     return (output, len(input))

AssertionError:
  

Такое поведение также наблюдается независимо от метода, используемого для выполнения встроенного кодека base64, который поставляется в комплекте с python2.7.

Кроме того, любой допустимый символ будет обработан должным образом, что приведет к странным результатам, таким как следующее:

 In [6]: base64.decodestring("x01x01x01x01x01AA==")
Out[6]: 'x00'

In [7]: base64.decodestring("x01Ax01Ax01=x01=x01A")
Out[7]: 'x00'

In [8]: base64.decodestring("x01Notx01Ax01Base64x01Stringx01")
Out[8]: '6x8b@x05xabx1exebx84xadxae)xe0'
  

Мой вопрос двоякий:

  1. Прав ли я в своем анализе такого поведения?
  2. Почему это поведение было реализовано вместо того, чтобы соответствовать другим кодекам и errors="strict" API?

Ответ №1:

base64 был изобретен, чтобы разрешить инкапсуляцию двоичных файлов в текстовые протоколы. Эти протоколы могли иметь другие ограничения, такие как максимальный размер строки, что требовало вставки конца строк в строки, закодированные в base64. Чтобы быть максимально терпимым к вводимым данным, многие декодеры решили просто игнорировать любой непечатаемый символ.

Именно так был разработан модуль Python base64.

Комментарии:

1. Интересно. Спасибо! Не имело бы смысла поддерживать base64 errors =»ignore» вместо этого?