Skip to content

Commit 0eb2dc1

Browse files
jleclanchecarltongibson
authored andcommitted
Prohibit null characters in CharField by default (#6073)
* Implement an allow_null_bytes argument to CharField (default True) * Switch to using native ProhibitNullCharactersValidator instead
1 parent 6618338 commit 0eb2dc1

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

rest_framework/compat.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
RegexURLResolver as URLResolver,
3030
)
3131

32+
try:
33+
from django.core.validators import ProhibitNullCharactersValidator # noqa
34+
except ImportError:
35+
ProhibitNullCharactersValidator = None
36+
3237

3338
def get_original_route(urlpattern):
3439
"""

rest_framework/fields.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
from rest_framework import ISO_8601
3535
from rest_framework.compat import (
3636
MaxLengthValidator, MaxValueValidator, MinLengthValidator,
37-
MinValueValidator, unicode_repr, unicode_to_repr
37+
MinValueValidator, ProhibitNullCharactersValidator, unicode_repr,
38+
unicode_to_repr
3839
)
3940
from rest_framework.exceptions import ErrorDetail, ValidationError
4041
from rest_framework.settings import api_settings
@@ -755,7 +756,7 @@ class CharField(Field):
755756
'invalid': _('Not a valid string.'),
756757
'blank': _('This field may not be blank.'),
757758
'max_length': _('Ensure this field has no more than {max_length} characters.'),
758-
'min_length': _('Ensure this field has at least {min_length} characters.')
759+
'min_length': _('Ensure this field has at least {min_length} characters.'),
759760
}
760761
initial = ''
761762

@@ -778,6 +779,10 @@ def __init__(self, **kwargs):
778779
self.validators.append(
779780
MinLengthValidator(self.min_length, message=message))
780781

782+
# ProhibitNullCharactersValidator is None on Django < 2.0
783+
if ProhibitNullCharactersValidator is not None:
784+
self.validators.append(ProhibitNullCharactersValidator())
785+
781786
def run_validation(self, data=empty):
782787
# Test for the empty string here so that it does not get validated,
783788
# and so that subclasses do not need to handle it explicitly

tests/test_fields.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import rest_framework
1717
from rest_framework import exceptions, serializers
18+
from rest_framework.compat import ProhibitNullCharactersValidator
1819
from rest_framework.fields import DjangoImageField, is_simple_callable
1920

2021
try:
@@ -728,6 +729,17 @@ def test_disallow_blank_with_trim_whitespace(self):
728729
field.run_validation(' ')
729730
assert exc_info.value.detail == ['This field may not be blank.']
730731

732+
@pytest.mark.skipif(ProhibitNullCharactersValidator is None, reason="Skipped on Django < 2.0")
733+
def test_null_bytes(self):
734+
field = serializers.CharField()
735+
736+
for value in ('\0', 'foo\0', '\0foo', 'foo\0foo'):
737+
with pytest.raises(serializers.ValidationError) as exc_info:
738+
field.run_validation(value)
739+
assert exc_info.value.detail == [
740+
'Null characters are not allowed.'
741+
]
742+
731743

732744
class TestEmailField(FieldValues):
733745
"""

0 commit comments

Comments
 (0)