summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohamed Karam <muhakh@pop-os.localdomain>2022-08-26 15:06:52 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-08-27 15:51:08 +0200
commitb92ffebb0cdc469baaf1b8f0e72dddb069eb2fb4 (patch)
tree43ddc1aae7de4892f35ca39c95d3a9e3abcc20f3
parent806e9e2d0dcf8f58e376fb7e2a8b9771e2a9ce16 (diff)
Fixed #33954 -- Prevented models.DecimalField from accepting NaN, Inf, and -Inf values.
-rw-r--r--django/db/models/fields/__init__.py21
-rw-r--r--tests/model_fields/test_decimalfield.py17
2 files changed, 24 insertions, 14 deletions
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 5381a3b17f..fd6969cd3d 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -2,7 +2,6 @@ import collections.abc
import copy
import datetime
import decimal
-import math
import operator
import uuid
import warnings
@@ -1703,22 +1702,24 @@ class DecimalField(Field):
def to_python(self, value):
if value is None:
return value
- if isinstance(value, float):
- if math.isnan(value):
- raise exceptions.ValidationError(
- self.error_messages["invalid"],
- code="invalid",
- params={"value": value},
- )
- return self.context.create_decimal_from_float(value)
try:
- return decimal.Decimal(value)
+ if isinstance(value, float):
+ decimal_value = self.context.create_decimal_from_float(value)
+ else:
+ decimal_value = decimal.Decimal(value)
except (decimal.InvalidOperation, TypeError, ValueError):
raise exceptions.ValidationError(
self.error_messages["invalid"],
code="invalid",
params={"value": value},
)
+ if not decimal_value.is_finite():
+ raise exceptions.ValidationError(
+ self.error_messages["invalid"],
+ code="invalid",
+ params={"value": value},
+ )
+ return decimal_value
def get_db_prep_save(self, value, connection):
return connection.ops.adapt_decimalfield_value(
diff --git a/tests/model_fields/test_decimalfield.py b/tests/model_fields/test_decimalfield.py
index 912d55af72..88c6878f59 100644
--- a/tests/model_fields/test_decimalfield.py
+++ b/tests/model_fields/test_decimalfield.py
@@ -67,10 +67,19 @@ class DecimalFieldTests(TestCase):
def test_save_nan_invalid(self):
msg = "“nan” value must be a decimal number."
- with self.assertRaisesMessage(ValidationError, msg):
- BigD.objects.create(d=float("nan"))
- with self.assertRaisesMessage(ValidationError, msg):
- BigD.objects.create(d=math.nan)
+ for value in [float("nan"), math.nan, "nan"]:
+ with self.subTest(value), self.assertRaisesMessage(ValidationError, msg):
+ BigD.objects.create(d=value)
+
+ def test_save_inf_invalid(self):
+ msg = "“inf” value must be a decimal number."
+ for value in [float("inf"), math.inf, "inf"]:
+ with self.subTest(value), self.assertRaisesMessage(ValidationError, msg):
+ BigD.objects.create(d=value)
+ msg = "“-inf” value must be a decimal number."
+ for value in [float("-inf"), -math.inf, "-inf"]:
+ with self.subTest(value), self.assertRaisesMessage(ValidationError, msg):
+ BigD.objects.create(d=value)
def test_fetch_from_db_without_float_rounding(self):
big_decimal = BigD.objects.create(d=Decimal(".100000000000000000000000000005"))