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

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

Closed
p5pRT opened this issue Dec 28, 2002 · 9 comments
Closed

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

p5pRT opened this issue Dec 28, 2002 · 9 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 28, 2002

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

Searchable as RT19545$

@p5pRT
Copy link
Author

p5pRT commented Dec 28, 2002

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
Copy link
Author

p5pRT commented Jan 14, 2003

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
Copy link
Author

p5pRT commented Jan 14, 2003

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
Copy link
Author

p5pRT commented Jan 15, 2003

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
Copy link
Author

p5pRT commented Jan 15, 2003

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
Copy link
Author

p5pRT commented Jan 15, 2003

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 <main>, 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
Copy link
Author

p5pRT commented Jan 15, 2003

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@​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
Copy link
Author

p5pRT commented Jan 15, 2003

From @rgs

I wrote​:

Seems to be fixed in blead too.

Here's a test case :

Which I added as change #18487.

@p5pRT
Copy link
Author

p5pRT commented Jan 16, 2003

@rspier - Status changed from 'new' 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