Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.96k stars 555 forks source link

print(do {} . "foo") gives unexpected result #6186

Closed p5pRT closed 21 years ago

p5pRT commented 21 years ago

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

Searchable as RT19545$

p5pRT commented 21 years ago

From b.wage@xs4all.nl

Created by b.wage@xs4all.nl

The following line of code prints one line on standard output​:

print($x = (do {} . "This should be printed twice.\n")); print $x;

I would have expected that it prints the line twice\, as the value assigned to $x in the first statement should be used by the two print statements in the same way. But it prints the line just once. This behavior is different from perl 5.6.1.

The documentation says

do BLOCK   Not really a function. Returns the value of the   last command in the sequence of commands indicated   by BLOCK. When modified by a loop modifier\,   executes the BLOCK once before testing the loop   condition. (On other statements the loop modifiers   test the conditional first.)

in this case there *is* no last command in the sequence of commands indicated by BLOCK. So one could argue that this is not a bug\, because I use an undocumented feature of Perl - but the upgrade to 5.8.0. still broke my code!

Thanks\,

Bart Wage

Perl Info ``` Flags: category=core severity=low Site configuration information for perl v5.8.0: Configured by Debian Project at Sat Sep 14 18:17:32 UTC 2002. Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration: Platform: osname=linux, osvers=2.4.19, archname=i386-linux-thread-multi uname='linux cyberhq 2.4.19 #1 smp sun aug 4 11:30:45 pdt 2002 i686 unknown unknown gnulinux ' config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i386-linux -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8.0 -Darchlib=/usr/lib/perl/5.8.0 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.0 -Dsitearch=/usr/local/lib/perl/5.8.0 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.0 -Dd_dosuid -des' hint=recommended, useposix=true, d_sigaction=define usethreads=define use5005threads=undef 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='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O3', cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -I/usr/local/include' ccversion='', gccversion='2.95.4 20011002 (Debian prerelease)', 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=-lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt perllibs=-ldl -lm -lpthread -lc -lcrypt libc=/lib/libc-2.2.5.so, so=so, useshrplib=true, libperl=libperl.so.5.8.0 gnulibc_version='2.2.5' 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.0: /home/bart/lib/perl /etc/perl /usr/local/lib/perl/5.8.0 /usr/local/share/perl/5.8.0 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.8.0 /usr/share/perl/5.8.0 /usr/local/lib/site_perl . Environment for perl v5.8.0: HOME=/home/bart LANG=C LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/home/bart/bin:/home/bart/bin:/home/bart/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/games PERLLIB=/home/bart/lib/perl PERL_BADLANG (unset) SHELL=/bin/bash ```
p5pRT commented 21 years ago

From perlbug-followup@perl.org

[resent by popular demand -rs]

The following line of code prints one line on standard output​:

print($x = (do {} . "This should be printed twice.\n")); print $x;

I would have expected that it prints the line twice\, as the value assigned to $x in the first statement should be used by the two print statements in the same way. But it prints the line just once. This behavior is different from perl 5.6.1.

The documentation says

do BLOCK   Not really a function. Returns the value of the   last command in the sequence of commands indicated   by BLOCK. When modified by a loop modifier\,   executes the BLOCK once before testing the loop   condition. (On other statements the loop modifiers   test the conditional first.)

in this case there *is* no last command in the sequence of commands indicated by BLOCK. So one could argue that this is not a bug\, because I use an undocumented feature of Perl - but the upgrade to 5.8.0. still broke my code!

Thanks\,

Bart Wage

p5pRT commented 21 years ago

From perl5-porters@ton.iguana.be

In article \m3k7h8ky6q\.wl\_rspier@​pobox\.com\,   Bart Wage \perlbug\-followup@​perl\.org writes​:

[resent by popular demand -rs]

The following line of code prints one line on standard output​:

print($x = (do {} . "This should be printed twice.\n")); print $x;

Can in fact easily be transformed into a coredump​: perl -wle '$z=5+($x = do {} . 2)'

p5pRT commented 21 years ago

From @audreyt

On Tue\, Jan 14\, 2003 at 10​:54​:43PM +0000\, Ton Hospel wrote​:

In article \m3k7h8ky6q\.wl\_rspier@​pobox\.com\, Bart Wage \perlbug\-followup@​perl\.org writes​:

[resent by popular demand -rs] The following line of code prints one line on standard output​: print($x = (do {} . "This should be printed twice.\n")); print $x;

Can in fact easily be transformed into a coredump​: perl -wle '$z=5+($x = do {} . 2)'

Here in maintperl (MAINT18448)\, the first example prints two lines as normal\, and the coredump case does not coredump. Seems like already fixed to me.

/Autrijus/

p5pRT commented 21 years ago

From @rgs

Autrijus Tang \autrijus@​autrijus\.org wrote​:

On Tue\, Jan 14\, 2003 at 10​:54​:43PM +0000\, Ton Hospel wrote​:

In article \m3k7h8ky6q\.wl\_rspier@​pobox\.com\, Bart Wage \perlbug\-followup@​perl\.org writes​:

[resent by popular demand -rs] The following line of code prints one line on standard output​: print($x = (do {} . "This should be printed twice.\n")); print $x;

Can in fact easily be transformed into a coredump​: perl -wle '$z=5+($x = do {} . 2)'

Here in maintperl (MAINT18448)\, the first example prints two lines as normal\, and the coredump case does not coredump. Seems like already fixed to me.

Seems to be fixed in blead too.

Here's a test case :

Index​: t/op/do.t

--- t/op/do.t (revision 581) +++ t/op/do.t (working copy) @​@​ -31\,7 +31\,7 @​@​   return $ok; }

-print "1..21\n"; +print "1..22\n";

# Test do &sub and proper @​_ handling. $_[0] = 0; @​@​ -89\,6 +89\,10 @​@​

# 6 must be interpreted as a file name here ok( (!defined do 6) && $!\, "'do 6' : $!" ); + +# [perl #19545] +push @​t\, ($u = (do {} . "This should be printed twice.\n")); +ok( $#t == 0\, "empty do result value" );

END {   1 while unlink("$$.16"\, "$$.17"\, "$$.18"); End.

p5pRT commented 21 years ago

From @nwc10

On Wed\, Jan 15\, 2003 at 10​:39​:29AM +0100\, Rafael Garcia-Suarez wrote​:

Autrijus Tang \autrijus@​autrijus\.org wrote​:

On Tue\, Jan 14\, 2003 at 10​:54​:43PM +0000\, Ton Hospel wrote​:

In article \m3k7h8ky6q\.wl\_rspier@​pobox\.com\, Bart Wage \perlbug\-followup@​perl\.org writes​:

[resent by popular demand -rs] The following line of code prints one line on standard output​: print($x = (do {} . "This should be printed twice.\n")); print $x;

Can in fact easily be transformed into a coredump​: perl -wle '$z=5+($x = do {} . 2)'

Here in maintperl (MAINT18448)\, the first example prints two lines as normal\, and the coredump case does not coredump. Seems like already fixed to me.

Seems to be fixed in blead too.

It's "fixed" in 5.8.0 if you run it under valgrind​:

$ /usr/local/bin/perl5.8.0 -wle '$z=5+($x = do {} . 2)' Name "main​::z" used only once​: possible typo at -e line 1. Name "main​::x" used only once​: possible typo at -e line 1. Use of uninitialized value in concatenation (.) or string at -e line 1. Segmentation fault $ valgrind /usr/local/bin/perl5.8.0 -wle '$z=5+($x = do {} . 2)' ==3311== Memcheck\, a.k.a. Valgrind\, a memory error detector for x86-linux. ==3311== Copyright (C) 2002\, and GNU GPL'd\, by Julian Seward. ==3311== Using valgrind-1.9.3\, a program instrumentation system for x86-linux. ==3311== Copyright (C) 2000-2002\, and GNU GPL'd\, by Julian Seward. ==3311== Estimated CPU clock rate is 733 MHz ==3311== For more details\, rerun with​: -v ==3311== syntax error at -e line 1\, at EOF Execution of -e aborted due to compilation errors. ==3311== ==3311== ERROR SUMMARY​: 0 errors from 0 contexts (suppressed​: 0 from 0) ==3311== malloc/free​: in use at exit​: 45840 bytes in 574 blocks. ==3311== malloc/free​: 781 allocs\, 207 frees\, 59678 bytes allocated. ==3311== For a detailed leak analysis\, rerun with​: --leak-check=yes ==3311== For counts of detected errors\, rerun with​: -v

Notice that it now thinks that there is a syntax error. I can't see how that can happen. (thinks) Something is busting past the end of a local variable? That's the biggest class of bug that valgrind can't see.

Also. 5.6.1 doesn't give the use of unitialised value warning\, whereas 5.8 and 5.005_03 do​:

perl5.6.1 -wle '$z=5+($x = do {} . 2)' Name "main​::x" used only once​: possible typo at -e line 1. Name "main​::z" used only once​: possible typo at -e line 1.

and the coredump from 5.8?

Program received signal SIGSEGV\, Segmentation fault. 0x080c2070 in Perl_pp_add () at pp_hot.c​:326 326 useleft = USE_LEFT(TOPm1s); (gdb) where #0 0x080c2070 in Perl_pp_add () at pp_hot.c​:326 #1 0x080ad42b in Perl_runops_debug () at dump.c​:1398 #2 0x0806043b in S_run_body (oldscope=1) at perl.c​:1681 #3 0x0806000f in perl_run (my_perl=0x8164088) at perl.c​:1600 #4 0x0805cb5b in main (argc=3\, argv=0xbffff9f4\, env=0xbffffa04)   at perlmain.c​:85 #5 0x40081657 in __libc_start_main (main=0x805cab0 \

\, argc=3\,   ubp_av=0xbffff9f4\, init=0x805bbac \<_init>\, fini=0x813f470 \<_fini>\,   rtld_fini=0x4000dcd4 \<_dl_fini>\, stack_end=0xbffff9ec)   at ../sysdeps/generic/libc-start.c​:129

(gdb) print *sp[-1] Cannot access memory at address 0x209

I believe there's more to this one than meets the eye. Can anyone run purify\, the third degree\, or similar\, on it?

Nicholas Clark

p5pRT commented 21 years ago

From @nwc10

On Wed\, Jan 15\, 2003 at 10​:39​:05AM +0000\, Nicholas Clark wrote​:

On Wed\, Jan 15\, 2003 at 10​:39​:29AM +0100\, Rafael Garcia-Suarez wrote​:

Autrijus Tang \autrijus@&#8203;autrijus\.org wrote​:

Here in maintperl (MAINT18448)\, the first example prints two lines as normal\, and the coredump case does not coredump. Seems like already fixed to me.

Seems to be fixed in blead too.

I believe there's more to this one than meets the eye. Can anyone run purify\, the third degree\, or similar\, on it?

Oops. Maybe I was premature​:

$ perl5.8.0 -wle 'print 1\, 2\, 3\, 4' 1234 $ perl5.8.0 -wle 'print 1\, 2\, 3\, do {}\, 4' 4 $ ./perl -Ilib -wle 'print 1\, 2\, 3\, 4' 1234 $ ./perl -Ilib -wle 'print 1\, 2\, 3\, do {}\, 4' 1234

It looks like do {} was doing something evil to the stack\, but it is fixed now\, and wasn't broken previously​:

$ perl5.6.1 -Ilib -wle 'print 1\, 2\, 3\, do {}\, 4' 1234

although there's a bug introduced between 5.6.0 and 5.6.1​:

$ perl5.6.0 -wle 'print do {} . 4' Use of uninitialized value in concatenation (.) at -e line 1. 4 $ perl5.6.1 -wle 'print do {} . 4' 4

Hmm​: $ perl5.8.0 -wle 'print do {} . 4' Use of uninitialized value in concatenation (.) or string at -e line 1.

(doesn't print 4)

Nicholas Clark

p5pRT commented 21 years ago

From @rgs

I wrote​:

Seems to be fixed in blead too.

Here's a test case :

Which I added as change #18487.

p5pRT commented 21 years ago

@rspier - Status changed from 'new' to 'resolved'