Skip to content

Commit

Permalink
Globs that are in symbol table can be un-globbed
Browse files Browse the repository at this point in the history
If a symbol table entry is undefined when a glob is assigned into it, it
gets a FAKE flag which makes it possible to be downgraded when non-glob
is subsequently assigned into it. It doesn't really matter, until we
decide to localize it -- it wouldn't be possible to restore its GP upon
context return if it changed type, therefore we must not do that.

This patch turns off FAKE flag when localizing a GV and restores it when
the context is left. A test case is included.
  • Loading branch information
lkundrak authored and rgs committed Apr 26, 2010
1 parent 01146ba commit b9e00b7
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 7 deletions.
15 changes: 12 additions & 3 deletions scope.c
Expand Up @@ -281,7 +281,15 @@ Perl_save_gp(pTHX_ GV *gv, I32 empty)

PERL_ARGS_ASSERT_SAVE_GP;

save_pushptrptr(SvREFCNT_inc(gv), GvGP(gv), SAVEt_GP);
SSCHECK(4);
SSPUSHINT(SvFAKE(gv));
SSPUSHPTR(GvGP(gv));
SSPUSHPTR(SvREFCNT_inc(gv));
SSPUSHINT(SAVEt_GP);

/* Don't let the localized GV coerce into non-glob, otherwise we would
* not be able to restore GP upon leave from context if that happened */
SvFAKE_off(gv);

if (empty) {
GP *gp = Perl_newGP(aTHX_ gv);
Expand Down Expand Up @@ -812,10 +820,11 @@ Perl_leave_scope(pTHX_ I32 base)
*(AV**)ptr = MUTABLE_AV(SSPOPPTR);
break;
case SAVEt_GP: /* scalar reference */
ptr = SSPOPPTR;
gv = MUTABLE_GV(SSPOPPTR);
gp_free(gv);
GvGP(gv) = (GP*)ptr;
GvGP(gv) = (GP*)SSPOPPTR;
if (SSPOPINT)
SvFAKE_on(gv);
/* putting a method back into circulation ("local")*/
if (GvCVu(gv) && (hv=GvSTASH(gv)) && HvNAME_get(hv))
mro_method_changed_in(hv);
Expand Down
7 changes: 4 additions & 3 deletions sv.c
Expand Up @@ -11581,12 +11581,13 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
TOPPTR(nss,ix) = pv_dup(c);
break;
case SAVEt_GP: /* scalar reference */
gv = (const GV *)POPPTR(ss,ix);
TOPPTR(nss,ix) = gv_dup_inc(gv, param);
gp = (GP*)POPPTR(ss,ix);
TOPPTR(nss,ix) = gp = gp_dup(gp, param);
(void)GpREFCNT_inc(gp);
gv = (const GV *)POPPTR(ss,ix);
TOPPTR(nss,ix) = gv_dup_inc(gv, param);
break;
TOPINT(nss,ix) = POPINT(ss,ix);
break;
case SAVEt_FREEOP:
ptr = POPPTR(ss,ix);
if (ptr && (((OP*)ptr)->op_private & OPpREFCOUNTED)) {
Expand Down
11 changes: 10 additions & 1 deletion t/op/gv.t
Expand Up @@ -12,7 +12,7 @@ BEGIN {
use warnings;

require './test.pl';
plan( tests => 188 );
plan( tests => 191 );

# type coersion on assignment
$foo = 'foo';
Expand Down Expand Up @@ -614,6 +614,15 @@ ok(exists($RT72740a::{s4}), "RT72740a::s4 exists");
is(RT72740a::s1(), "RT72740b::s2", "RT72740::s1 parsed correctly");
is(RT72740a::s3(), "RT72740b::s4", "RT72740::s3 parsed correctly");

# [perl #71686] Globs that are in symbol table can be un-globbed
$sym = undef;
$::{fake} = *sym;
is (eval 'local *::fake = \"chuck"; $fake', 'chuck',
"Localized glob didn't coerce into a RV");
is ($@, '', "Can localize FAKE glob that's present in stash");
is (scalar $::{fake}, "*main::sym",
"Localized FAKE glob's value was correctly restored");

__END__
Perl
Rules
Expand Down

0 comments on commit b9e00b7

Please sign in to comment.