Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[perl #26522] "use bignum" interacts badly with variable capture

1 view
Skip to first unread message

Patrick J. Lopresti

unread,
Feb 10, 2004, 2:58:33 PM2/10/04
to bugs-bi...@netlabs.develooper.com
# New Ticket Created by "Patrick J. LoPresti"
# Please include the string: [perl #26522]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=26522 >


Consider the following program:

============================= bug2.pl ================================
use warnings;
use strict;
#use bignum;

sub call ($$) {
my ($f, $arg) = @_;

print 'Result: ', &$f($arg), "\n";
}

my $c = 6;

call (sub { my $d = $_[0];
my $ret;
$ret = $d * ($c + $d) * ($c - $d);
print "here $c $d $ret\n";
return $ret },
$c/2);
======================================================================

The results of executing this program with and without "bignum":

egghead$ perl ./bug2.pl
here 6 3 81
Result: 81

egghead$ perl -Mbignum ./bug2.pl
here 6 3 162
Result: 162

The first answer is correct. The second is... not.

The output of "perlbug -d" is appended.

- Pat


---
Flags:
category=
severity=
---
Site configuration information for perl v5.8.3:

Configured by patl at Mon Feb 9 19:36:03 EST 2004.

Summary of my perl5 (revision 5.0 version 8 subversion 3) configuration:
Platform:
osname=linux, osvers=2.4.20-20.9, archname=i686-linux
uname='linux mumm-ra.curl.com 2.4.20-20.9 #1 mon aug 18 11:45:58 edt 2003 i686 i686 i386 gnulinux '
config_args='-d'
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=undef use64bitall=undef uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
optimize='-O3',
cppflags='-fno-strict-aliasing -I/usr/local/include -I/usr/include/gdbm'
ccversion='', gccversion='3.2.2 20030222 (Red Hat Linux 3.2.2-5)', 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='cc', ldflags =' -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib
libs=-lnsl -lgdbm -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='-rdynamic'
cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:

---
@INC for perl v5.8.3:
/usr/local/perl-5.8.3/lib/5.8.3/i686-linux
/usr/local/perl-5.8.3/lib/5.8.3
/usr/local/perl-5.8.3/lib/site_perl/5.8.3/i686-linux
/usr/local/perl-5.8.3/lib/site_perl/5.8.3
/usr/local/perl-5.8.3/lib/site_perl
.

---
Environment for perl v5.8.3:
HOME=/u/patl
LANG=POSIX
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/curl/bin:/u/patl/bin:/usr/local/sbin:/sbin:/usr/sbin:/u/patl/bin:/usr/local/sbin:/sbin:/usr/sbin
PERL_BADLANG (unset)
SHELL=/bin/bash

Dave Mitchell

unread,
Feb 11, 2004, 6:29:24 AM2/11/04
to perl5-...@perl.org
On Tue, Feb 10, 2004 at 07:58:33PM -0000, Patrick J. LoPresti wrote:
>
> ============================= bug2.pl ================================
> use warnings;
> use strict;
> #use bignum;
>
> sub call ($$) {
> my ($f, $arg) = @_;
>
> print 'Result: ', &$f($arg), "\n";
> }
>
> my $c = 6;
>
> call (sub { my $d = $_[0];
> my $ret;
> $ret = $d * ($c + $d) * ($c - $d);
> print "here $c $d $ret\n";
> return $ret },
> $c/2);
> ======================================================================
>
> The results of executing this program with and without "bignum":
>
> egghead$ perl ./bug2.pl
> here 6 3 81
> Result: 81
>
> egghead$ perl -Mbignum ./bug2.pl
> here 6 3 162
> Result: 162

Thanks for the report.

The bug can be reduced to the following, and is still present under bleedperl:

use warnings;
use strict;
use bignum;

my ($a,$b,$c);
$a = 6;
$b = $a/2;
$c = 0 - $b;
print "$a $b $c\n";

outputs:

6 3 0

Sounds like a job for Tels!

Dave.


--
Spock (or Data) is fired from his high-ranking position for not being able
to understand the most basic nuances of about one in three sentences that
anyone says to him.
-- Things That Never Happen in "Star Trek" #19

Patrick J. Lopresti

unread,
Feb 11, 2004, 9:10:04 AM2/11/04
to perlbug-...@perl.org
"Dave Mitchell via RT" <perlbug-...@perl.org> writes:

> The bug can be reduced to the following, and is still present under
> bleedperl:

[snip]

I did try to find a smaller example, but the bug kept disappearing.

Any suggestions for a workaround? This is biting me pretty badly...

Tels

unread,
Feb 11, 2004, 1:01:35 PM2/11/04
to perlbug-...@perl.org, da...@fdisolutions.com
-----BEGIN PGP SIGNED MESSAGE-----

Moin,

"Patrick J. LoPresti" wrote:

>Consider the following program:
[snip]

David wrote:

>The bug can be reduced to the following, and is still present under
>bleedperl:
>

> use warnings; use strict; use bignum;
> my ($a,$b,$c);
> $a = 6;
> $b = $a/2;
> $c = 0 - $b;
> print "$a $b $c\n";
>outputs:
>
> 6 3 0
>
>Sounds like a job for Tels!

It took me quite a whilte to trace this and figure it out, since using

perl -Mbignum=t -le '...'

makes the bug disappear. Here is what happens (up to BigInt v1.69 and Bigint
v1.70-tobe):

$b = $a / 2; # creates a BigFloat (due to upgrade by bdiv)
$c = $a - $b; # $c = BigInt - BigFloat

The second line calls the overload code for '-', which in turn calls bsub()
in BigInt. bsub() then flips the sign of $y, calls badd(), flips the sign
back and returns the (potential) modified $x like that:

$y->{sign} =~ tr/+\-/-+/; # does nothing for NaN
$x->badd($y,@r); # badd does not leave internal zeros
$y->{sign} =~ tr/+\-/-+/; # refix $y (does nothing for NaN)
$x; # already rounded or no round necc.

badd() as called by bsub()) then detects that it needs to upgrade the
operation, because it cannot handle the case properly. The upgrade,
however, does not modify $x in place, but returns a new object. bsub()
discards that object (and hence the result) and returns an unmodified $x.
Oops.

There are a couple of possibilities how to fix this:

* make bdiv() return an int on integer results. Would not catch all cases
(think: 7/2 would still lead to bsub() dropping the result).
* make bsub() check for upgrade - easy, quick, but still there might be
cornercases
* fix upgrading so that it keeps the original $x and modifies it in place.
This is tricky, and needs more than 5 mins work. And I gotta leave in 30
minutes and haven't eaten all day, nor slept well...

The attached patch fixes the problem with case #2:

# perl t.pl
6 3 0
# perl -Ilib t.pl
6 3 -3

Patrick, thank you for your report! If you find anything else, please report
it ASAP so that I can include it into v1.70.

Best wishes,

Tels


- --
Signed on Wed Feb 11 18:48:54 2004 with key 0x93B84C15.
Visit my photo gallery at http://bloodgate.com/photos/
PGP key on http://bloodgate.com/tels.asc or per email.

"Some spammers have this warped idea that their freedom of speech is
guaranteed all the way into my hard drive, but it is my firm belief that
their rights end at my firewall." -- Nigel Featherston

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2-rc1-SuSE (GNU/Linux)
Comment: When cryptography is outlawed, bayl bhgynjf jvyy unir cevinpl.

iQEVAwUBQCpt/3cLPEOTuEwVAQGZ2Qf9EwipMW0broNp4M+4a4nfsVjs7FnKuYJ+
ruLyLnFmBE2N5Q/Ss0zJW6EPcusVupFpUQqP3ivxVMwcA9AFkQRc+5CDd9oWxofQ
M7RK92bnhWjFqBZGaUJJ0luu6BV5znGMFCu9zrdaRRGDS5n6WDvYybxHbzu2cfbk
IiiT6wKZfuR2ClvWs0TpzuTRe2By5f8yWN3n7YCbvCVxZZ/r+LbVly9eWo/MSq0d
mF7Zre7FoieooMzjE387EgpsSdk/ywl5rjWIaftDrEKiUvMRBlwAFBYNJ6qpvu5K
ZyE2Nz08VVdymmRYIoiayUrJcuBxd4FfEz7LPnlOXOeZuP05g7/9xQ==
=R+Xq
-----END PGP SIGNATURE-----

BigInt-v1.69_bsub_upgrade_patch.txt
0 new messages