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

Discussion in 'Perl Misc' started by bernd, Jan 25, 2012.

  1. bernd

    bernd Guest

    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::eek:ld" used only once: possible typo at ./subst_nostrict.pl
    line 3.
    Name "main::pat" 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
     
    bernd, Jan 25, 2012
    #1
    1. Advertising

  2. bernd

    bernd Guest

    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
     
    bernd, Jan 26, 2012
    #2
    1. Advertising

  3. bernd

    bernd Guest

    On Jan 25, 8:33 pm, Ben Morrow <> wrote:
    > Quoth bernd <>:
    >
    >
    >
    > > 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
     
    bernd, Jan 26, 2012
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Xah Lee
    Replies:
    0
    Views:
    2,285
    Xah Lee
    Feb 26, 2009
  2. Tassilo v. Parseval

    select()ing a lexical FH

    Tassilo v. Parseval, Dec 18, 2003, in forum: Perl Misc
    Replies:
    1
    Views:
    106
    Michele Dondi
    Dec 18, 2003
  3. H. Wade Minter
    Replies:
    8
    Views:
    354
    Robin
    Apr 25, 2004
  4. Rocky

    variable scope and use strict

    Rocky, Apr 27, 2004, in forum: Perl Misc
    Replies:
    9
    Views:
    170
    Tore Aursand
    Apr 27, 2004
  5. Lexical scope and looping

    , Apr 5, 2007, in forum: Javascript
    Replies:
    6
    Views:
    169
Loading...

Share This Page