in reply to Using Regexp Patterns as Variables

This smells a little XY Problem to me since I can't see why you'd want to do that.

That said, what's happening here is that the value of $1 is interpolated into $out at the time that you define $out. If you want, you can use single quotes to define out, and it will have the literal string "$1" in it, but that won't work either.

You may be able to do this:

my $out = '/s/Products/$1'; $ENV{REQUEST_URI} =~ s/$in/eval qq{"$out"}/ie;

I can't say I recommend that, however, especially if you don't trust the source of your real $out.

So what problem are you really trying to solve? What lead you to write code like this in the first place?

Replies are listed 'Best First'.
Re^2: Using Regexp Patterns as Variables
by ikegami (Patriarch) on Mar 18, 2009 at 16:39 UTC

    You just allowed arbitrary code to be placed in the url. Considering the code appears in a CGI script, that doesn't seem to be a good idea.

    If you want a template (that's what '$1' is here), use a template, not eval EXPR!!!

      It's an admin function. I fully trust the source of where these rules are created. Regular users cannot do this and the function is well protected.

      Think of it like giving them root access. If root wants to do an "rm -rf /" that's the power of root.

      With great power comes great... well, you know.

        Turn on taint #!/usr/bin/perl -T-- just the same.

      That's why I wrote this:

      I can't say I recommend that, however, especially if you don't trust the source of your real $out.

        There's no "if". $ENV{REQUEST_URI} is controlled by remote users.

        Even ignoring the evident trust issues, eval is simply not the right tool.

Re^2: Using Regexp Patterns as Variables
by Rodster001 (Pilgrim) on Mar 18, 2009 at 16:23 UTC
    I thought someone might ask.

    This code runs two sites, there is an admin function that allows site admins to create URL translators (old product links to new product links). Basically, they add patterns and those get stored in a database (it doesn't work yet though).

    I don't want to hard code the patterns (as both sites are very different) and also there needs to be a way to add these rules as broken links are found.

    Make sense? Code looks something like this:

    my $req = $ENV{REQUEST_URI}; ## Get rules my $query = qq~ SELECT incoming, outgoing, id FROM url_translate ~; my $sth = $dbh->prepare($query); my $rv = $sth->execute; while (my $r = $sth->fetchrow_hashref) { my $in = $r->{incoming}; my $out = $r->{outgoing}; # if( s#$in#$out#i ) { if( $req =~ s#/Products/bt-(.*?).aspx#/s/Products/$1#i + ) { $ENV{REQUEST_URI} = $req; return; } } return;
Re^2: Using Regexp Patterns as Variables
by Rodster001 (Pilgrim) on Mar 18, 2009 at 17:01 UTC
    This worked kyle:
    my $out = '/s/Products/$1'; $ENV{REQUEST_URI} =~ s/$in/eval qq{"$out"}/ie;
    I fully understand the security implications of doing this. But, as I mentioned the people creating these rules also have full access to the machine running the site. So as to say, it's a trusted source.

    Thanks for your help!

      What ikegami points out is also important to recognize. Anyone who can access to the site can feed in a URL with anything in it. As such, they may be able to choose a value for $1 with Dire Consequences.

      For example, $1 = q{";system('shutdown -h now');"}

        Ok, I see what you are saying. But, would that really happen execute?

        For example:

        #!/usr/bin/perl use strict; use warnings; $ENV{REQUEST_URI} = "/Products/bt-;system('ls -l');.aspx"; my $in = '/Products/bt-(.*?).aspx'; my $out = '/s/Products/$1'; $ENV{REQUEST_URI} =~ s#$in#eval qq{"$out"}#ie; print "$ENV{REQUEST_URI}\n";
        Prints out this:
        /Products/bt-;system('ls -l');.aspx
        But, the eval isn't actually executing that command. Or, did I not do this test correctly?