This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #73534] Bigrat segfaults on irrational numbers
authorFather Chrysostomos <sprout@cpan.org>
Tue, 5 Oct 2010 06:04:44 +0000 (23:04 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 5 Oct 2010 06:05:59 +0000 (23:05 -0700)
aka [rt.cpan.org #55767] segfault on sqrt(2) with bigrat

The problem seems to be in &Math::BigInt::objectify. It doesn’t try to
convert the number object into the right class if $upgrade is defined.
The attached patch changes it to make sure it belongs to the calling
class or to the $upgrade class.

Here is a ‘one’-liner to trigger the same bug without bigrat:

perl -Ilib -MMath::BigInt=upgrade,Math::BigFloat \
 -MMath::BigFloat=upgrade,Math::BigMouse -le \
 '@Math::BigMouse::ISA = Math::BigFloat; print sqrt Math::BigInt->new(2)'

MANIFEST
dist/Math-BigInt/lib/Math/BigInt.pm
dist/Math-BigInt/t/upgrade2.t [new file with mode: 0644]
pod/perldelta.pod

index a773176..6ab6a86 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -2825,6 +2825,7 @@ dist/Math-BigInt/t/sub_mbf.t              Empty subclass test of BigFloat
 dist/Math-BigInt/t/sub_mbi.t           Empty subclass test of BigInt
 dist/Math-BigInt/t/sub_mif.t           Test A & P with subclasses using mbimbf.inc
 dist/Math-BigInt/t/trap.t              Test whether trap_nan and trap_inf work
+dist/Math-BigInt/t/upgrade2.t          Test that two upgrade levels work
 dist/Math-BigInt/t/upgradef.t          Test if use Math::BigFloat(); under upgrade works
 dist/Math-BigInt/t/upgrade.inc         Actual tests for upgrade.t
 dist/Math-BigInt/t/upgrade.t           Test if use Math::BigInt(); under upgrade works
index aa26996..0ab9120 100644 (file)
@@ -18,7 +18,7 @@ package Math::BigInt;
 my $class = "Math::BigInt";
 use 5.006002;
 
-$VERSION = '1.96';
+$VERSION = '1.97';
 
 @ISA = qw(Exporter);
 @EXPORT_OK = qw(objectify bgcd blcm); 
@@ -2559,7 +2559,7 @@ sub objectify
         {
         $k = $a[0]->new($k);
         }
-      elsif (!defined $up && ref($k) ne $a[0])
+      elsif (ref($k) ne $a[0] and !defined $up || ref $k ne $up)
        {
        # foreign object, try to convert to integer
         $k->can('as_number') ? $k = $k->as_number() : $k = $a[0]->new($k);
diff --git a/dist/Math-BigInt/t/upgrade2.t b/dist/Math-BigInt/t/upgrade2.t
new file mode 100644 (file)
index 0000000..cdc8d0e
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/perl -w
+
+# Test 2 levels of upgrade classes. This used to cause a segv.
+
+use Test::More tests => 1;
+
+use Math::BigInt upgrade => 'Math::BigFloat';
+use Math::BigFloat upgrade => 'Math::BigMouse';
+
+no warnings 'once';
+@Math::BigMouse::ISA = 'Math::BigFloat';
+
+() = sqrt Math::BigInt->new(2);
+pass('sqrt on a big int does not segv if there are 2 upgrade levels');
index 74a1082..b478273 100644 (file)
@@ -258,7 +258,10 @@ messages are not supressed
 
 =item *
 
-C<Math::BigInt> has been upgraded from version 1.95 to 1.96.
+C<Math::BigInt> has been upgraded from version 1.95 to 1.97.
+
+This prevents C<sqrt($int)> from crashing under C<use bigrat;>
+L<[perl #73534]|http://rt.perl.org/rt3//Public/Bug/Display.html?id=73534>.
 
 =item *