Dacav
Dacav

Reputation: 14078

Is anything wrong with perl's s/../../e?

I was searching for the Perl equivalent of python's re.sub, in which according to the documentation repl can be either a string or a callable.

I eventually found out about the e modifier of the perl s// function, which would allow me to do things like:

my $n = 1;
sub repl {
    return $_[0] x $n ++;
}
my $hw = "hello world";
$hw =~ s/(l)/repl $1/eg;
say $hw;

And obtain helllo worllld.

I found it a bit suspicious on the security standpoint. I assumed that Mallory has control on the $hw string and I'm not convinced on the safety of this method, although I was not able to find any possible exploitation.

For sure there's something inherently wrong with the /ee modifier: search for the word "vendetta" in this thread to get a clue. The double-e lets me think that the evaluated expression (in this case repl $1) corresponds to an implicit eval('repl $1').

Is this the case?

Example of possible issue

We clearly have repl("foo lish") called, but you could wonder if repl foo lish is going to be evaluated. It's a bit ambiguous. This is not a problem, but my question is about possible pitfalls whith similar patterns.

Upvotes: 1

Views: 103

Answers (1)

ikegami
ikegami

Reputation: 386541

It doesn't cause any data to become code. It simply tells Perl to treat part of the .pl file as Perl code. As such, it doesn't introduce any security issues.

If the substitution operator was a function, then

s/pat/repl/     ⇒  substitute($_, qr/pat/, sub { qq/repl/ })
s/pat/repl()/e  ⇒  substitute($_, qr/pat/, sub { repl() })

And that's obviously perfectly alright.


Further proof is that everything one can do with /e can do easily be done without.

s/pat/repl()/e

is similar to

s/pat/${\( repl() )/

/ee, on the other hand, could be a security issue. Data can become code.

s/pat/repl/ee

is similar to

s/pat/eval "repl"/e

The problem comes with the replacement pattern interpolates[1].

$ echo 'print "0wn3d\n";' | perl -e'$_ = <>; s/(.*)/$1/ee'
0wn3d

I never use /ee since it obscures the fact that you used eval EXPR.


  1. There's no reason to use /ee if the replacement expression doesn't interpolate.

Upvotes: 3

Related Questions