Skip to content

Reject non-finite values (nan, inf) in FloatField#9998

Open
winklemad wants to merge 1 commit into
encode:mainfrom
winklemad:fix-floatfield-non-finite
Open

Reject non-finite values (nan, inf) in FloatField#9998
winklemad wants to merge 1 commit into
encode:mainfrom
winklemad:fix-floatfield-non-finite

Conversation

@winklemad

Copy link
Copy Markdown

Description

FloatField accepts non-finite floats — nan, inf, -inf, and overflow-to-inf strings such as "1e400" — returning float('nan') / float('inf') instead of raising a ValidationError. It is the only DRF numeric field without a finiteness guard: IntegerField and DecimalField already reject these, as does Django's own forms.FloatField.

serializers.FloatField().run_validation('nan')    # -> nan   (before); ValidationError (after)
serializers.FloatField().run_validation('inf')    # -> inf   (before); ValidationError (after)
serializers.FloatField().run_validation('1e400')  # -> inf   (before); ValidationError (after)

The value arrives as a JSON/form string (e.g. "nan"), so it slips past the JSON parser's parse_constant guard — float("nan") accepts it.

Why it matters

REST framework deliberately renders JSON with allow_nan=False to stay spec-compliant (rest_framework/utils/json.py). A non-finite value accepted by FloatField therefore raises ValueError: Out of range float values are not JSON compliant when the object is later serialized, turning a silent validation gap into a 500 error:

from rest_framework.renderers import JSONRenderer
JSONRenderer().render({'x': serializers.FloatField().run_validation('inf')})
# ValueError: Out of range float values are not JSON compliant: inf

Fix

Guard to_internal_value with math.isfinite, mirroring DecimalField (which rejects is_nan) and Django's forms.FloatField (which uses math.isfinite). The existing overflow path (huge integer inputs raising OverflowError) is unchanged; string inputs like "1e400" that float() turns into inf are now rejected as invalid.

Added nan, inf, -inf, 1e400, and native float('nan') / float('inf') cases to TestFloatField.invalid_inputs. Full tests/test_fields.py passes (334 passed, 3 pre-existing skips).

FloatField accepted nan, inf, -inf and overflow-to-inf strings such as
"1e400", returning float('nan')/float('inf') instead of raising a
ValidationError. It was the only numeric field without a finiteness
guard: IntegerField and DecimalField already reject these, as does
Django's own forms.FloatField.

REST framework renders JSON with allow_nan=False to stay spec-compliant,
so a non-finite value accepted here raises "Out of range float values
are not JSON compliant" when the object is later serialized, turning a
validation gap into a 500 error.

Guard to_internal_value with math.isfinite, mirroring DecimalField's
is_nan check and Django's forms.FloatField.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant