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

Globs in tied scalars can be reified if STORE dies #10626

Closed
p5pRT opened this issue Sep 12, 2010 · 3 comments
Closed

Globs in tied scalars can be reified if STORE dies #10626

p5pRT opened this issue Sep 12, 2010 · 3 comments
Labels

Comments

@p5pRT
Copy link
Collaborator

@p5pRT p5pRT commented Sep 12, 2010

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

Searchable as RT77812$

@p5pRT
Copy link
Collaborator Author

@p5pRT p5pRT commented Sep 12, 2010

From @cpansprout

Another regression in 5.13, this one caused by 0fe688f. Some of these patch authors are clueless!

#!perl -l
sub TIESCALAR{bless[]}
sub STORE{ die "No!"}
sub FETCH{ *foo }
tie $a, "";
() = $a; # do a fetch
eval { *$a = sub{} };
# From this point on $a holds a glob without the FAKE flag.
eval { $a = undef };
untie $a;
$a = "bar";
print $a;

In 5.12 and earlier this prints "bar".

In 5.13.4 the penultimate line dies with "No!", because it’s still tied.

This is because of the order of these statements in pp_sassign is wrong​:

  /* Allow glob assignments like *$x = ..., which, when the glob has a
  SVf_FAKE flag, cannot be distinguished from $x = ... without looking
  at the op tree. */
  if( SvTYPE(right) == SVt_PVGV && cBINOP->op_last->op_type == OP_RV2GV
  && (wasfake = SvFLAGS(right) & SVf_FAKE) )
  SvFLAGS(right) &= ~SVf_FAKE;
  SvSetMagicSV(right, left);
  if(wasfake) SvFLAGS(right) |= SVf_FAKE;

Turning the fake flag back on should happen before magic is called.

If bug #77810 is fixed, we can simply revert the patch that caused this, and put the appropriate logic in one place.

This same bug also affects a patch I wrote for #77508 (list assignment to dereferenced fake glob).

Here is the example script again, with more explanatory notes​:

#!perl -l
sub TIESCALAR{bless[]}
sub STORE{ die "No you don​::t!"}
sub FETCH{ *foo }
tie $a, "";
() = $a; # do a fetch

# Now the $a scalar holds a copy of *foo; i.e., a PVGV with the FAKE flag
# on, indicating that this is not really a glob, but just a scalar holding
# a copy of one.

eval { *$a = sub{} };
# pp_sassign (the function implementing the = operator) turns off the FAKE
# flag temporarily before assignment, because of the * (rv2gv) on the
# lefthand side.
# Set-magic (called right after the assignment) dies (in the STORE routine
# above) before the FAKE flag is turned back on. As a result, it stays off,
# so what we now have looks exactly like a glob in the symbol table.

eval { $a = undef };
# This is a workaround for a bug still present in blead. untie() won’t
# untie a scalar if it sees a glob, whether FAKE or not.
# We try to assign undef to $a, so that the $a scalar will itself hold
# undef, even if STORE dies. But, since the FAKE flag is gone, we are
# asigning to a ‘real’ glob. Assigning undef to a glob does nothing (except
# warn).

# Untie the variable. Since there is a glob, it tries to untie the IO slot,
# which doesn’t exist, so nothing happens.
untie $a;

# We are supposedly assigning "bar" to an innocent $a variable, but in
# truth we are making the glob in $a an alias to *bar.
$a = "bar";
# That assignment triggers set-magic, which calls STORE, which dies.

# We never get here.

print $a;

At this point (suppose all the above was in an eval), even if the FETCH routine starts returning undef, it will always be the glob that is returned to the calling code.

This would make it rather difficult to implement read-only aliases using ties.

@p5pRT
Copy link
Collaborator Author

@p5pRT p5pRT commented Oct 25, 2010

From @cpansprout

On Sun Sep 12 12​:41​:24 2010, sprout wrote​:

#!perl -l
sub TIESCALAR{bless[]}
sub STORE{ die "No!"}
sub FETCH{ *foo }
tie $a, "";
() = $a; # do a fetch
eval { *$a = sub{} };
# From this point on $a holds a glob without the FAKE flag.
eval { $a = undef };
untie $a;
$a = "bar";
print $a;

Fixed in 2acc331.
Tests added in 0936ef8.

@p5pRT
Copy link
Collaborator Author

@p5pRT p5pRT commented Oct 25, 2010

@cpansprout - Status changed from 'new' to 'resolved'

@p5pRT p5pRT closed this Oct 25, 2010
@p5pRT p5pRT added the Severity Low label Oct 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant
You can’t perform that action at this time.