Prohibit null characters in CharField by default (#6073)

* Implement an allow_null_bytes argument to CharField (default True)
* Switch to using native ProhibitNullCharactersValidator instead
This commit is contained in:
Jerome Leclanche 2018-10-02 17:54:15 +03:00 committed by Carlton Gibson
parent 66183389f6
commit 0eb2dc1137
3 changed files with 24 additions and 2 deletions

View File

@ -29,6 +29,11 @@ except ImportError:
RegexURLResolver as URLResolver, RegexURLResolver as URLResolver,
) )
try:
from django.core.validators import ProhibitNullCharactersValidator # noqa
except ImportError:
ProhibitNullCharactersValidator = None
def get_original_route(urlpattern): def get_original_route(urlpattern):
""" """

View File

@ -34,7 +34,8 @@ from pytz.exceptions import InvalidTimeError
from rest_framework import ISO_8601 from rest_framework import ISO_8601
from rest_framework.compat import ( from rest_framework.compat import (
MaxLengthValidator, MaxValueValidator, MinLengthValidator, MaxLengthValidator, MaxValueValidator, MinLengthValidator,
MinValueValidator, unicode_repr, unicode_to_repr MinValueValidator, ProhibitNullCharactersValidator, unicode_repr,
unicode_to_repr
) )
from rest_framework.exceptions import ErrorDetail, ValidationError from rest_framework.exceptions import ErrorDetail, ValidationError
from rest_framework.settings import api_settings from rest_framework.settings import api_settings
@ -755,7 +756,7 @@ class CharField(Field):
'invalid': _('Not a valid string.'), 'invalid': _('Not a valid string.'),
'blank': _('This field may not be blank.'), 'blank': _('This field may not be blank.'),
'max_length': _('Ensure this field has no more than {max_length} characters.'), 'max_length': _('Ensure this field has no more than {max_length} characters.'),
'min_length': _('Ensure this field has at least {min_length} characters.') 'min_length': _('Ensure this field has at least {min_length} characters.'),
} }
initial = '' initial = ''
@ -778,6 +779,10 @@ class CharField(Field):
self.validators.append( self.validators.append(
MinLengthValidator(self.min_length, message=message)) MinLengthValidator(self.min_length, message=message))
# ProhibitNullCharactersValidator is None on Django < 2.0
if ProhibitNullCharactersValidator is not None:
self.validators.append(ProhibitNullCharactersValidator())
def run_validation(self, data=empty): def run_validation(self, data=empty):
# Test for the empty string here so that it does not get validated, # Test for the empty string here so that it does not get validated,
# and so that subclasses do not need to handle it explicitly # and so that subclasses do not need to handle it explicitly

View File

@ -15,6 +15,7 @@ from django.utils.timezone import activate, deactivate, override, utc
import rest_framework import rest_framework
from rest_framework import exceptions, serializers from rest_framework import exceptions, serializers
from rest_framework.compat import ProhibitNullCharactersValidator
from rest_framework.fields import DjangoImageField, is_simple_callable from rest_framework.fields import DjangoImageField, is_simple_callable
try: try:
@ -728,6 +729,17 @@ class TestCharField(FieldValues):
field.run_validation(' ') field.run_validation(' ')
assert exc_info.value.detail == ['This field may not be blank.'] assert exc_info.value.detail == ['This field may not be blank.']
@pytest.mark.skipif(ProhibitNullCharactersValidator is None, reason="Skipped on Django < 2.0")
def test_null_bytes(self):
field = serializers.CharField()
for value in ('\0', 'foo\0', '\0foo', 'foo\0foo'):
with pytest.raises(serializers.ValidationError) as exc_info:
field.run_validation(value)
assert exc_info.value.detail == [
'Null characters are not allowed.'
]
class TestEmailField(FieldValues): class TestEmailField(FieldValues):
""" """