Skip to content

Commit

Permalink
Fixed #35483 -- Added NUL (0x00) character validation to ModelChoiceF…
Browse files Browse the repository at this point in the history
…ields.

Applied the ProhibitNullCharactersValidator to ModelChoiceField and ModelMultipleChoiceField.

Co-authored-by: Viktor Paripás <[email protected]>
Co-authored-by: Vasyl Dizhak <[email protected]>
Co-authored-by: Arthur Vasconcelos <[email protected]>
  • Loading branch information
4 people authored and sarahboyce committed Jun 17, 2024
1 parent fa78481 commit 38ad710
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 1 deletion.
7 changes: 7 additions & 0 deletions django/forms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
ImproperlyConfigured,
ValidationError,
)
from django.core.validators import ProhibitNullCharactersValidator
from django.db.models.utils import AltersData
from django.forms.fields import ChoiceField, Field
from django.forms.forms import BaseForm, DeclarativeFieldsMetaclass
Expand Down Expand Up @@ -1487,6 +1488,10 @@ def __init__(
self.limit_choices_to = limit_choices_to # limit the queryset later.
self.to_field_name = to_field_name

def validate_no_null_characters(self, value):
non_null_character_validator = ProhibitNullCharactersValidator()
return non_null_character_validator(value)

def get_limit_choices_to(self):
"""
Return ``limit_choices_to`` for this form field.
Expand Down Expand Up @@ -1551,6 +1556,7 @@ def prepare_value(self, value):
def to_python(self, value):
if value in self.empty_values:
return None
self.validate_no_null_characters(value)
try:
key = self.to_field_name or "pk"
if isinstance(value, self.queryset.model):
Expand Down Expand Up @@ -1631,6 +1637,7 @@ def _check_values(self, value):
code="invalid_list",
)
for pk in value:
self.validate_no_null_characters(pk)
try:
self.queryset.filter(**{key: pk})
except (ValueError, TypeError):
Expand Down
8 changes: 7 additions & 1 deletion tests/model_forms/test_modelchoicefield.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from django.template import Context, Template
from django.test import TestCase

from .models import Article, Author, Book, Category, Writer
from .models import Article, Author, Book, Category, ExplicitPK, Writer


class ModelChoiceFieldTests(TestCase):
Expand Down Expand Up @@ -79,6 +79,12 @@ def test_clean_to_field_name(self):
self.assertEqual(f.clean(self.c1.slug), self.c1)
self.assertEqual(f.clean(self.c1), self.c1)

def test_model_choice_null_characters(self):
f = forms.ModelChoiceField(queryset=ExplicitPK.objects.all())
msg = "Null characters are not allowed."
with self.assertRaisesMessage(ValidationError, msg):
f.clean("\x00something")

def test_choices(self):
f = forms.ModelChoiceField(
Category.objects.filter(pk=self.c1.id), required=False
Expand Down
9 changes: 9 additions & 0 deletions tests/model_forms/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2227,6 +2227,15 @@ def test_model_multiple_choice_number_of_queries(self):
f = forms.ModelMultipleChoiceField(queryset=Writer.objects.all())
self.assertNumQueries(1, f.clean, [p.pk for p in persons[1:11:2]])

def test_model_multiple_choice_null_characters(self):
f = forms.ModelMultipleChoiceField(queryset=ExplicitPK.objects.all())
msg = "Null characters are not allowed."
with self.assertRaisesMessage(ValidationError, msg):
f.clean(["\x00something"])

with self.assertRaisesMessage(ValidationError, msg):
f.clean(["valid", "\x00something"])

def test_model_multiple_choice_run_validators(self):
"""
ModelMultipleChoiceField run given validators (#14144).
Expand Down

0 comments on commit 38ad710

Please sign in to comment.