Fixed #33033 -- Prevented models.DecimalField from accepting NaN values.

This commit is contained in:
Chinmoy Chakraborty 2021-08-21 20:57:15 +05:30 committed by Mariusz Felisiak
parent 93f3b7a0ba
commit b7fd668b37
2 changed files with 15 additions and 0 deletions

View File

@ -2,6 +2,7 @@ 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
@ -1539,6 +1540,12 @@ class DecimalField(Field):
if value is None: if value is None:
return value return value
if isinstance(value, float): 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) return self.context.create_decimal_from_float(value)
try: try:
return decimal.Decimal(value) return decimal.Decimal(value)

View File

@ -1,3 +1,4 @@
import math
from decimal import Decimal from decimal import Decimal
from django.core import validators from django.core import validators
@ -65,6 +66,13 @@ class DecimalFieldTests(TestCase):
bd = BigD.objects.get(pk=bd.pk) bd = BigD.objects.get(pk=bd.pk)
self.assertEqual(bd.d, Decimal('12.9')) self.assertEqual(bd.d, Decimal('12.9'))
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)
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'))
big_decimal.refresh_from_db() big_decimal.refresh_from_db()