Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > eval()ing a pattern substitution under 'use strict' and lexical scope

Reply
Thread Tools

eval()ing a pattern substitution under 'use strict' and lexical scope

 
 
bernd
Guest
Posts: n/a
 
      01-25-2012
Hi folks,

I have two perl progs, both expected to do the same, eval()ing a
pattern substitution expression using variables for the substitution
pattern and the replacement (to be used in a subroutine later on).

The first prog uses 'use strict' and lexical variables and looks like
this:

#!/usr/bin/perl -w

use strict;
my $old = 'test this one';
my $pat = 'this';
my $repl = 'that';
my $mods = '';
my $new;

eval('($new = $old) =~ s/$pat/$repl/ee . $mods');

print $new . "\n";

($mods can take a string containing one or more modifiers (like 'g')
to the s/// operator).

The output is

Use of uninitialized value in substitution iterator at (eval 1) line
1.
test one

In the second version I dispensed with 'use strict' and lexical
variables:

#!/usr/bin/perl -w

$old = 'test this one';
$pat = 'this';
$repl = 'that';
$mods = '';

eval('($new = $old) =~ s/$pat/$repl/ee . $mods');

print $new . "\n";

And the output is as expected:

Name "main::repl" used only once: possible typo at ./subst_nostrict.pl
line 5.
Name "main::new" used only once: possible typo at ./subst_nostrict.pl
line 10.
Name "main:ld" used only once: possible typo at ./subst_nostrict.pl
line 3.
Name "main:at" used only once: possible typo at ./subst_nostrict.pl
line 4.
Name "main::mods" used only once: possible typo at ./subst_nostrict.pl
line 6.
Unquoted string "that" may clash with future reserved word at (eval 2)
line 2.
test that one

Unfortunately, in the project in which the eval-stuff should be
integrated I have to use 'strict' and lexical scoping.

Can somebody explain the differences in the output and how I could
reach the desired output 'test that one'?

TIA


Bernd
 
Reply With Quote
 
 
 
 
bernd
Guest
Posts: n/a
 
      01-26-2012
Hi Ben,

thanks for the elaborate explanations.

> Did you mean the '. $mods' to come outside the string?


Exactly, and in the original code it was like that. I changed this to
the statement posted during testing and "forgot" to change it back
since it seemed to have no effect anyway (but this was an erroneous
assumption, caused by the fact that $mods was the empty string during
all of these tests). So, the outer eval was intended to "glue" the
modifier string to the s///ee expression, what it actually does if
$mods is outside of the single quoted string.

My intention with this code was to use it in a subroutine which
executes pattern substitution with $pat and $repl read from a
configuration file. The double evaluation of the substitution operator
is strictly necessary since it could be possible that the replacement
read from the configuration file could contain backreference variables
($1, $2, ...).

So, what did I do after reading Your post?:

I changed back the eval-statement as mentioned above, introduced the
subroutine, in which I placed the code, with 'no use "subs"' (so that
'use "vars"' is still in effect and lexicals are forced) and switched
off warnings for the statement containing the pattern substitution
('no warnings'/'use warnings').

> What if someone gives
> you a $pat of


> '//; system "rm -rf /"; s/'


>?


Hm. The only users who could do something like this would be able to
execute 'rm -rf' on the UNIX command line anyway (and then they would
mess around with their own workplace ). If a black hat from outside
would be able to do this we would have a much bigger problem with our
it-security and therefore this particular thread is neglectable. :->>

Cheers


Bernd

 
Reply With Quote
 
 
 
 
bernd
Guest
Posts: n/a
 
      01-26-2012
On Jan 25, 8:33*pm, Ben Morrow <b...@morrow.me.uk> wrote:
> Quoth bernd <bew...@gmx.net>:
>
>
>
> > I have two perl progs, both expected to do the same, eval()ing a
> > pattern substitution expression using variables for the substitution
> > pattern and the replacement (to be used in a subroutine later on).

>
> I don't know what you're trying to do, but I'm *certain* there's a
> better way of doing it. Maybe if you explained why you're doing this
> someone could suggest a less-insane alternative.
>
>
>
>
>
>
>
>
>
> > The first prog uses 'use strict' and lexical variables and looks like
> > this:

>
> > #!/usr/bin/perl -w

>
> > use strict;
> > my $old = 'test this one';
> > my $pat = 'this';
> > my $repl = 'that';
> > my $mods = '';
> > my $new;

>
> > eval('($new = $old) =~ s/$pat/$repl/ee . $mods');

>
> > print $new . "\n";

>
> > ($mods can take a string containing one or more modifiers (like 'g')
> > to the s/// operator).

>
> > The output is

>
> > Use of uninitialized value in substitution iterator at (eval 1) line
> > 1.
> > test *one

>
> OK, you have multiple levels of 'eval' here, so we need to step through
> them carefully to understand what's going on.
>
> First we eval the single-quoted string
>
> * * '($new = $old) =~ s/$pat/$repl/ee . $mods'
>
> Since this is single-quoted there's no interpolation, so the eval has
> exactly the same effect as writing the code out normally. (Did you mean
> the '. $mods' to come outside the string?) So now we are executing
>
> * * ($new = $old) =~ s/$pat/$repl/ee . $mods
>
> s///ee starts by interpolating $pat on the LHS, so we're searching for
>
> * * /this/
>
> (as a regular expression). For each instance it finds, it runs
>
> * * eval "$repl"
>
> (note the double-quotes, they're important). This is equivalent to
>
> * * eval 'that'
>
> which is equivalent to
>
> * * that;
>
> as a standalone Perl statement.
>
> Since this is all under 'use strict "subs"', and there is no 'sub that'
> in scope, this throws a 'Bareword "that" not allowed while "strict subs"
> in use' error. The eval catches the error, stuffs it into $@, and
> returns undef. The s///ee takes the undef and inserts it into $new in
> place of the 'this' it found, which gives an 'uninitialized value'
> warning.
>
> > In the second version I dispensed with 'use strict' and lexical
> > variables:

>
> The reason this 'worked' is not because you stopped using 'strict
> "refs"' and lexicals, but because you stopped using 'strict "subs"'.
>
> Perl 4 had a completely bizarre bit of behaviour: if it saw an
> expression like
>
> * * that;
>
> and there was no 'sub that' defined, it assumed you had meant
>
> * * 'that';
>
> and carried right on. This means that once the chain of evals above gets
> that far, it simply turns the bareword back into a string (without
> complaining) and you get the substitution you were expecting.
>
> Now, how much of that did you want? I suspect you will get what you
> meant if you just remove the 'ee' (and put the $mods outside the
> string), but the whole thing is enormously unsafe. What if someone gives
> you a $pat of
>
> * * '//; system "rm -rf /"; s/'
>
> ?
>
> Ben


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Lexical scope vs. dynamic scope Xah Lee Java 0 02-26-2009 10:08 AM
python: lexical or dynamic scope? globalrev Python 3 05-14-2008 01:28 PM
Lexical scope and looping enaeher@gmail.com Javascript 6 04-06-2007 06:36 PM
Problem with Lexical Scope jslowery@gmail.com Python 18 12-17-2005 10:53 AM
Lexical Scope Matt Knepley Python 3 10-30-2003 06:45 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57