Fixed #33954 -- Prevented models.DecimalField from accepting NaN, Inf, and -Inf values.
This commit is contained in:
parent
806e9e2d0d
commit
b92ffebb0c
|
@ -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(
|
||||
|
|
|
@ -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"))
|
||||
|
|
Loading…
Reference in New Issue