develooper Front page | perl.perl5.porters | Postings from December 2010

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

From:
Father Chrysostomos via RT
Date:
December 26, 2010 14:39
Subject:
[perl #81170] [PATCH] Fix RT 25274: Math::BigInt::Calc->_num() overflow.
Message ID:
rt-3.6.HEAD-5425-1293403193-832.81170-14-0@perl.org
As 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.
> 
> 






nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About