Skip to content

Commit bc0c97a

Browse files
Do not require padding when decoding base64 bytes (#1448)
1 parent dbe03f6 commit bc0c97a

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

src/validators/config.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use std::borrow::Cow;
22
use std::str::FromStr;
33

4-
use base64::engine::general_purpose::{STANDARD, URL_SAFE};
5-
use base64::{DecodeError, Engine};
4+
use base64::engine::general_purpose::GeneralPurpose;
5+
use base64::engine::{DecodePaddingMode, GeneralPurposeConfig};
6+
use base64::{alphabet, DecodeError, Engine};
67
use pyo3::types::{PyDict, PyString};
78
use pyo3::{intern, prelude::*};
89

@@ -11,6 +12,15 @@ use crate::input::EitherBytes;
1112
use crate::serializers::BytesMode;
1213
use crate::tools::SchemaDict;
1314

15+
const URL_SAFE_OPTIONAL_PADDING: GeneralPurpose = GeneralPurpose::new(
16+
&alphabet::URL_SAFE,
17+
GeneralPurposeConfig::new().with_decode_padding_mode(DecodePaddingMode::Indifferent),
18+
);
19+
const STANDARD_OPTIONAL_PADDING: GeneralPurpose = GeneralPurpose::new(
20+
&alphabet::STANDARD,
21+
GeneralPurposeConfig::new().with_decode_padding_mode(DecodePaddingMode::Indifferent),
22+
);
23+
1424
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
1525
pub struct ValBytesMode {
1626
pub ser: BytesMode,
@@ -29,10 +39,10 @@ impl ValBytesMode {
2939
pub fn deserialize_string<'py>(self, s: &str) -> Result<EitherBytes<'_, 'py>, ErrorType> {
3040
match self.ser {
3141
BytesMode::Utf8 => Ok(EitherBytes::Cow(Cow::Borrowed(s.as_bytes()))),
32-
BytesMode::Base64 => URL_SAFE
42+
BytesMode::Base64 => URL_SAFE_OPTIONAL_PADDING
3343
.decode(s)
3444
.or_else(|err| match err {
35-
DecodeError::InvalidByte(_, b'/' | b'+') => STANDARD.decode(s),
45+
DecodeError::InvalidByte(_, b'/' | b'+') => STANDARD_OPTIONAL_PADDING.decode(s),
3646
_ => Err(err),
3747
})
3848
.map(EitherBytes::from)

tests/test_json.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,12 @@ def test_json_bytes_base64_round_trip():
401401
assert v.validate_json(b'{"key":' + encoded_url + b'}') == {'key': data}
402402

403403

404+
def test_json_bytes_base64_no_padding():
405+
v = SchemaValidator({'type': 'bytes'}, {'val_json_bytes': 'base64'})
406+
base_64_without_padding = 'bm8tcGFkZGluZw'
407+
assert v.validate_json(json.dumps(base_64_without_padding)) == b'no-padding'
408+
409+
404410
def test_json_bytes_base64_invalid():
405411
v = SchemaValidator({'type': 'bytes'}, {'val_json_bytes': 'base64'})
406412
wrong_input = 'wrong!'

0 commit comments

Comments
 (0)