diff options
author | David Mitchell <davem@iabyn.com> | 2010-03-30 15:03:50 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2010-03-30 15:03:50 +0100 |
commit | 099be4f1d597471eb719c9a344b7c1b55e11ba24 (patch) | |
tree | 46ddeb749d35c52c3df9d34f54e7200aef8ddbcf /pp_sys.c | |
parent | 447ee1343739cf8e34c4ff1ba9b30eae75c3f1ab (diff) | |
download | perl-099be4f1d597471eb719c9a344b7c1b55e11ba24.tar.gz |
PL_defoutgv isn't always a GV.
Nasty code like the following results in PL_defoutgv not pointing
to a valid GV:
my $x = *STDERR; select($x); $x = 1;
This causes all sorts of SEGVs when PL_defoutgv is subsequently accessed,
because most code assumes that it has a valid gv_gp pointer. It also
turns out that PL_defoutgv is under-tested; for example, temporarily
hacking pp_close to make an arg-less close() croak didn't cause any
minitest failures.
Add a new test file that does some basic testing of a bad PL_defoutgv,
and fix all the obvious badness in accessing it.
This also fixes #20727, which although ostensibly a tie bug, was due to
PL_defoutgv pointing to a tiedelem scalar, and fun like that described
above happening.
Diffstat (limited to 'pp_sys.c')
-rw-r--r-- | pp_sys.c | 6 |
1 files changed, 3 insertions, 3 deletions
@@ -1170,11 +1170,11 @@ PP(pp_select) dVAR; dSP; dTARGET; HV *hv; GV * const newdefout = (PL_op->op_private > 0) ? (MUTABLE_GV(POPs)) : NULL; - GV * egv = GvEGV(PL_defoutgv); + GV * egv = GvEGVx(PL_defoutgv); if (!egv) egv = PL_defoutgv; - hv = GvSTASH(egv); + hv = isGV_with_GP(egv) ? GvSTASH(egv) : NULL; if (! hv) XPUSHs(&PL_sv_undef); else { @@ -2017,7 +2017,7 @@ PP(pp_eof) if (MAXARG) gv = PL_last_in_gv = MUTABLE_GV(POPs); /* eof(FH) */ else if (PL_op->op_flags & OPf_SPECIAL) - gv = PL_last_in_gv = GvEGV(PL_argvgv); /* eof() - ARGV magic */ + gv = PL_last_in_gv = GvEGVx(PL_argvgv); /* eof() - ARGV magic */ else gv = PL_last_in_gv; /* eof */ |