Skip to content

Commit 1305df5

Browse files
committed
Limit SmallerIntegerFields to 32-bit values
1 parent 52dc36a commit 1305df5

File tree

4 files changed

+46
-7
lines changed

4 files changed

+46
-7
lines changed

django_mongodb_backend/operations.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,15 @@ def explain_query_prefix(self, format=None, **options):
248248
return validated_options
249249

250250
def integer_field_range(self, internal_type):
251-
# MongODB doesn't enforce any integer constraints, but it supports
252-
# integers up to 64 bits.
253-
if internal_type in {
254-
"PositiveBigIntegerField",
255-
"PositiveIntegerField",
256-
"PositiveSmallIntegerField",
257-
}:
251+
# MongoDB doesn't enforce any integer constraints, but the
252+
# SmallIntegerFields use "int" for unique constraints which is limited
253+
# to 32 bits.
254+
if internal_type == "PositiveSmallIntegerField":
255+
return (0, 2147483647)
256+
if internal_type == "SmallIntegerField":
257+
return (-2147483648, 2147483647)
258+
# Other fields use "long" which supports up to 64 bits.
259+
if internal_type in {"PositiveBigIntegerField", "PositiveIntegerField"}:
258260
return (0, 9223372036854775807)
259261
return (-9223372036854775808, 9223372036854775807)
260262

docs/source/ref/models/fields.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ A few notes about some of the other fields:
2020
(rather than microsecond like most other databases), and correspondingly,
2121
:class:`~django.db.models.DurationField` stores milliseconds rather than
2222
microseconds.
23+
- :class:`~django.db.models.SmallIntegerField` and
24+
:class:`~django.db.models.PositiveSmallIntegerField` support 32 bit values
25+
(ranges ``(-2147483648, 2147483647)`` and ``(0, 2147483647)``, respectively),
26+
validated only by forms and model validation. Be careful because MongoDB
27+
doesn't prohibit inserting values outside of the supported range and unique
28+
constraints don't work for values outside of the 32-bit range of the BSON
29+
``int`` type.
30+
2331

2432
MongoDB-specific model fields
2533
=============================

docs/source/releases/5.2.x.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ New features
2020
Backwards incompatible changes
2121
------------------------------
2222

23+
- :class:`django.db.models.SmallIntegerField` and
24+
:class:`django.db.models.PositiveSmallIntegerField` are now limited to 32 bit
25+
values in forms and model validation.
2326
- Removed support for database caching as the MongoDB security team considers the cache
2427
backend's ``pickle`` encoding of cached values a vulnerability. If an attacker
2528
compromises the database, they could run arbitrary commands on the application

tests/model_fields_/test_integerfield.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from django.core.exceptions import ValidationError
12
from django.db import IntegrityError
23
from django.test import TestCase
34

@@ -30,9 +31,22 @@ def test_unique_min_value(self):
3031
with self.assertRaises(IntegrityError):
3132
Integers.objects.create(small=self.min_value)
3233

34+
def test_validate_max_value(self):
35+
Integers(small=self.max_value).full_clean() # no error
36+
msg = "{'small': ['Ensure this value is less than or equal to 2147483647.']"
37+
with self.assertRaisesMessage(ValidationError, msg):
38+
Integers(small=self.max_value + 1).full_clean()
39+
40+
def test_validate_min_value(self):
41+
Integers(small=self.min_value).full_clean() # no error
42+
msg = "{'small': ['Ensure this value is greater than or equal to -2147483648.']"
43+
with self.assertRaisesMessage(ValidationError, msg):
44+
Integers(small=self.min_value - 1).full_clean()
45+
3346

3447
class PositiveSmallIntegerFieldTests(TestCase):
3548
max_value = 2**31 - 1
49+
min_value = 0
3650

3751
def test_unique_max_value(self):
3852
"""
@@ -47,3 +61,15 @@ def test_unique_max_value(self):
4761

4862
# test_unique_min_value isn't needed since PositiveSmallIntegerField has a
4963
# limit of zero (enforced only in forms and model validation).
64+
65+
def test_validate_max_value(self):
66+
Integers(positive_small=self.max_value).full_clean() # no error
67+
msg = "{'positive_small': ['Ensure this value is less than or equal to 2147483647.']"
68+
with self.assertRaisesMessage(ValidationError, msg):
69+
Integers(positive_small=self.max_value + 1).full_clean()
70+
71+
def test_validate_min_value(self):
72+
Integers(positive_small=self.min_value).full_clean() # no error
73+
msg = "{'positive_small': ['Ensure this value is greater than or equal to 0.']"
74+
with self.assertRaisesMessage(ValidationError, msg):
75+
Integers(positive_small=self.min_value - 1).full_clean()

0 commit comments

Comments
 (0)