From:

Date:

December 26, 2010 14:39Subject:

[perl #81170] [PATCH] Fix RT 25274: Math::BigInt::Calc->_num() overflow.Message ID:

rt-3.6.HEAD-5425-1293403193-832.81170-14-0@perl.orgAs often happeneth, I forgat to forward this to p5p: On Sun Dec 26 14:38:35 2010, sprout wrote: > On Wed Dec 22 10:43:11 2010, pjacklam@online.no wrote: > > Why: Math::BigInt::Calc->_num() converts a big integer (in the > > internal > > format) to a Perl scalar. If the big integer is too large to be > > represented as a Perl scalar, it might return a Perl scalar numeric > > "nan", rather than "inf". The reason is that the current algorithm > > might > > multiply "inf" by "0", giving a "nan" which propagates. The > following > > example illustrates the bug: > > > > perl -MMath::BigInt=lib,Calc -wle \ > > 'print Math::BigInt->new("1e999999")->numify()' > > > > How: This fix computes the output in a different way, never multiply > > "inf" by "0". > > > > Test: It is not obvious to me how to test this automatically in a > > portable way, since Perl has no standard way of stringifying a > scalar > > numeric infinity. However the desired behaviour is verified manually > > and > > no existing tests fail with the new code. > > --- > > dist/Math-BigInt/lib/Math/BigInt/Calc.pm | 23 > > ++++++++++++++--------- > > 1 files changed, 14 insertions(+), 9 deletions(-) > > > > diff --git a/dist/Math-BigInt/lib/Math/BigInt/Calc.pm b/dist/Math- > > BigInt/lib/Math/BigInt/Calc.pm > > index 3cb2025..c778dcd 100644 > > --- a/dist/Math-BigInt/lib/Math/BigInt/Calc.pm > > +++ b/dist/Math-BigInt/lib/Math/BigInt/Calc.pm > > @@ -272,17 +272,22 @@ sub _str > > > > sub _num > > { > > - # Make a number (scalar int/float) from a BigInt object > > - my $x = $_[1]; > > + # Make a Perl scalar number (int/float) from a BigInt object. > > + my $x = $_[1]; > > > > - return 0+$x->[0] if scalar @$x == 1; # below $BASE > > - my $fac = 1; > > - my $num = 0; > > - foreach (@$x) > > - { > > - $num += $fac*$_; $fac *= $BASE; > > + return 0 + $x->[0] if scalar @$x == 1; # below $BASE > > + > > + # Start with the most significant element and work towards the > > least > > + # significant element. Avoid multiplying "inf" (which happens > if > > the number > > + # overflows) with "0" (if there are zero elements in $x) since > > this gives > > + # "nan" which propagates to the output. > > + > > + my $num = 0; > > + for (my $i = $#$x ; $i >= 0 ; --$i) { > > + $num *= $BASE; > > + $num += $x -> [$i]; > > } > > - $num; > > + return $num; > > } > > > > > ############################################################################## > > Thank you. Applied as e5dcd52. > >

**[perl #81170] [PATCH] Fix RT 25274: Math::BigInt::Calc->_num() overflow.**by Father Chrysostomos via RT

nntp.perl.org: Perl Programming lists via nntp and http.

Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About