develooper Front page | perl.perl5.porters | Postings from March 2006

fanciful: local implemented through "masking containers"

From:
David Nicol
Date:
March 30, 2006 10:49
Subject:
fanciful: local implemented through "masking containers"
Message ID:
934f64a20603301049v5ecd8b6fjdf3932c04a006fea@mail.gmail.com
On 3/30/06, Nicholas Clark <nick@ccl4.org> wrote:
> On Wed, Mar 29, 2006 at 05:33:27PM -0600, David Nicol wrote:
> > 1:  a new data structure, the "masking hash", that has an attribute
> > that says what other (masking or non-masking) hash to look in when looking for a
> > nonexistent key

> > Given masking-hash, C<local> could be rewritten using maskinghash instead pf
> > the current implementation and MJD's scalar localization tieing
> > exploits would all
> > fail.
>
> I don't think that this would work, as it only affects where the lookup of
> a particular name takes you. local needs to be able to localise specific
> value containers directly, rather than just the name. For example, this works:
>
> $ perl -lwe 'local $ARGV[1] = "Boo!"; print "@ARGV"' a b c
> a Boo! c
>
> Nicholas Clark

Right.  Masking arrays and masked scalars (Hi ho, Silver!) would need
to exist too.  Local would determine the final container and mask it.

In that one-liner, *ARGV->array would get replaced with a maskable
array with its parent attribute set to the old *ARGV->array and ->[1]
set to the string.  At the end of the scope, *ARGV->array would be
replaced with the old value.

This is how I thought local worked, before I found out how local really works,
which is simpler but involves hidden FETCH and STORE operations.

Masking-local would avoid the fetching and storing on the hidden values, since
the container is getting changed instead of the value, at the cost of having
to check for a mask hit and then traverse parent pointers on every access  to
non-masked data.

array masks would usually be sparse, so using the same mechanism for
storing the mask as with a masked hash would make sense.

The whole idea would be a net efficiency loss, but it would avoid
the "remotely tied global localized with a sigyll exploit."  But no
better than always localizing globs when you must localize does.

bash-3.00# cat -n localploit
     1
     2  use Carp;
     3  use Tie::Array;
     4
     5  @ar=qw/a b c/;
     6  local $ar[1]="Boo!";
     7  print"@ar";
     8
     9  BEGIN{
    10   push@X::ISA,"Tie::StdArray";
    11   tie@ar,"X";
    12   sub X::FETCH{confess "ha ha ha"}
    13  }
    14
    15
bash-3.00# perl localploit
ha ha ha at localploit line 12
        X::FETCH('X=ARRAY(0x8098948)', 1) called at localploit line 6

bash-3.00# cat -n localploit_defeated
     1
     2  use Carp;
     3  use Tie::Array;
     4
     5  @ar=qw/a b c/;
     6  # local *ar[1]="Boo!"; ### syntax error
     7  local *ar=[qw/a Boo! c/];
     8  print"@ar\n";
     9
    10  BEGIN{
    11   push@X::ISA,"Tie::StdArray";
    12   tie@ar,"X";
    13   sub X::FETCH{confess "ha ha ha"}
    14  }
    15
    16
bash-3.00# perl localploit_defeated
a Boo! c

I guess a pure-perl masked array might get used like

      @ar=qw/a b c/;
      # INSTEAD OF:  local $ar[1]="Boo!";
      {
         tie my @ar, "Tie::MaskedArray", parent => \@ar, mask => { 1 => "Boo!"};
         print"@ar";
      }
      print "@ar\n";

Anyone want me to add such a thing to my CPAN directory full of stupid
tie tricks?

--
David L Nicol
"the opportunity of making good with a hard undertaking - one that had
been held impossible of realization - would be a strong asset to the
firm's reputation" -- William Russell, 1860
http://cronos.advenge.com/pc/americana/PonyExpress/p15.html



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About