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

5.10.0 functionality change and segfault #9732

Closed
p5pRT opened this issue May 12, 2009 · 11 comments
Closed

5.10.0 functionality change and segfault #9732

p5pRT opened this issue May 12, 2009 · 11 comments

Comments

@p5pRT
Copy link

p5pRT commented May 12, 2009

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

Searchable as RT65582$

@p5pRT
Copy link
Author

p5pRT commented May 12, 2009

From @gbarr

Created by @gbarr

I have not been able to track down the exact cause yet, but the following demonstrates
an change in functionality and a subsequent segfault in 5.10

$ cat test
sub type {
  my $r = shift;
  my $q = *$r; # defined in 5.10.0, was undef in all prior versions tested
  print defined($q) ? "defined" : "undefined","\n";
  print "$q\n"; # will segv in Perl_sv_2pv_flags when $r = *DATA{IO}
}

type(*DATA);
type(*DATA{IO}); # will segv in Perl_sv_2pv_flags
<DATA>; # force DATA to be created

$ /apps/perl-5.8.9/bin/perl test
defined
*main​::DATA
undefined

$ /apps/perl-5.10.0/bin/perl test
defined
*main​::DATA
defined
Segmentation fault

When compiled with debugging, and assert fails

Assertion ((buffer)->sv_flags & 0x00000400) failed​: file "sv.c", line 1741 at test line 5.

Perl Info

Flags:
    category=core
    severity=medium

Site configuration information for perl 5.10.0:

Configured by gbarr at Mon May 11 19:27:00 CDT 2009.

Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
  Platform:
    osname=linux, osvers=2.6.18-92.1.22.el5xen, archname=i686-linux
    uname='linux p1.goingon.net 2.6.18-92.1.22.el5xen #1 smp tue dec 16 13:08:49 est 2008 i686 i686 i386 gnulinux '
    config_args='-der -D prefix=/apps/perl-5.10.0'
    hint=recommended, useposix=true, d_sigaction=define
    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 -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='4.1.2 20071124 (Red Hat 4.1.2-42)', 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 -ldb -ldl -lm -lcrypt -lutil -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=/lib/libc-2.5.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.5'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib'

Locally applied patches:
    


@INC for perl 5.10.0:
    /apps/perl-5.10.0/lib/5.10.0/i686-linux
    /apps/perl-5.10.0/lib/5.10.0
    /apps/perl-5.10.0/lib/site_perl/5.10.0/i686-linux
    /apps/perl-5.10.0/lib/site_perl/5.10.0
    .


Environment for perl 5.10.0:
    HOME=/home/gbarr
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/local/sbin:/usr/local/bin:/home/gbarr/bin:/sbin:/bin:/usr/sbin:/usr/bin
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented May 12, 2009

From @nwc10

On Mon, May 11, 2009 at 08​:59​:20PM -0700, Graham Barr wrote​:

I have not been able to track down the exact cause yet, but the following demonstrates
an change in functionality and a subsequent segfault in 5.10

$ cat test
sub type {
my $r = shift;
my $q = *$r; # defined in 5.10.0, was undef in all prior versions tested
print defined($q) ? "defined" : "undefined","\n";
print "$q\n"; # will segv in Perl_sv_2pv_flags when $r = *DATA{IO}
}

Yes, that's interesting. I think it has to be a bug in 5.8.9 and earlier that
there's this inconsistency​:

$ perl -MDevel​::Peek -le 'print $]; $a = *STDIN{IO}; $b = *$a; print defined $b; print length $b'
5.008008

0

How can something not be defined, yet stringify to "" without warning?

Your testcase pinpoints the cause of the SEGV - it's an unexpected interaction
between this return​:

void
Perl_gv_fullname4(pTHX_ SV *sv, const GV *gv, const char *prefix, bool keepmain)
{
  const char *name;
  STRLEN namelen;
  const HV * const hv = GvSTASH(gv);

  PERL_ARGS_ASSERT_GV_FULLNAME4;

  if (!hv) {
  SvOK_off(sv);
  return;

and this call to it​:

  SvFAKE_off(gv);
  gv_efullname3(buffer, gv, "*");
  SvFLAGS(gv) |= wasfake;

  assert(SvPOK(buffer));

The problem is that the "obvious" fix ends up with just a reversal of the
inconsistent pre-5.10 behaviour, with that sort of typeglob defined, but
warning on stringification.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented May 12, 2009

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

@p5pRT
Copy link
Author

p5pRT commented May 12, 2009

From @gbarr

On May 12, 2009, at 3​:12 PM, Nicholas Clark via RT wrote​:

On Mon, May 11, 2009 at 08​:59​:20PM -0700, Graham Barr wrote​:

I have not been able to track down the exact cause yet, but the
following demonstrates
an change in functionality and a subsequent segfault in 5.10

$ cat test
sub type {
my $r = shift;
my $q = *$r; # defined in 5.10.0, was undef in all prior
versions tested
print defined($q) ? "defined" : "undefined","\n";
print "$q\n"; # will segv in Perl_sv_2pv_flags when $r = *DATA{IO}
}

Yes, that's interesting. I think it has to be a bug in 5.8.9 and
earlier that
there's this inconsistency​:

$ perl -MDevel​::Peek -le 'print $]; $a = *STDIN{IO}; $b = *$a; print
defined $b; print length $b'
5.008008

0

How can something not be defined, yet stringify to "" without warning?

because you did not add -w to the command line

adding -w I se the warning as far back as

/apps/perl-5.4.5/bin/perl5.00405
5.00405

Use of uninitialized value at -e line 1.
0

However note that a Dump($b) is different in blead then 5.8.9

blead​:

SV = PVGV(0x89be768) at 0x89ad580
  REFCNT = 1
  FLAGS = (FAKE,MULTI,IMPORTALL)
  NAME = ""
  NAMELEN = 0
  GvSTASH = 0x0
  GP = 0x89b0e28

5.8.9​:

SV = PVGV(0x90caa3c) at 0x90b3b7c
  REFCNT = 1
  FLAGS = (GMG,SMG,FAKE,MULTI,IMPORTALL)
  IV = 0
  NV = 0
  PV = 0
  MAGIC = 0x90c78a0
  MG_VIRTUAL = &PL_vtbl_glob
  MG_TYPE = PERL_MAGIC_glob(*)
  MG_OBJ = 0x90b3b7c
  NAME = ""
  NAMELEN = 0
  GvSTASH = 0x0
  GP = 0x90c8c90

I have not followed closely enough to know if that dropping of magic
is intentional

Graham.

Your testcase pinpoints the cause of the SEGV - it's an unexpected
interaction
between this return​:

void
Perl_gv_fullname4(pTHX_ SV *sv, const GV *gv, const char *prefix,
bool keepmain)

{
const char *name;
STRLEN namelen;
const HV * const hv = GvSTASH(gv);

PERL_ARGS_ASSERT_GV_FULLNAME4;

if (!hv) {
SvOK_off(sv);
return;

and this call to it​:

SvFAKE_off(gv);
gv_efullname3(buffer, gv, "*");
SvFLAGS(gv) |= wasfake;

assert(SvPOK(buffer));

The problem is that the "obvious" fix ends up with just a reversal
of the
inconsistent pre-5.10 behaviour, with that sort of typeglob defined,
but
warning on stringification.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented May 12, 2009

From @nwc10

On Tue, May 12, 2009 at 04​:24​:28PM -0500, Graham Barr wrote​:

I have not followed closely enough to know if that dropping of magic
is intentional

Totally intentional. 24+ bytes used per typeglob (hence per sub or method)
were used for magic, the sole purpose of which was to deal with stringifying
the typeglob and assigning strings to it. With several thousand typeglobs
created by a small program that directly pulls in a moderate number of
modules, it soon adds up.

http​://perl5.git.perl.org/perl.git/commit/180488f8452e93d2afa0f62b189be1cc9ac6
http​://perl5.git.perl.org/perl.git/commit/c0c446747ad6c5bde53bc8415ca16ef77f63

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented May 13, 2009

From @gbarr

On May 12, 2009, at 5​:41 PM, Nicholas Clark wrote​:

On Tue, May 12, 2009 at 04​:24​:28PM -0500, Graham Barr wrote​:

I have not followed closely enough to know if that dropping of magic
is intentional

Totally intentional. 24+ bytes used per typeglob (hence per sub or
method)
were used for magic, the sole purpose of which was to deal with
stringifying
the typeglob and assigning strings to it. With several thousand
typeglobs
created by a small program that directly pulls in a moderate number of
modules, it soon adds up.

Sure, OK. As I said I had not been following closely.

I have done a little more digging

It seems to me that the root of this issue is that
in pp_rv2gv where SvTYPE(sv) == SVt_PVIO a call is
made to

  gv_init(gv, 0, "", 0, 0);

after this, in blead SvOK(gv) returns true, but in 5.8.9 SvOK(gv) is
false

this is why defined($y) is true on 5.10.0 but false on 5.8.x and before

While not a fix, because lib/Benchmark and op/tie fail, I put in a
call to
SvOK_off(sv); at the end of that block in 5.10.0 code.

The result was that the following matches 5.8.x and before

$ ./perl -wle '$x = *STDIN{IO}; $y = *$x; print "$x"; print "$y"'
IO​::Handle=IO(0x9704eb8)
Use of uninitialized value $y in string at -e line 1.

Graham.

@p5pRT
Copy link
Author

p5pRT commented May 13, 2009

From @gbarr

On May 13, 2009, at 12​:52 AM, Graham Barr wrote​:

On May 12, 2009, at 5​:41 PM, Nicholas Clark wrote​:

On Tue, May 12, 2009 at 04​:24​:28PM -0500, Graham Barr wrote​:

I have not followed closely enough to know if that dropping of magic
is intentional

Totally intentional. 24+ bytes used per typeglob (hence per sub or
method)
were used for magic, the sole purpose of which was to deal with
stringifying
the typeglob and assigning strings to it. With several thousand
typeglobs
created by a small program that directly pulls in a moderate number
of
modules, it soon adds up.

Sure, OK. As I said I had not been following closely.

I have done a little more digging

It seems to me that the root of this issue is that
in pp_rv2gv where SvTYPE(sv) == SVt_PVIO a call is
made to

gv_init(gv, 0, "", 0, 0);

after this, in blead SvOK(gv) returns true, but in 5.8.9 SvOK(gv) is
false

this is why defined($y) is true on 5.10.0 but false on 5.8.x and
before

While not a fix, because lib/Benchmark and op/tie fail, I put in a
call to
SvOK_off(sv); at the end of that block in 5.10.0 code.

The result was that the following matches 5.8.x and before

$ ./perl -wle '$x = *STDIN{IO}; $y = *$x; print "$x"; print "$y"'
IO​::Handle=IO(0x9704eb8)
Use of uninitialized value $y in string at -e line 1.

However, the following is still different

$ perl5.8.9 -wle '$x = *STDERR{IO}; $y = *$x; print "$x"; print
fileno($y); print "$y"'
IO​::Handle=IO(0x84898c4)
2
Use of uninitialized value in string at -e line 1.

$ ./perl -wle '$x = *STDERR{IO}; $y = *$x; print "$x"; print
fileno($y); print "$y"'
IO​::Handle=IO(0x8168f88)
Use of uninitialized value $y in print at -e line 1.

Use of uninitialized value $y in string at -e line 1.

So $y was undefined but still valid for use as a filehandle

(time to seep)
Graham.

@p5pRT
Copy link
Author

p5pRT commented May 28, 2009

From @nwc10

Dave notes​:

Fine in 5.8.8,5.8.9; assert fails in 5.10.0, maint, blead.

Nick notes​:

I have some idea of what's going on here.

@p5pRT
Copy link
Author

p5pRT commented Jun 1, 2009

From p5p@spam.wizbit.be

Binary searches​:

There appears to be two changes​:

----Program----
#!/usr/bin/perl

sub type {
  my $r = shift;
  my $q = *$r; # defined in 5.10.0, was undef in all prior
versions tested
  print defined($q) ? "defined" : "undefined","\n";
  print "$q\n"; # will segv in Perl_sv_2pv_flags when $r =
*DATA{IO}
}

type(*DATA);
type(*DATA{IO}); # will segv in Perl_sv_2pv_flags
<DATA>; # force DATA to be created

----Output of .../pPSPFBH/perl-5.9.3@​27276/bin/perl----
defined
*main​::DATA
undefined

----EOF ($?='0')----
----Output of .../pcY8DIw/perl-5.9.3@​27278/bin/perl----
defined
*main​::DATA
defined

----EOF ($?='0')----
Need a perl between 27276 and 27278

http​://public.activestate.com/cgi-bin/perlbrowse/p/27278
Change 27278 by nicholas@​nicholas-saigo on 2006/02/23 11​:11​:12

  Remove get magic from typeglobs. This means that PVGVs holding
  typeglobs never need to use SvPVX. This comes at price -
typeglobs
  were using magic get for their stringificiation, and to pass
SvOK(),
  so need to make typeglobs SvOK by default (by sucking
SVp_SCREAM into
  SVf_OK - it's the only flag left), tweak SvSCREAM() to also
check
  SVp_POK, and teach sv_2[inpu]v how to convert globs.
  However, it should free up SvPVX for the next part of the plan
to
  pointer indirections, and therefore CPU cache pressure.

----Program----
#!/usr/bin/perl

sub type {
  my $r = shift;
  my $q = *$r; # defined in 5.10.0, was undef in all prior
versions tested
  print defined($q) ? "defined" : "undefined","\n";
  print "$q\n"; # will segv in Perl_sv_2pv_flags when $r =
*DATA{IO}
}

type(*DATA);
type(*DATA{IO}); # will segv in Perl_sv_2pv_flags
<DATA>; # force DATA to be created

----Output of .../pP16HNv/perl-5.9.3@​27802/bin/perl----
defined
*main​::DATA
defined

----EOF ($?='0')----
----Output of .../pZSoT5g/perl-5.9.3@​27803/bin/perl----

----EOF ($?='11')----
Need a perl between 27802 and 27803

http​://public.activestate.com/cgi-bin/perlbrowse/p/27803
Change 27803 by nicholas@​nicholas-saigo on 2006/04/14 16​:43​:03

  S_glob_2inpuv() did not check if lenp was NULL. Oops.

(all perls compiled without -DDEBUGGING)

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2010

From @iabyn

On Wed, May 13, 2009 at 01​:13​:12AM -0500, Graham Barr wrote​:

On May 13, 2009, at 12​:52 AM, Graham Barr wrote​:

On May 12, 2009, at 5​:41 PM, Nicholas Clark wrote​:

On Tue, May 12, 2009 at 04​:24​:28PM -0500, Graham Barr wrote​:

I have not followed closely enough to know if that dropping of magic
is intentional

Totally intentional. 24+ bytes used per typeglob (hence per sub or
method)
were used for magic, the sole purpose of which was to deal with
stringifying
the typeglob and assigning strings to it. With several thousand
typeglobs
created by a small program that directly pulls in a moderate number
of
modules, it soon adds up.

Sure, OK. As I said I had not been following closely.

I have done a little more digging

It seems to me that the root of this issue is that
in pp_rv2gv where SvTYPE(sv) == SVt_PVIO a call is
made to

gv_init(gv, 0, "", 0, 0);

after this, in blead SvOK(gv) returns true, but in 5.8.9 SvOK(gv) is
false

this is why defined($y) is true on 5.10.0 but false on 5.8.x and
before

While not a fix, because lib/Benchmark and op/tie fail, I put in a
call to
SvOK_off(sv); at the end of that block in 5.10.0 code.

The result was that the following matches 5.8.x and before

$ ./perl -wle '$x = *STDIN{IO}; $y = *$x; print "$x"; print "$y"'
IO​::Handle=IO(0x9704eb8)
Use of uninitialized value $y in string at -e line 1.

However, the following is still different

$ perl5.8.9 -wle '$x = *STDERR{IO}; $y = *$x; print "$x"; print
fileno($y); print "$y"'
IO​::Handle=IO(0x84898c4)
2
Use of uninitialized value in string at -e line 1.

$ ./perl -wle '$x = *STDERR{IO}; $y = *$x; print "$x"; print fileno($y);
print "$y"'
IO​::Handle=IO(0x8168f88)
Use of uninitialized value $y in print at -e line 1.

Use of uninitialized value $y in string at -e line 1.

So $y was undefined but still valid for use as a filehandle

(time to seep)
Graham.

I've applied the following commit, which I hope makes for sensible
behaviour​:

commit 1809c94
Author​: David Mitchell <davem@​iabyn.com>
AuthorDate​: Tue Jan 12 00​:14​:41 2010 +0000
Commit​: David Mitchell <davem@​iabyn.com>
CommitDate​: Tue Jan 12 00​:26​:59 2010 +0000

  fix for [perl #65582] anon globs segfaulting
 
  The following code has had differing behaviours​:
 
  my $io_ref = *STDOUT{IO};
  my $glob = *$io_ref;
 
  defined($glob) "$glob"
  -------------- -------
  5.8.8 false "" with uninit warning
  5.10.0 true (coredump)
  this commit true ""
 
  $glob is essentially an anonymous typeglob (no NAME, EGV or GvSTASH).
  It shouldn't register as undefined since it's clearly a valid GV with a
  valid IO slot; Stringifying to "" seems to be the right thing, and not
  warning seems right too, since its not undef.

Affected files ...
 
  M sv.c
  M t/op/gv.t

Differences ...

Inline Patch
diff --git a/sv.c b/sv.c
index 063dd19..4e80e18 100644
--- a/sv.c
+++ b/sv.c
@@ -2986,11 +2986,17 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags
 	    gv_efullname3(buffer, gv, "*");
 	    SvFLAGS(gv) |= wasfake;
 
-	    assert(SvPOK(buffer));
-	    if (lp) {
-		*lp = SvCUR(buffer);
+	    if (SvPOK(buffer)) {
+		if (lp) {
+		    *lp = SvCUR(buffer);
+		}
+		return SvPVX(buffer);
+	    }
+	    else {
+		if (lp)
+		    *lp = 0;
+		return (char *)"";
 	    }
-	    return SvPVX(buffer);
 	}
 
 	if (lp)
diff --git a/t/op/gv.t b/t/op/gv.t
index 1b705ef..72787c4 100644
--- a/t/op/gv.t
+++ b/t/op/gv.t
@@ -12,7 +12,7 @@ BEGIN {
 use warnings;
 
 require './test.pl';
-plan( tests => 178 );
+plan( tests => 181 );
 
 # type coersion on assignment
 $foo = 'foo';
@@ -560,6 +560,27 @@ foreach my $type (qw(integer number string)) {
 	  "with the correct error message");
 }
 
+# RT #60954 anonymous glob should be defined, and not coredump when
+# stringified. The behaviours are:
+#
+#        defined($glob)    "$glob"
+# 5.8.8     false           "" with uninit warning
+# 5.10.0    true            (coredump)
+# 5.12.0    true            ""
+
+{
+    my $io_ref = *STDOUT{IO};
+    my $glob = *$io_ref;
+    ok(defined $glob, "RT #60954 anon glob should be defined");
+
+    my $warn = '';
+    local $SIG{__WARN__} = sub { $warn = $_[0] };
+    use warnings;
+    my $str = "$glob";
+    is($warn, '', "RT #60954 anon glob stringification shouln't warn");
+    is($str,  '', "RT #60954 anon glob stringification should be empty");
+}
+
 __END__
 Perl
 Rules


-- 

Red sky at night - gerroff my land!
Red sky at morning - gerroff my land!
  -- old farmers' sayings #14

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2010

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