mirror of
https://github.com/django/django.git
synced 2024-12-31 21:46:05 +00:00
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 copy
|
||||||
import datetime
|
import datetime
|
||||||
import decimal
|
import decimal
|
||||||
import math
|
|
||||||
import operator
|
import operator
|
||||||
import uuid
|
import uuid
|
||||||
import warnings
|
import warnings
|
||||||
@ -1703,22 +1702,24 @@ class DecimalField(Field):
|
|||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
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:
|
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):
|
except (decimal.InvalidOperation, TypeError, ValueError):
|
||||||
raise exceptions.ValidationError(
|
raise exceptions.ValidationError(
|
||||||
self.error_messages["invalid"],
|
self.error_messages["invalid"],
|
||||||
code="invalid",
|
code="invalid",
|
||||||
params={"value": value},
|
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):
|
def get_db_prep_save(self, value, connection):
|
||||||
return connection.ops.adapt_decimalfield_value(
|
return connection.ops.adapt_decimalfield_value(
|
||||||
|
@ -67,10 +67,19 @@ class DecimalFieldTests(TestCase):
|
|||||||
|
|
||||||
def test_save_nan_invalid(self):
|
def test_save_nan_invalid(self):
|
||||||
msg = "“nan” value must be a decimal number."
|
msg = "“nan” value must be a decimal number."
|
||||||
with self.assertRaisesMessage(ValidationError, msg):
|
for value in [float("nan"), math.nan, "nan"]:
|
||||||
BigD.objects.create(d=float("nan"))
|
with self.subTest(value), self.assertRaisesMessage(ValidationError, msg):
|
||||||
with self.assertRaisesMessage(ValidationError, msg):
|
BigD.objects.create(d=value)
|
||||||
BigD.objects.create(d=math.nan)
|
|
||||||
|
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):
|
def test_fetch_from_db_without_float_rounding(self):
|
||||||
big_decimal = BigD.objects.create(d=Decimal(".100000000000000000000000000005"))
|
big_decimal = BigD.objects.create(d=Decimal(".100000000000000000000000000005"))
|
||||||
|
Loading…
Reference in New Issue
Block a user