Skip to content

Commit 635f722

Browse files
authored
Merge pull request #10 from Stormheg/feature/add-padding-correction
Correct and consider truncated base64 padding valid
2 parents 5114f75 + bc656a9 commit 635f722

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/drf_base64_binaryfield/fields.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ def from_base64(self, data: str) -> bytes:
8787
8888
Override this method if you want to control how base64 is decoded.
8989
"""
90+
data = self._correct_padding(data)
9091
if self.url_safe:
9192
# Base64 uses + and /, but these characters are not safe to use in URLs.
9293
# We allow these characters to be replaced with - and _.
@@ -96,6 +97,16 @@ def from_base64(self, data: str) -> bytes:
9697
return base64.b64decode(data, altchars=websafe_substitution_chars, validate=True)
9798
return base64.b64decode(data, validate=True)
9899

100+
def _correct_padding(self, data: str) -> str:
101+
"""Correct base64 padding, if necessary.
102+
103+
Padding could have been truncated, so we add it back to make sure the data is valid base64.
104+
"""
105+
padding = len(data) % 4
106+
if padding:
107+
data += "=" * (4 - padding)
108+
return data
109+
99110
def to_base64(self, data: bytes) -> bytes:
100111
"""Convert binary data to base64.
101112

tests/test_fields.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def test_base64_binary_field_to_internal_value_happy(input, url_safe, expected_o
2626

2727
@pytest.mark.parametrize(
2828
"input",
29-
["#(*@)", "aGVsbG8", "asd/sd/", "123098"],
29+
["#(*@)", "hello", "aGVsbG8==", "aGVsbG8==", "aGVsbG8===", "aGVsbG8====", "aGVsbG8====="],
3030
)
3131
@pytest.mark.parametrize("url_safe", [True, False])
3232
def test_base64_binary_field_to_internal_value_invalid(input, url_safe):
@@ -64,6 +64,20 @@ def test_base64_binary_field_to_representation_invalid():
6464
assert exc_info.value.detail[0].code == "invalid_type"
6565

6666

67+
@pytest.mark.parametrize(
68+
"input,corrected_input",
69+
[
70+
("WcUTqPwauLDnGdb9uCZ0VQ", "WcUTqPwauLDnGdb9uCZ0VQ=="),
71+
("JWmxDeJ8VCtmukFItR683RM", "JWmxDeJ8VCtmukFItR683RM="),
72+
("402aaUKt/TlX41z5tcQLdv3WMvw", "402aaUKt/TlX41z5tcQLdv3WMvw="),
73+
],
74+
)
75+
def test_base64_binary_field_corrects_truncated_padding(input, corrected_input):
76+
"""Check that the field corrects truncated padding to form valid base64."""
77+
field = Base64BinaryField()
78+
assert field._correct_padding(input) == corrected_input
79+
80+
6781
@pytest.mark.parametrize(
6882
"url_safe",
6983
[True, False],

0 commit comments

Comments
 (0)