summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2011-12-17 19:22:51 -0800
committerFather Chrysostomos <sprout@cpan.org>2011-12-17 23:19:03 -0800
commit69930016894689da4e8234c429d5ef26b311e7ec (patch)
tree850166ef2a979490826efdb5cfd42a12646854c4 /sv.c
parentd6ec5f13c8daa49c1550a4fa54a8410f913203fd (diff)
downloadperl-69930016894689da4e8234c429d5ef26b311e7ec.tar.gz
[perl #97988] Nullify PL_last_in_gv when unglobbed
Code like this can cause PL_last_in_gv to point to a coercible glob: $f{g} = *STDOUT; readline $f{g}; If $f{g} is then modified such that it is no longer a glob, PL_last_in_gv ends up pointing to a non-glob: $f{g} = 3; If $f{g} is freed now, the PL_last_in_gv-nulling code in sv_clear will be skipped, as it only applies to globs. undef %f; # now PL_last_in_gv points to a freed scalar The resulting freed scalar can be reused by another handle, *{"foom"} = *other; causing tell() with no arguments to return the position on *other, even though *other was no the last handle read from. This commit fixes it by nulling PL_last_in_gv when a coercible glob is coerced.
Diffstat (limited to 'sv.c')
-rw-r--r--sv.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/sv.c b/sv.c
index dec1794d6f..fc8ee86b10 100644
--- a/sv.c
+++ b/sv.c
@@ -6116,6 +6116,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
/* FIXME. There are probably more unreferenced pointers to SVs
* in the interpreter struct that we should check and tidy in
* a similar fashion to this: */
+ /* See also S_sv_unglob, which does the same thing. */
if ((const GV *)sv == PL_last_in_gv)
PL_last_in_gv = NULL;
case SVt_PVMG:
@@ -9518,6 +9519,9 @@ S_sv_unglob(pTHX_ SV *const sv, U32 flags)
set operation as merely an internal storage change. */
if (flags & SV_COW_DROP_PV) SvOK_off(sv);
else sv_setsv_flags(sv, temp, 0);
+
+ if ((const GV *)sv == PL_last_in_gv)
+ PL_last_in_gv = NULL;
}
/*