Fix an issue with JSON encoding of "Infinity" and "NaN" values #26933

Merged
merged 1 commit into from Nov 13, 2016

Projects

None yet

7 participants

@prathamesh-sonpatki

Summary

  • When as_json returns Infinity or NaN as the value of any of the key,
    we don't used to call as_json on it as it was treated as primitive.
  • This used to pass Infinity or NaN to JSON.generate and Ruby used
    to throw an error for Infinity/NaN not allowed in JSON.
  • This patch changes the code to call as_json on these primitives so
    that they are converted to proper values before being passed to
    JSON.generate.
  • Fixes #26877.

r? @chancancode

@prathamesh-sonpatki prathamesh-sonpatki Fix an issue with JSON encoding of "Infinity" and "NaN" values
- When `as_json` returns `Infinity` or `NaN` as the value of any of the key,
  we don't used to call `as_json` on it as it was treated as primitive.
- This used to pass `Infinity` or `NaN` to `JSON.generate` and Ruby used
  to throw an error for `Infinity/NaN not allowed in JSON.`
- This patch changes the code to call `as_json` on these primitives so
  that they are converted to proper values before being passed to
  `JSON.generate`.
- Fixes #26877.
8776f15
@prathamesh-sonpatki
Member
prathamesh-sonpatki commented Nov 13, 2016 edited

@pixeltrix I had a discussion about this issue with @matthewd at Rubyconf and he suggested that we merge and backport this change and after that deprecate the behvior from #2532 and #6096 on master, and eventually remove it in next to next release. I will open deprecation PR once this gets merged.

@pixeltrix
Member

@prathamesh-sonpatki sounds like a plan 😄

@prathamesh-sonpatki

@pixeltrix So can we merge this 😄

@pixeltrix pixeltrix merged commit c85d305 into rails:master Nov 13, 2016

1 of 2 checks passed

continuous-integration/travis-ci/pr The Travis CI build could not complete due to an error
Details
codeclimate Code Climate didn't find any new or fixed issues.
Details
@pixeltrix
Member

Done 👍

@@ -432,6 +432,28 @@ def test_exception_to_json
assert_equal '"foo"', ActiveSupport::JSON.encode(exception)
end
+ class InfiniteNumber
+ def as_json(options = nil)
+ { "number" => 1.0 / 0 }
@simi
simi Nov 13, 2016 Contributor

What about to use Float::INFINITY directly here?

@pixeltrix
pixeltrix Nov 13, 2016 Member

Changed in d2890f7 - thanks @simi

@@ -432,6 +432,28 @@ def test_exception_to_json
assert_equal '"foo"', ActiveSupport::JSON.encode(exception)
end
+ class InfiniteNumber
+ def as_json(options = nil)
+ { "number" => 1.0 / 0 }
@pixeltrix
pixeltrix Nov 13, 2016 Member

Changed in d2890f7 - thanks @simi

+ def test_to_json_works_when_as_json_returns_infinite_number
+ expected = { number: nil }.to_json
+ assert_equal expected, InfiniteNumber.new.to_json
+ end
@pixeltrix
pixeltrix Nov 13, 2016 Member

I wouldn't use to_json to generate expected values here since that's the method under test - better to use literal values, e.g:

assert_equal '{"number":null}' InfiniteNumber.new.to_json
+ def test_to_json_works_when_as_json_returns_NaN_number
+ expected = { number: nil }.to_json
+ assert_equal expected, NaNNumber.new.to_json
+ end
@pixeltrix
pixeltrix Nov 13, 2016 Member

Ditto here - use a literal for the expected value.

+
+ class NaNNumber
+ def as_json(options = nil)
+ { "number" => 0.0 / 0 }
@simi
simi Nov 13, 2016 Contributor

0.0 / 0 => Float:NAN

Too late :(, is it worth to open PR for this?

@pixeltrix
pixeltrix Nov 13, 2016 Member

No, I'll fix it

@pixeltrix
pixeltrix Nov 13, 2016 Member

Two commits later I've fixed it - more haste, less speed 😄

@prathamesh-sonpatki

Thanks @simi and @pixeltrix!

@prathamesh-sonpatki prathamesh-sonpatki deleted the prathamesh-sonpatki:fix-26877 branch Nov 13, 2016
@prathamesh-sonpatki

@pixeltrix Please backport this and other related commits as well.

@rafaelfranca
Member

Backported in 2e421ad

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment