From 45029d2dbcc918ee10234beaf6a38744ad61567e Mon Sep 17 00:00:00 2001 From: Father Chrysostomos Date: Mon, 4 Oct 2010 23:04:44 -0700 Subject: [perl #73534] Bigrat segfaults on irrational numbers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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)' --- dist/Math-BigInt/lib/Math/BigInt.pm | 4 ++-- dist/Math-BigInt/t/upgrade2.t | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 dist/Math-BigInt/t/upgrade2.t (limited to 'dist') diff --git a/dist/Math-BigInt/lib/Math/BigInt.pm b/dist/Math-BigInt/lib/Math/BigInt.pm index aa26996153..0ab9120b70 100644 --- a/dist/Math-BigInt/lib/Math/BigInt.pm +++ b/dist/Math-BigInt/lib/Math/BigInt.pm @@ -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 index 0000000000..cdc8d0edf4 --- /dev/null +++ b/dist/Math-BigInt/t/upgrade2.t @@ -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'); -- cgit v1.2.1