summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYitzchak Scott-Thoennes <sthoenna@efn.org>2006-02-12 17:39:25 -0800
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2006-02-17 08:50:27 +0000
commita0cec76945276a0895c829a391529265d9b76bc0 (patch)
tree071d39c902266f67ba8504374e9785f6c0ce053a
parentbc82975d259d743626ad1b4a960b4b1f13c7a816 (diff)
downloadperl-a0cec76945276a0895c829a391529265d9b76bc0.tar.gz
Re: [perl #38485] use integer; 0x80000000/-1; # coredump
Message-ID: <20060213093925.GA3476@efn.org> p4raw-id: //depot/perl@27205
-rw-r--r--lib/integer.t11
-rw-r--r--pp.c27
2 files changed, 29 insertions, 9 deletions
diff --git a/lib/integer.t b/lib/integer.t
index 5c353b348c..c1bb4d04cf 100644
--- a/lib/integer.t
+++ b/lib/integer.t
@@ -7,7 +7,7 @@ BEGIN {
use integer;
-use Test::More tests => 12;
+use Test::More tests => 15;
use Config;
my $x = 4.5;
@@ -55,10 +55,15 @@ is(~0, -1, "signed instead of unsigned");
# [perl #38485] use integer; 0x80000000/-1;
SKIP: {
my $ivsize = $Config{ivsize};
- skip "ivsize == $ivsize", 2 unless $ivsize == 4 || $ivsize == 8;
+ skip "ivsize == $ivsize", 4 unless $ivsize == 4 || $ivsize == 8;
my $iv_min = $ivsize == 4 ? -2147483648 : -9223372036854775808;
my $biff;
eval { $biff = $iv_min / -1 };
- like($@, qr/Integer overflow in division/, "Caught IV_MIN / -1");
+ is($@, '', 'IV_MIN / -1 succeeds');
+ is($biff, -$iv_min, 'IV_MIN / -1 == -IV_MIN');
+
+ eval { $biff = $iv_min % -1 };
+ is($@, '', 'IV_MIN % -1 succeeds');
+ is($biff, 0, 'IV_MIN % -1 == 0');
}
diff --git a/pp.c b/pp.c
index 4080c45296..f9f9e7b82d 100644
--- a/pp.c
+++ b/pp.c
@@ -2433,9 +2433,12 @@ PP(pp_i_divide)
if (value == 0)
DIE(aTHX_ "Illegal division by zero");
num = POPi;
- if (num == IV_MIN && value == -1)
- DIE(aTHX_ "Integer overflow in division");
- value = num / value;
+
+ /* avoid FPE_INTOVF on some platforms when num is IV_MIN */
+ if (value == -1)
+ value = - num;
+ else
+ value = num / value;
PUSHi( value );
RETURN;
}
@@ -2450,7 +2453,11 @@ PP(pp_i_modulo_0)
dPOPTOPiirl;
if (!right)
DIE(aTHX_ "Illegal modulus zero");
- SETi( left % right );
+ /* avoid FPE_INTOVF on some platforms when left is IV_MIN */
+ if (right == -1)
+ SETi( 0 );
+ else
+ SETi( left % right );
RETURN;
}
}
@@ -2467,7 +2474,11 @@ PP(pp_i_modulo_1)
dPOPTOPiirl;
if (!right)
DIE(aTHX_ "Illegal modulus zero");
- SETi( left % PERL_ABS(right) );
+ /* avoid FPE_INTOVF on some platforms when left is IV_MIN */
+ if (right == -1)
+ SETi( 0 );
+ else
+ SETi( left % PERL_ABS(right) );
RETURN;
}
}
@@ -2508,7 +2519,11 @@ PP(pp_i_modulo)
}
}
#endif
- SETi( left % right );
+ /* avoid FPE_INTOVF on some platforms when left is IV_MIN */
+ if (right == -1)
+ SETi( 0 );
+ else
+ SETi( left % right );
RETURN;
}
}