summaryrefslogtreecommitdiff
path: root/tests/model_fields
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2023-02-25 13:09:53 -0500
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-03-09 15:55:10 +0100
commitdde2537fbb04ad78a673092a931b449245a2d6ae (patch)
tree4335962e7d4ab3b86ee82fd8b51ebd372170b49b /tests/model_fields
parentcc67344db9de0248ba1064f7e986c6b29276a7b1 (diff)
downloaddjango-dde2537fbb04ad78a673092a931b449245a2d6ae.tar.gz
Fixed #27397 -- Prevented integer overflows on integer field lookups.
This prevents a sqlite3 crash and address a potential DDoS vector on PostgreSQL caused by full-table-scans on overflows.
Diffstat (limited to 'tests/model_fields')
-rw-r--r--tests/model_fields/test_integerfield.py39
1 files changed, 39 insertions, 0 deletions
diff --git a/tests/model_fields/test_integerfield.py b/tests/model_fields/test_integerfield.py
index 3ee6ac16d8..7698160678 100644
--- a/tests/model_fields/test_integerfield.py
+++ b/tests/model_fields/test_integerfield.py
@@ -1,3 +1,5 @@
+from unittest import SkipTest
+
from django.core import validators
from django.core.exceptions import ValidationError
from django.db import IntegrityError, connection, models
@@ -94,6 +96,43 @@ class IntegerFieldTests(TestCase):
instance.value = max_value
instance.full_clean()
+ def test_backend_range_min_value_lookups(self):
+ min_value = self.backend_range[0]
+ if min_value is None:
+ raise SkipTest("Backend doesn't define an integer min value.")
+ underflow_value = min_value - 1
+ self.model.objects.create(value=min_value)
+ # A refresh of obj is necessary because last_insert_id() is bugged
+ # on MySQL and returns invalid values.
+ obj = self.model.objects.get(value=min_value)
+ with self.assertNumQueries(0), self.assertRaises(self.model.DoesNotExist):
+ self.model.objects.get(value=underflow_value)
+ with self.assertNumQueries(1):
+ self.assertEqual(self.model.objects.get(value__gt=underflow_value), obj)
+ with self.assertNumQueries(1):
+ self.assertEqual(self.model.objects.get(value__gte=underflow_value), obj)
+ with self.assertNumQueries(0), self.assertRaises(self.model.DoesNotExist):
+ self.model.objects.get(value__lt=underflow_value)
+ with self.assertNumQueries(0), self.assertRaises(self.model.DoesNotExist):
+ self.model.objects.get(value__lte=underflow_value)
+
+ def test_backend_range_max_value_lookups(self):
+ max_value = self.backend_range[-1]
+ if max_value is None:
+ raise SkipTest("Backend doesn't define an integer max value.")
+ overflow_value = max_value + 1
+ obj = self.model.objects.create(value=max_value)
+ with self.assertNumQueries(0), self.assertRaises(self.model.DoesNotExist):
+ self.model.objects.get(value=overflow_value)
+ with self.assertNumQueries(0), self.assertRaises(self.model.DoesNotExist):
+ self.model.objects.get(value__gt=overflow_value)
+ with self.assertNumQueries(0), self.assertRaises(self.model.DoesNotExist):
+ self.model.objects.get(value__gte=overflow_value)
+ with self.assertNumQueries(1):
+ self.assertEqual(self.model.objects.get(value__lt=overflow_value), obj)
+ with self.assertNumQueries(1):
+ self.assertEqual(self.model.objects.get(value__lte=overflow_value), obj)
+
def test_redundant_backend_range_validators(self):
"""
If there are stricter validators than the ones from the database