Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use integer; 0x80000000/-1; # coredump #8321

Closed
p5pRT opened this issue Feb 10, 2006 · 28 comments
Closed

use integer; 0x80000000/-1; # coredump #8321

p5pRT opened this issue Feb 10, 2006 · 28 comments

Comments

@p5pRT
Copy link

p5pRT commented Feb 10, 2006

Migrated from rt.perl.org#38485 (status was 'resolved')

Searchable as RT38485$

@p5pRT
Copy link
Author

p5pRT commented Feb 10, 2006

From @nwc10

Created by @nwc10

The code

  use integer;
  0x80000000/-1;

will coredump on (at least) x86 FreeBSD, with a floating point exception.
(It's amazing what strange things you learn from perl6-internals)

Do we want to trap this overflow case before things go boom?
If so, what do we do? Die with something more meaningful analagous to the
division by zero error?

Nicholas Clark

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.9.4:

Configured by nwc10 at Fri Feb 10 21:49:21 GMT 2006.

Summary of my perl5 (revision 5 version 9 subversion 4) configuration:
  Platform:
    osname=freebsd, osvers=5.4-stable, archname=i386-freebsd-thread-multi
    uname='freebsd colon.colondot.net 5.4-stable freebsd 5.4-stable #3: sat oct 15 10:50:35 bst 2005 mbm@colonii.colondot.net:usrobjusrsrcsyscolon i386 '
    config_args='-Dusedevel=y -Dcc=ccache gcc -Dld=gcc -Ubincompat5005 -Uinstallusrbinperl -Dcf_email=nick@ccl4.org -Dperladmin=nick@ccl4.org -Dinc_version_list=  -Dinc_version_list_init=0 -Doptimize=-g -Dusethreads -Uuse64bitint -Dprefix=~/snap5.9.x-27152 -Dusesitecustomize -Accflags=-DPERL_POISON -Uperlio -Dinstallman1dir=none -Dinstallman3dir=none -de'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='ccache gcc', ccflags ='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -DPERL_POISON -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include',
    optimize='-g',
    cppflags='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -DPERL_POISON -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include'
    ccversion='', gccversion='3.4.2 [FreeBSD] 20040728', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags ='-Wl,-E  -L/usr/local/lib'
    libpth=/usr/lib /usr/local/lib
    libs=-lgdbm -lm -lcrypt -lutil -lc_r
    perllibs=-lm -lcrypt -lutil -lc_r
    libc=, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' '
    cccdlflags='-DPIC -fPIC', lddlflags='-shared  -L/usr/local/lib'

Locally applied patches:
    


@INC for perl 5.9.4:
    lib
    /export/home/nwc10/snap5.9.x-27152/lib/perl5/5.9.4/i386-freebsd-thread-multi
    /export/home/nwc10/snap5.9.x-27152/lib/perl5/5.9.4
    /export/home/nwc10/snap5.9.x-27152/lib/perl5/site_perl/5.9.4/i386-freebsd-thread-multi
    /export/home/nwc10/snap5.9.x-27152/lib/perl5/site_perl/5.9.4
    /export/home/nwc10/snap5.9.x-27152/lib/perl5/site_perl
    .


Environment for perl 5.9.4:
    HOME=/export/home/nwc10
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/export/home/nwc10/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin:/export/home/nwc10/bin:/usr/local/sbin:/sbin:/usr/sbin
    PERL_BADLANG (unset)
    SHELL=/usr/local/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Feb 10, 2006

From @smpeters

On Fri, Feb 10, 2006 at 03​:06​:24PM -0800, Nicholas Clark wrote​:

# New Ticket Created by Nicholas Clark
# Please include the string​: [perl #38485]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=38485 >

This is a bug report for perl from nick@​ccl4.org,
generated with the help of perlbug 1.35 running under perl 5.9.4.

-----------------------------------------------------------------
[Please enter your report here]

The code

use integer;
0x80000000/\-1;

will coredump on (at least) x86 FreeBSD, with a floating point exception.
(It's amazing what strange things you learn from perl6-internals)

Do we want to trap this overflow case before things go boom?
If so, what do we do? Die with something more meaningful analagous to the
division by zero error?

Odd. On Linux, I get a Floating Point Exception with a core dump. I'll
compile with -g later to find out exactly where. Solaris gives me
"Useless use of a constant in void context at -e line 1.". OpenBSD
hangs.

Ideally, though, they should all gag and puke similarly rather than each
following their own way to oblivion.

Steve Peters
steve@​fisharerojo.org

@p5pRT
Copy link
Author

p5pRT commented Feb 10, 2006

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Feb 11, 2006

From @andk

On Fri, 10 Feb 2006 17​:31​:58 -0600, Steve Peters <steve@​fisharerojo.org> said​:

use integer;
0x80000000/-1;

will coredump on (at least) x86 FreeBSD, with a floating point exception.
(It's amazing what strange things you learn from perl6-internals)

Do we want to trap this overflow case before things go boom?
If so, what do we do? Die with something more meaningful analagous to the
division by zero error?

  > Odd. On Linux, I get a Floating Point Exception with a core dump. I'll
  > compile with -g later to find out exactly where. Solaris gives me
  > "Useless use of a constant in void context at -e line 1.". OpenBSD
  > hangs.

What?

On my Debian his program just works.

Only a few very old perls (e.g. perl-5.5.650@​5042 or perl-5.8.0@​19096;
in total about 10 of 300) cannot handle this code. The program returns
true on all perls I have from recent times. I append the official
Debian perl '-V' output as a reference. Let me know if I can provide
more info.

--
andreas

Summary of my perl5 (revision 5 version 8 subversion 7) configuration​:
  Platform​:
  osname=linux, osvers=2.4.30, archname=i686-linux-64int
  uname='linux k76 2.4.30 #1 tue apr 26 09​:44​:16 cest 2005 i686 gnulinux '
  config_args='-Dprefix=/usr/local/perl-5.8.7 -Dinstallusrbinperl=n -Uversiononly -des -Dusedevel -Duse64bitint'
  hint=recommended, useposix=true, d_sigaction=define
  usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
  useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
  use64bitint=define use64bitall=undef uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-O2',
  cppflags='-fno-strict-aliasing -pipe -I/usr/local/include'
  ccversion='', gccversion='3.3.6 (Debian 1​:3.3.6-7)', gccosandvers=''
  intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
  ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
  alignbytes=4, prototype=define
  Linker and Libraries​:
  ld='cc', ldflags =' -L/usr/local/lib'
  libpth=/usr/local/lib /lib /usr/lib
  libs=-lnsl -ldb -ldl -lm -lcrypt -lutil -lc
  perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
  libc=/lib/libc-2.3.2.so, so=so, useshrplib=false, libperl=libperl.a
  gnulibc_version='2.3.2'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
  cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'

Characteristics of this binary (from libperl)​:
  Compile-time options​: USE_64_BIT_INT USE_LARGE_FILES
  Built under linux
  Compiled at Jul 8 2005 05​:16​:10
  @​INC​:
  /usr/local/perl-5.8.7/lib/5.8.7/i686-linux-64int
  /usr/local/perl-5.8.7/lib/5.8.7
  /usr/local/perl-5.8.7/lib/site_perl/5.8.7/i686-linux-64int
  /usr/local/perl-5.8.7/lib/site_perl/5.8.7
  /usr/local/perl-5.8.7/lib/site_perl
  .

@p5pRT
Copy link
Author

p5pRT commented Feb 11, 2006

From @smpeters

On Fri, Feb 10, 2006 at 05​:31​:58PM -0600, Steve Peters wrote​:

On Fri, Feb 10, 2006 at 03​:06​:24PM -0800, Nicholas Clark wrote​:

# New Ticket Created by Nicholas Clark
# Please include the string​: [perl #38485]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=38485 >

This is a bug report for perl from nick@​ccl4.org,
generated with the help of perlbug 1.35 running under perl 5.9.4.

-----------------------------------------------------------------
[Please enter your report here]

The code

use integer;
0x80000000/\-1;

will coredump on (at least) x86 FreeBSD, with a floating point exception.
(It's amazing what strange things you learn from perl6-internals)

Do we want to trap this overflow case before things go boom?
If so, what do we do? Die with something more meaningful analagous to the
division by zero error?

Here's the backtrace...

#0 0x0811bffe in Perl_pp_i_divide () at pp.c​:2431
2431 value = POPi / value;
(gdb) bt
#0 0x0811bffe in Perl_pp_i_divide () at pp.c​:2431
#1 0x080d2249 in Perl_runops_debug () at dump.c​:1630
#2 0x080a1669 in Perl_fold_constants (o=0x81f1778) at op.c​:2123
#3 0x080a2241 in Perl_newBINOP (type=57, flags=0, first=0x81cb718,
  last=0x81cb6d8) at op.c​:2400
#4 0x0809b92b in Perl_yyparse () at perly.y​:532
#5 0x08063bf0 in S_parse_body (env=0x0, xsinit=0x805ea68 <xs_init>)
  at perl.c​:2182
#6 0x0806270d in perl_parse (my_perl=0x81c3008, xsinit=0x805ea68
<xs_init>,
  argc=4, argv=0xbfac0084, env=0x0) at perl.c​:1570
#7 0x0805ea2a in main (argc=4, argv=0xbfac0084, env=0xbfac0098)
  at perlmain.c​:101

@p5pRT
Copy link
Author

p5pRT commented Feb 11, 2006

From @smpeters

On Fri, Feb 10, 2006 at 10​:07​:41PM -0600, Steve Peters wrote​:

On Fri, Feb 10, 2006 at 05​:31​:58PM -0600, Steve Peters wrote​:

On Fri, Feb 10, 2006 at 03​:06​:24PM -0800, Nicholas Clark wrote​:

# New Ticket Created by Nicholas Clark
# Please include the string​: [perl #38485]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=38485 >

This is a bug report for perl from nick@​ccl4.org,
generated with the help of perlbug 1.35 running under perl 5.9.4.

-----------------------------------------------------------------
[Please enter your report here]

The code

use integer;
0x80000000/\-1;

will coredump on (at least) x86 FreeBSD, with a floating point exception.
(It's amazing what strange things you learn from perl6-internals)

Do we want to trap this overflow case before things go boom?
If so, what do we do? Die with something more meaningful analagous to the
division by zero error?

This problem seems to actually have a fairly simple solution. If you
C<use integer>, if the divisor is less that zero but greater than
negative one, it is rounded to zero.

steve@​kirk​:~/perl-current$ ./perl -Ilib -Minteger -wle'print
0x80000000/-0.99999999999'
Illegal division by zero at -e line 1.

Since C<use integer> wraps all numbers greater the Perl's IV_MAX, only
one number causes this problem, IV_MIN, and then, only when divided by
-1. Also, when not constrained by C<use integer>, Perl uses pp_divide,
which doesn't have the integer-only constraints. The following patch
should cause Perl to die in this unusual condition.

hange 27155 by stevep@​stevep-mccoy on 2006/02/11 06​:14​:02

  Die when integer overflow condition is detected in division
under
  C<use integer>. Hopefully fixes RT #38485.

Affected files ...

... //depot/perl/pp.c#518 edit

Differences ...

==== //depot/perl/pp.c#518 (text) ====

@​@​ -2423,12 +2423,16 @​@​

PP(pp_i_divide)
{
+ IV num;
  dVAR; dSP; dATARGET; tryAMAGICbin(div,opASSIGN);
  {
  dPOPiv;
  if (value == 0)
- DIE(aTHX_ "Illegal division by zero");
- value = POPi / value;
+ DIE(aTHX_ "Illegal division by zero");
+ num = POPi;
+ if (num == IV_MIN && value == -1)
+ DIE(aTHX_ "Integer overflow in division");
+ value = num / value;
  PUSHi( value );
  RETURN;
  }

@p5pRT
Copy link
Author

p5pRT commented Feb 11, 2006

From @obra

Odd. On Linux, I get a Floating Point Exception with a core dump. I'll
compile with -g later to find out exactly where. Solaris gives me
"Useless use of a constant in void context at -e line 1.". OpenBSD
hangs.

What?

On my Debian his program just works.

Only a few very old perls (e.g. perl-5.5.650@​5042 or perl-5.8.0@​19096;
in total about 10 of 300) cannot handle this code. The program returns
true on all perls I have from recent times. I append the official
Debian perl '-V' output as a reference. Let me know if I can provide
more info.

On Apple's shipped 5.8.1rc3 on OSX 10.3, the program results in

"Abort trap"

@p5pRT
Copy link
Author

p5pRT commented Feb 11, 2006

From @Abigail

On Fri, Feb 10, 2006 at 03​:06​:24PM -0800, Nicholas Clark wrote​:

# New Ticket Created by Nicholas Clark
# Please include the string​: [perl #38485]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=38485 >

This is a bug report for perl from nick@​ccl4.org,
generated with the help of perlbug 1.35 running under perl 5.9.4.

-----------------------------------------------------------------
[Please enter your report here]

The code

use integer;
0x80000000/\-1;

will coredump on (at least) x86 FreeBSD, with a floating point exception.
(It's amazing what strange things you learn from perl6-internals)

Do we want to trap this overflow case before things go boom?
If so, what do we do? Die with something more meaningful analagous to the
division by zero error?

Nicholas Clark

[Please do not change anything below this line]
-----------------------------------------------------------------

Interesting, on Linux I only get an error ("Floating point exception")
if I compile with 32 bit integers. With 64 bits, no problem.

Abigail

@p5pRT
Copy link
Author

p5pRT commented Feb 11, 2006

From @nwc10

On Sat, Feb 11, 2006 at 11​:26​:22PM +0100, Abigail wrote​:

On Fri, Feb 10, 2006 at 03​:06​:24PM -0800, Nicholas Clark wrote​:

# New Ticket Created by Nicholas Clark
# Please include the string​: [perl #38485]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=38485 >

This is a bug report for perl from nick@​ccl4.org,
generated with the help of perlbug 1.35 running under perl 5.9.4.

-----------------------------------------------------------------
[Please enter your report here]

The code

use integer;
0x80000000/\-1;

will coredump on (at least) x86 FreeBSD, with a floating point exception.
(It's amazing what strange things you learn from perl6-internals)

Do we want to trap this overflow case before things go boom?
If so, what do we do? Die with something more meaningful analagous to the
division by zero error?

Nicholas Clark

[Please do not change anything below this line]
-----------------------------------------------------------------

Interesting, on Linux I only get an error ("Floating point exception")
if I compile with 32 bit integers. With 64 bits, no problem.

With 64 bits, do you get the exception with 0x8000000000000000/-1 ?
(-1-(~0>>1))/-1

On FreeBSD with the system's 64 bit perl I see​:

$ perl -le '$a = -1-(~0>>1); print $a; {use integer; print $a/-1}'
-9223372036854775808
-9223372036854775808

(the same system that will coredump for the 32 bit equivalent)

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2006

From @Abigail

On Sat, Feb 11, 2006 at 10​:58​:36PM +0000, Nicholas Clark wrote​:

On Sat, Feb 11, 2006 at 11​:26​:22PM +0100, Abigail wrote​:

On Fri, Feb 10, 2006 at 03​:06​:24PM -0800, Nicholas Clark wrote​:

# New Ticket Created by Nicholas Clark
# Please include the string​: [perl #38485]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=38485 >

This is a bug report for perl from nick@​ccl4.org,
generated with the help of perlbug 1.35 running under perl 5.9.4.

-----------------------------------------------------------------
[Please enter your report here]

The code

use integer;
0x80000000/\-1;

will coredump on (at least) x86 FreeBSD, with a floating point exception.
(It's amazing what strange things you learn from perl6-internals)

Do we want to trap this overflow case before things go boom?
If so, what do we do? Die with something more meaningful analagous to the
division by zero error?

Nicholas Clark

[Please do not change anything below this line]
-----------------------------------------------------------------

Interesting, on Linux I only get an error ("Floating point exception")
if I compile with 32 bit integers. With 64 bits, no problem.

With 64 bits, do you get the exception with 0x8000000000000000/-1 ?
(-1-(~0>>1))/-1

Nope.

On FreeBSD with the system's 64 bit perl I see​:

$ perl -le '$a = -1-(~0>>1); print $a; {use integer; print $a/-1}'
-9223372036854775808
-9223372036854775808

Same here.

Abigail

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2006

From @ysth

On Fri, Feb 10, 2006 at 03​:06​:24PM -0800, Nicholas Clark wrote​:

The code

use integer;
0x80000000/\-1;

will coredump on (at least) x86 FreeBSD, with a floating point exception.

That should do whatever​:

  (IV)( (IV)0x80000000/(IV)-1 )

does in C. Even if that's give an exception. But I highly doubt it
should give a floating point exception.

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2006

From @smpeters

On Sat, Feb 11, 2006 at 08​:01​:35PM -0800, Yitzchak Scott-Thoennes wrote​:

On Fri, Feb 10, 2006 at 03​:06​:24PM -0800, Nicholas Clark wrote​:

The code

use integer;
0x80000000/\-1;

will coredump on (at least) x86 FreeBSD, with a floating point exception.

That should do whatever​:

(IV)( (IV)0x80000000/(IV)-1 )

does in C. Even if that's give an exception. But I highly doubt it
should give a floating point exception.

Actually, this problem is an inherent part of the Intel (and other)
architectures. See <http​://en.wikipedia.org/wiki/SIGFPE> for details.

Steve Peters
steve@​fisharerojo.org

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2006

From @smpeters

On Sun, Feb 12, 2006 at 01​:25​:10AM +0100, Abigail wrote​:

On Sat, Feb 11, 2006 at 10​:58​:36PM +0000, Nicholas Clark wrote​:

On Sat, Feb 11, 2006 at 11​:26​:22PM +0100, Abigail wrote​:

On Fri, Feb 10, 2006 at 03​:06​:24PM -0800, Nicholas Clark wrote​:

# New Ticket Created by Nicholas Clark
# Please include the string​: [perl #38485]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=38485 >

This is a bug report for perl from nick@​ccl4.org,
generated with the help of perlbug 1.35 running under perl 5.9.4.

-----------------------------------------------------------------
[Please enter your report here]

The code

use integer;
0x80000000/\-1;

will coredump on (at least) x86 FreeBSD, with a floating point exception.
(It's amazing what strange things you learn from perl6-internals)

Do we want to trap this overflow case before things go boom?
If so, what do we do? Die with something more meaningful analagous to the
division by zero error?

Nicholas Clark

[Please do not change anything below this line]
-----------------------------------------------------------------

Interesting, on Linux I only get an error ("Floating point exception")
if I compile with 32 bit integers. With 64 bits, no problem.

With 64 bits, do you get the exception with 0x8000000000000000/-1 ?
(-1-(~0>>1))/-1

Nope.

On FreeBSD with the system's 64 bit perl I see​:

$ perl -le '$a = -1-(~0>>1); print $a; {use integer; print $a/-1}'
-9223372036854775808
-9223372036854775808

I also did not run into problems with the above on a Perl built with
-Duse64bitint. I really want to try it on a couple of other CPUs before
I undo the C<die()> I added for the case of INT_MIN / -1;

Steve Peters
steve@​fisharerojo.org

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2006

From @andk

On Sun, 12 Feb 2006 06​:27​:43 -0600, Steve Peters <steve@​fisharerojo.org> said​:

On FreeBSD with the system's 64 bit perl I see​:

$ perl -le '$a = -1-(~0>>1); print $a; {use integer; print $a/-1}'
-9223372036854775808
-9223372036854775808

  > I also did not run into problems with the above on a Perl built with
  > -Duse64bitint.

That also explains why all my perls have no problem, I always use 64bitint.

--
andreas

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2006

From @nwc10

On Sun, Feb 12, 2006 at 04​:34​:39AM -0800, Steve Peters via RT wrote​:

I also did not run into problems with the above on a Perl built with
-Duse64bitint. I really want to try it on a couple of other CPUs before
I undo the C<die()> I added for the case of INT_MIN / -1;

Well, the most "interesting" thing to do would be to set up the signal handler
in the case of INT_MIN / -1, and see if it gets called. Die it it turns out
to have been, otherwise return the result.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2006

From @ysth

On Sun, Feb 12, 2006 at 05​:34​:01AM -0600, Steve Peters wrote​:

On Sat, Feb 11, 2006 at 08​:01​:35PM -0800, Yitzchak Scott-Thoennes wrote​:

On Fri, Feb 10, 2006 at 03​:06​:24PM -0800, Nicholas Clark wrote​:

The code

use integer;
0x80000000/\-1;

will coredump on (at least) x86 FreeBSD, with a floating point exception.

That should do whatever​:

(IV)( (IV)0x80000000/(IV)-1 )

does in C. Even if that's give an exception. But I highly doubt it
should give a floating point exception.

Actually, this problem is an inherent part of the Intel (and other)
architectures. See <http​://en.wikipedia.org/wiki/SIGFPE> for details.

Can you point out what part of that you meant? I didn't know that
"integer divide by zero" or "integer overflow" were in fact classified
as "floating point exceptions". But what does Intel have to do with
it?

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2006

From nick@ing-simmons.net

Paul Johnson <paul@​pjcj.net> writes​:

On Sun, Feb 12, 2006 at 06​:02​:03PM +0000, Nicholas Clark wrote​:

On Sun, Feb 12, 2006 at 04​:34​:39AM -0800, Steve Peters via RT wrote​:

I also did not run into problems with the above on a Perl built with
-Duse64bitint. I really want to try it on a couple of other CPUs before
I undo the C<die()> I added for the case of INT_MIN / -1;

Well, the most "interesting" thing to do would be to set up the signal handler
in the case of INT_MIN / -1, and see if it gets called. Die it it turns out
to have been, otherwise return the result.

If I remember correctly, the C standard could be a little more clear on
this subject but I believe that overflow of signed integers leads to
undefined behaviour. This would be the case in 0x80000000 / -1 where
there is no representation of the result for an integer of 32 bits using
a two's compliment representation. So in that case we shouldn't be too
surprised at different architectures and compilers doing different
things.

Why is / singled out ?

Why not INT_MIN * -1

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2006

From @nwc10

On Sun, Feb 12, 2006 at 08​:48​:26PM +0000, Nick Ing-Simmons wrote​:

Why is / singled out ?

Why not INT_MIN * -1

I think only because we've not yet found a platform where that throws a
signal where the default is to exit with a coredump.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2006

From @ysth

On Sun, Feb 12, 2006 at 06​:02​:03PM +0000, Nicholas Clark wrote​:

On Sun, Feb 12, 2006 at 04​:34​:39AM -0800, Steve Peters via RT wrote​:

I also did not run into problems with the above on a Perl built with
-Duse64bitint. I really want to try it on a couple of other CPUs before
I undo the C<die()> I added for the case of INT_MIN / -1;

Well, the most "interesting" thing to do would be to set up the signal handler
in the case of INT_MIN / -1, and see if it gets called. Die it it turns out
to have been, otherwise return the result.

Hmm. Is it really worth the extra code? Maybe we should just return
INT_MIN for INT_MIN / -1 and 0 for INT_MIN % -1 across the board.

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2006

From @pjcj

On Sun, Feb 12, 2006 at 06​:02​:03PM +0000, Nicholas Clark wrote​:

On Sun, Feb 12, 2006 at 04​:34​:39AM -0800, Steve Peters via RT wrote​:

I also did not run into problems with the above on a Perl built with
-Duse64bitint. I really want to try it on a couple of other CPUs before
I undo the C<die()> I added for the case of INT_MIN / -1;

Well, the most "interesting" thing to do would be to set up the signal handler
in the case of INT_MIN / -1, and see if it gets called. Die it it turns out
to have been, otherwise return the result.

If I remember correctly, the C standard could be a little more clear on
this subject but I believe that overflow of signed integers leads to
undefined behaviour. This would be the case in 0x80000000 / -1 where
there is no representation of the result for an integer of 32 bits using
a two's compliment representation. So in that case we shouldn't be too
surprised at different architectures and compilers doing different
things.

But it's not always the case that -INT_MIN cannot be represented anyway,
especially in sign and magnitude or one's compliment representations.
But even in two's compliment systems, INT_MIN could be -INT_MAX, for
example.

My opinion on this is that by using "integer" you are asking for
whatever C does, and in this case you get undefined behaviour. But then
I also think that Perl should explicitly say that other operations
result in undefined behaviour.

In any case, whatever solution we have for 0x80000000 / -1 should
probably also be applied to 0x80000000 % -1, since % is defined in terms
of /.

--
Paul Johnson - paul@​pjcj.net
http​://www.pjcj.net

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2006

From @ysth

On Sun, Feb 12, 2006 at 01​:13​:17PM -0800, Yitzchak Scott-Thoennes wrote​:

On Sun, Feb 12, 2006 at 06​:02​:03PM +0000, Nicholas Clark wrote​:

On Sun, Feb 12, 2006 at 04​:34​:39AM -0800, Steve Peters via RT wrote​:

I also did not run into problems with the above on a Perl built with
-Duse64bitint. I really want to try it on a couple of other CPUs before
I undo the C<die()> I added for the case of INT_MIN / -1;

Well, the most "interesting" thing to do would be to set up the signal handler
in the case of INT_MIN / -1, and see if it gets called. Die it it turns out
to have been, otherwise return the result.

Hmm. Is it really worth the extra code? Maybe we should just return
INT_MIN for INT_MIN / -1 and 0 for INT_MIN % -1 across the board.

I mean s/INT/IV/g.

How about​:

Inline Patch
--- perl/pp.c   2006-02-10 22:14:58.000000000 -0800
+++ p/pp.c      2006-02-12 13:49:54.803859200 -0800
@@ -2430,9 +2430,12 @@
       if (value == 0)
          DIE(aTHX_ "Illegal division by zero");
       num = POPi;
+
+      /* avoid FPE_INTOVF on some platforms */
       if (num == IV_MIN && value == -1)
-          DIE(aTHX_ "Integer overflow in division");
-      value = num / value;
+          value = IV_MIN;
+      else
+          value = num / value;
       PUSHi( value );
       RETURN;
     }
@@ -2447,7 +2450,11 @@
          dPOPTOPiirl;
          if (!right)
               DIE(aTHX_ "Illegal modulus zero");
-         SETi( left % right );
+         /* avoid FPE_INTOVF on some platforms */
+         if (left == IV_MIN && right == -1)
+             SETi( 0 );
+         else
+             SETi( left % right );
          RETURN;
      }
 }
@@ -2464,7 +2471,11 @@
          dPOPTOPiirl;
          if (!right)
               DIE(aTHX_ "Illegal modulus zero");
-         SETi( left % PERL_ABS(right) );
+         /* avoid FPE_INTOVF on some platforms */
+         if (left == IV_MIN && right == -1)
+             SETi( 0 );
+         else
+             SETi( left % PERL_ABS(right) );
          RETURN;
      }
 }
@@ -2505,7 +2516,11 @@
               }
          }
 #endif
-         SETi( left % right );
+         /* avoid FPE_INTOVF on some platforms */
+         if (left == IV_MIN && right == -1)
+             SETi( 0 );
+         else
+             SETi( left % right );
          RETURN;
      }
 }

@p5pRT
Copy link
Author

p5pRT commented Feb 13, 2006

From @ysth

On Sun, Feb 12, 2006 at 01​:57​:53PM -0800, Yitzchak Scott-Thoennes wrote​:

On Sun, Feb 12, 2006 at 01​:13​:17PM -0800, Yitzchak Scott-Thoennes wrote​:

On Sun, Feb 12, 2006 at 06​:02​:03PM +0000, Nicholas Clark wrote​:

On Sun, Feb 12, 2006 at 04​:34​:39AM -0800, Steve Peters via RT wrote​:

I also did not run into problems with the above on a Perl built with
-Duse64bitint. I really want to try it on a couple of other CPUs before
I undo the C<die()> I added for the case of INT_MIN / -1;

Well, the most "interesting" thing to do would be to set up the signal handler
in the case of INT_MIN / -1, and see if it gets called. Die it it turns out
to have been, otherwise return the result.

Hmm. Is it really worth the extra code? Maybe we should just return
INT_MIN for INT_MIN / -1 and 0 for INT_MIN % -1 across the board.

I mean s/INT/IV/g.

How about​:

--- perl/pp.c 2006-02-10 22​:14​:58.000000000 -0800
+++ p/pp.c 2006-02-12 13​:49​:54.803859200 -0800
@​@​ -2430,9 +2430,12 @​@​
if (value == 0)
DIE(aTHX_ "Illegal division by zero");
num = POPi;
+
+ /* avoid FPE_INTOVF on some platforms */
if (num == IV_MIN && value == -1)
- DIE(aTHX_ "Integer overflow in division");
- value = num / value;
+ value = IV_MIN;
+ else
+ value = num / value;

Hmmm, that does assume wrapping the way two's complement does.

  value = - num;

instead? I'm afraid I don't know anything about non-two's complement
systems. Revised patch attached.

@p5pRT
Copy link
Author

p5pRT commented Feb 13, 2006

From @ysth

intovf.patch
--- perl/pp.c	2006-02-10 22:14:58.000000000 -0800
+++ p/pp.c	2006-02-12 22:14:00.555113600 -0800
@@ -2430,9 +2430,12 @@
       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;
     }
@@ -2447,7 +2450,11 @@
 	  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;
      }
 }
@@ -2464,7 +2471,11 @@
 	  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;
      }
 }
@@ -2505,7 +2516,11 @@
 	       }
 	  }
 #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;
      }
 }
--- perl/lib/integer.t	2006-02-11 06:21:35.000000000 -0800
+++ p/lib/integer.t	2006-02-12 23:46:51.435646400 -0800
@@ -7,7 +7,7 @@
 
 use integer;
 
-use Test::More tests => 12;
+use Test::More tests => 15;
 use Config;
 
 my $x = 4.5;
@@ -55,10 +55,15 @@
 # [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');
 }

@p5pRT
Copy link
Author

p5pRT commented Feb 17, 2006

From @ysth

On Sun, Feb 12, 2006 at 06​:02​:03PM +0000, Nicholas Clark wrote​:

On Sun, Feb 12, 2006 at 04​:34​:39AM -0800, Steve Peters via RT wrote​:

I also did not run into problems with the above on a Perl built with
-Duse64bitint. I really want to try it on a couple of other CPUs before
I undo the C<die()> I added for the case of INT_MIN / -1;

Well, the most "interesting" thing to do would be to set up the signal handler
in the case of INT_MIN / -1, and see if it gets called. Die it it turns out
to have been, otherwise return the result.

Nicholas Clark

I *really* don't like what we are doing now (DIE()'ing, even on systems
that wouldn't have gotten an exception).

If no one wants to implement the above, can the patch in

  http​://nntp.perl.org/group/perl.perl5.porters/109652

be applied, which should avoid the exception altogether?

@p5pRT
Copy link
Author

p5pRT commented Feb 17, 2006

From @rgs

Yitzchak Scott-Thoennes wrote​:

On Sun, Feb 12, 2006 at 06​:02​:03PM +0000, Nicholas Clark wrote​:

On Sun, Feb 12, 2006 at 04​:34​:39AM -0800, Steve Peters via RT wrote​:

I also did not run into problems with the above on a Perl built with
-Duse64bitint. I really want to try it on a couple of other CPUs before
I undo the C<die()> I added for the case of INT_MIN / -1;

Well, the most "interesting" thing to do would be to set up the signal handler
in the case of INT_MIN / -1, and see if it gets called. Die it it turns out
to have been, otherwise return the result.

Nicholas Clark

I *really* don't like what we are doing now (DIE()'ing, even on systems
that wouldn't have gotten an exception).

If no one wants to implement the above, can the patch in

http​://nntp.perl.org/group/perl.perl5.porters/109652

be applied, which should avoid the exception altogether?

OK, I thus applied it as #27205, thanks !

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2006

From @ysth

On Fri, Feb 17, 2006 at 09​:52​:10AM +0100, Rafael Garcia-Suarez wrote​:

Yitzchak Scott-Thoennes wrote​:

On Sun, Feb 12, 2006 at 06​:02​:03PM +0000, Nicholas Clark wrote​:

On Sun, Feb 12, 2006 at 04​:34​:39AM -0800, Steve Peters via RT wrote​:

I also did not run into problems with the above on a Perl built with
-Duse64bitint. I really want to try it on a couple of other CPUs before
I undo the C<die()> I added for the case of INT_MIN / -1;

Well, the most "interesting" thing to do would be to set up the signal handler
in the case of INT_MIN / -1, and see if it gets called. Die it it turns out
to have been, otherwise return the result.

Nicholas Clark

I *really* don't like what we are doing now (DIE()'ing, even on systems
that wouldn't have gotten an exception).

If no one wants to implement the above, can the patch in

http​://nntp.perl.org/group/perl.perl5.porters/109652

be applied, which should avoid the exception altogether?

OK, I thus applied it as #27205, thanks !

Remove the now-unused perldiag entry​:

Inline Patch
--- perl/pod/perldiag.pod.orig	2006-02-13 09:30:30.000000000 -0800
+++ perl/pod/perldiag.pod	2006-02-19 12:03:33.015625000 -0800
@@ -1976,16 +1976,6 @@
 internally--subject to loss of precision errors in subsequent
 operations.
 
-=item Integer overflow in division
-
-(F) In the scope of the C<use integer;> pragma, division would have overflowed.
-This will happen if you attempt to divide the largest negative integer by -1,
-since the result cannot be represented as a signed integer on a two's complement
-system.  This division is trapped as a Perl-level exception because on some
-architectures the integer divide operation will trigger a CPU exception
-causing program exit, rather than merely returning a mathematically wrong
-answer.
-
 =item Integer overflow in format string for %s
 
 (F) The indexes and widths specified in the format string of C<printf()>

@p5pRT
Copy link
Author

p5pRT commented Feb 20, 2006

From @rgarcia

On 2/19/06, Yitzchak Scott-Thoennes <sthoenna@​efn.org> wrote​:

Remove the now-unused perldiag entry​:

--- perl/pod/perldiag.pod.orig 2006-02-13 09​:30​:30.000000000 -0800
+++ perl/pod/perldiag.pod 2006-02-19 12​:03​:33.015625000 -0800
@​@​ -1976,16 +1976,6 @​@​
internally--subject to loss of precision errors in subsequent
operations.

-=item Integer overflow in division

Right; done as #27237, thanks.

@p5pRT
Copy link
Author

p5pRT commented Feb 27, 2006

@smpeters - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant