Re: [perl #38485] use integer; 0x80000000/-1; # coredump
Yitzchak Scott-Thoennes [Mon, 13 Feb 2006 01:39:25 +0000 (17:39 -0800)]
Message-ID: <20060213093925.GA3476@efn.org>

p4raw-id: //depot/perl@27205

lib/integer.t
pp.c

index 5c353b3..c1bb4d0 100644 (file)
@@ -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 4080c45..f9f9e7b 100644 (file)
--- 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;
      }
 }