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

regression in print length undef #11177

Closed
p5pRT opened this issue Mar 6, 2011 · 6 comments
Closed

regression in print length undef #11177

p5pRT opened this issue Mar 6, 2011 · 6 comments

Comments

@p5pRT
Copy link

p5pRT commented Mar 6, 2011

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

Searchable as RT85508$

@p5pRT
Copy link
Author

p5pRT commented Mar 6, 2011

From @nwc10

Created by @nwc10

In fixing a related bug, d88e091 introduced a regression when printing
the length of an undefined value​:

$ ./perl -wle 'print length undef'

$ ./perl -wle 'print length $a'
Name "main​::a" used only once​: possible typo at -e line 1.

$ ./perl^ -wle 'print length undef'
Use of uninitialized value in print at -e line 1.

$ ./perl^ -wle 'print length $a'
Name "main​::a" used only once​: possible typo at -e line 1.
Use of uninitialized value in print at -e line 1.

It's not obvious to me why this code change causes this behaviour change.
It doesn't seem to be to do with list context.

commit d88e091
Author​: Ben Morrow <ben@​morrow.me.uk>
Date​: Fri Aug 20 18​:35​:58 2010 +0100

  Fix my $x = 3; $x = length(undef);.
 
  Assignment of length() to a lexical is optimized by passing the
  assigned-to variable as TARG, avoiding a pp_padsv and pp_sassign.
  9f621b which changed length(undef) to return undef didn't take this into
  account, and used SETs (which doesn't set TARG), so the code above left
  $x == 3.

Inline Patch
diff --git a/pp.c b/pp.c
index 0da8bba..fcb7ff2 100644
--- a/pp.c
+++ b/pp.c
@@ -3105,8 +3105,10 @@ PP(pp_length)
            = sv_2pv_flags(sv, &len,
                           SV_UNDEF_RETURNS_NULL|SV_CONST_RETURN|SV_GMAGIC);
 
-       if (!p)
-           SETs(&PL_sv_undef);
+       if (!p) {
+           sv_setsv(TARG, &PL_sv_undef);
+           SETTARG;
+       }
        else if (DO_UTF8(sv)) {
            SETi(utf8_length((U8*)p, (U8*)p + len));
        }
@@ -3119,7 +3121,8 @@ PP(pp_length)
        else
            SETi(sv_len(sv));
     } else {
-       SETs(&PL_sv_undef);
+       sv_setsv_nomg(TARG, &PL_sv_undef);
+       SETTARG;
     }
     RETURN;
 }

[snip tests for bug fixed]

Nicholas Clark

Perl Info

Flags:
    category=core
    severity=medium

Site configuration information for perl 5.13.4:

Configured by nick at Sun Mar  6 11:55:52 GMT 2011.

Summary of my perl5 (revision 5 version 13 subversion 4) configuration:
  Commit id: d88e091f660036722622a815efa9ef3779605ea6
  Platform:
    osname=linux, osvers=2.6.35.4, archname=x86_64-linux-thread-multi
    uname='linux eris 2.6.35.4 #4 smp tue sep 21 09:54:22 bst 2010 x86_64 gnulinux '
    config_args='-Dusethreads -Dprefix=~/Sandpit/bisect -Dcc=ccache gcc -Dld=gcc -Dnoextensions=IPC/SysV -Dusedevel -de'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='ccache gcc', ccflags ='-DFOO -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-DFOO -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.3.2', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib /lib64 /usr/lib64
    libs=-lnsl -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=/lib/libc-2.7.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.7'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector'

Locally applied patches:
    


@INC for perl 5.13.4:
    lib
    /home/nick/Sandpit/bisect/lib/perl5/site_perl/5.13.4/x86_64-linux-thread-multi
    /home/nick/Sandpit/bisect/lib/perl5/site_perl/5.13.4
    /home/nick/Sandpit/bisect/lib/perl5/5.13.4/x86_64-linux-thread-multi
    /home/nick/Sandpit/bisect/lib/perl5/5.13.4
    .


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

@p5pRT
Copy link
Author

p5pRT commented Mar 6, 2011

From @dgl

On 6 Mar 2011, at 12​:35, Nicholas Clark (via RT) wrote​:
[...]

It's not obvious to me why this code change causes this behaviour change.
It doesn't seem to be to do with list context.

It looks like it's because it results in returning a temporary 'undef' which is neither &PL_sv_undef nor readonly, which seems to be expected by other bits of code.

Making TARG be the copy and returning the actual PL_sv_undef seems to fix it. (Plus it seemed like a good idea to avoid the copy to TARG when it doesn't make sense, although maybe slightly premature optimisation.)

@p5pRT
Copy link
Author

p5pRT commented Mar 6, 2011

From @dgl

0001-Fix-perl-85508-regression-in-print-length-undef.patch
From 0ce9891599f473abedd59f087eafc4414ba53dd7 Mon Sep 17 00:00:00 2001
From: David Leadbeater <dgl@dgl.cx>
Date: Sun, 6 Mar 2011 15:19:57 +0000
Subject: [PATCH] Fix [perl #85508] regression in print length undef

length was returning a temporary copy of undef, this meant it didn't
generate a warning when used uninitialised. Return PL_sv_undef but
also ensure TARG is cleared if needed.
---
 pp.c          |   14 ++++++++++----
 t/op/length.t |   13 ++++++++++---
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/pp.c b/pp.c
index d857c7e..bea4551 100644
--- a/pp.c
+++ b/pp.c
@@ -3330,8 +3330,11 @@ PP(pp_length)
 			   SV_UNDEF_RETURNS_NULL|SV_CONST_RETURN|SV_GMAGIC);
 
 	if (!p) {
-	    sv_setsv(TARG, &PL_sv_undef);
-	    SETTARG;
+	    if (!SvPADTMP(TARG)) {
+		sv_setsv(TARG, &PL_sv_undef);
+		SETTARG;
+	    }
+	    SETs(&PL_sv_undef);
 	}
 	else if (DO_UTF8(sv)) {
 	    SETi(utf8_length((U8*)p, (U8*)p + len));
@@ -3345,8 +3348,11 @@ PP(pp_length)
 	else
 	    SETi(sv_len(sv));
     } else {
-	sv_setsv_nomg(TARG, &PL_sv_undef);
-	SETTARG;
+	if (!SvPADTMP(TARG)) {
+	    sv_setsv_nomg(TARG, &PL_sv_undef);
+	    SETTARG;
+	}
+	SETs(&PL_sv_undef);
     }
     RETURN;
 }
diff --git a/t/op/length.t b/t/op/length.t
index 705b9d5..0288bec 100644
--- a/t/op/length.t
+++ b/t/op/length.t
@@ -6,7 +6,7 @@ BEGIN {
     @INC = '../lib';
 }
 
-plan (tests => 36);
+plan (tests => 37);
 
 print "not " unless length("")    == 0;
 print "ok 1\n";
@@ -210,11 +210,18 @@ is($ul, undef, "Assigned length of overloaded undef with result in TARG");
 
 # ok(!defined $uo); Turns you can't test this. FIXME for pp_defined?
 
-is($warnings, 0, "There were no warnings");
-
 {
     my $y = "\x{100}BC";
     is(index($y, "B"), 1, 'adds an intermediate position to the offset cache');
     is(length $y, 3,
        'Check that sv_len_utf8() can take advantage of the offset cache');
 }
+
+{
+    local $SIG{__WARN__} = sub {
+        pass("'print length undef' warned");
+    };
+    print length undef;
+}
+
+is($warnings, 0, "There were no other warnings");
-- 
1.7.3.5

@p5pRT
Copy link
Author

p5pRT commented Mar 6, 2011

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

@p5pRT
Copy link
Author

p5pRT commented Mar 6, 2011

From @cpansprout

On Sun Mar 06 07​:23​:23 2011, dgl wrote​:

On 6 Mar 2011, at 12​:35, Nicholas Clark (via RT) wrote​:
[...]

It's not obvious to me why this code change causes this behaviour
change.
It doesn't seem to be to do with list context.

It looks like it's because it results in returning a temporary 'undef'
which is neither &PL_sv_undef nor readonly, which seems to be
expected by other bits of code.

Making TARG be the copy and returning the actual PL_sv_undef seems to
fix it. (Plus it seemed like a good idea to avoid the copy to TARG
when it doesn't make sense, although maybe slightly premature
optimisation.)

Thank you. Applied as 9407f9c.

@p5pRT
Copy link
Author

p5pRT commented Mar 6, 2011

@cpansprout - 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