Project

General

Profile

Actions

Bug #17731

closed

Integer downflow with inject/reduce

Added by gaojun (Jun Gao) 5 months ago. Updated 4 months ago.

Status:
Closed
Priority:
Normal
Target version:
-
ruby -v:
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]
[ruby-core:102922]

Description

Test case:
[-2305843009213693953,-2305843009213693953,-2305843009213693953].inject(:+)
or
([-2**61-1] * 3).inject(:+)

Expected Result:
-6917529027641081859

Actual Result:
11529215046068469757

Some clues:

  • Downflow seems not happen if there are only two elements in Array
  • The sample above works fine in https://try.ruby-lang.org/
  • [-2305843009213693953,-2305843009213693953,-2305843009213693953].sum can get the correct result
  • ([-2**61] * 3).inject(:+) can get the correct result

Affected Versions:

  • ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]
  • ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux]
  • ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-linux]

Updated by gaojun (Jun Gao) 5 months ago

Some more interesting samples:

3.0.0 :001 > [0,-2305843009213693953,-2305843009213693953].inject(:+)
 => 13835058055282163710 
3.0.0 :002 > [-2305843009213693953,-2305843009213693953].inject(:+)
 => -4611686018427387906 
3.0.0 :003 > [-2305843009213693953,-2305843009213693953,0].inject(:+)
 => -4611686018427387906 

Updated by Hanmac (Hans Mackowiak) 5 months ago

more interesting samples:

[-2305843009213693953,-2305843009213693953,-2305843009213693953].inject(:+)
#=> 11529215046068469757
[-2305843009213693953,-2305843009213693953,-2305843009213693953].inject(&:+)
#=> -6917529027641081859

Updated by marcandre (Marc-Andre Lafortune) 5 months ago

  • Assignee set to marcandre (Marc-Andre Lafortune)

Right, there's a ULONG2NUM that seem to assume the subtotal is always positive...
I'll make a PR for this

Updated by marcandre (Marc-Andre Lafortune) 5 months ago

  • Backport changed from 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN to 2.5: REQUIRED, 2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED

Removing the letter 'U' fixes it...

https://github.com/ruby/ruby/pull/4288

Updated by akr (Akira Tanaka) 5 months ago

marcandre (Marc-Andre Lafortune) wrote in #note-3:

Right, there's a ULONG2NUM that seem to assume the subtotal is always positive...
I'll make a PR for this

nobu changed it from LONG2NUM to ULONG2NUM at
https://github.com/ruby/ruby/commit/6bb70c11b344dee0739c6fb7bbf0ea124b5225b6

Actions #6

Updated by Anonymous 5 months ago

  • Status changed from Open to Closed

Applied in changeset git|a85ed626f18d1014d09fb37eb0a703976c3d2b53.


Fix Enumerable#inject with high negative fixnums [Bug #17731]

Updated by marcandre (Marc-Andre Lafortune) 5 months ago

akr (Akira Tanaka) wrote in #note-5:

nobu changed it from LONG2NUM to ULONG2NUM at
https://github.com/ruby/ruby/commit/6bb70c11b344dee0739c6fb7bbf0ea124b5225b6

Thanks.
The other changes were for counts (always positive) and most were considered as integers. In the inject case, the values can be any fixnum, including negative ones, so that change was a bug. Now fixed.

Updated by nagachika (Tomoyuki Chikanaga) 4 months ago

  • Backport changed from 2.5: REQUIRED, 2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED to 2.5: REQUIRED, 2.6: REQUIRED, 2.7: DONE, 3.0: REQUIRED

ruby_2_7 364c8595884808315aaec9605bf2423963ed81c0 merged revision(s) a85ed626f18d1014d09fb37eb0a703976c3d2b53.

Updated by naruse (Yui NARUSE) 4 months ago

  • Backport changed from 2.5: REQUIRED, 2.6: REQUIRED, 2.7: DONE, 3.0: REQUIRED to 2.5: REQUIRED, 2.6: REQUIRED, 2.7: DONE, 3.0: DONE

ruby_3_0 855401da495117fcf5d258fe43b71010abc43d9a merged revision(s) a85ed626f18d1014d09fb37eb0a703976c3d2b53.

Actions

Also available in: Atom PDF