Back to Top

Monday, December 22, 2008

How to interpolate a string in Perl?

Perl (and some other languages which came after it :-)) have a feature called interpolation, whereby the names of the variables in strings are replaced by their actual values. This is both useful and dangerous (it can easily result in problems like command injection / SQL injection / HTML injection (aka XSS) - as with everything else you have to know what you are doing!).

However interpolation is performed only once, there is no easy way to "force" the interpolation to occur. Or is it? :-). Lets suppose we have the following scenario:

  • We read a string from the user input.
  • We read a pattern and the replacement which can contain backreferences from the input (or - for that matter - references to other variables)
  • We would like to apply the search/replace pattern on the input string.

The solution is to "eval" the string in the search/replace expression to get the interpolation effect:

#!/usr/bin/perl
use strict;

my $foo = '(foo)';
my $bar = '>>>}$1<<<';

$bar =~ s/([{}])/\\$1/g;
my $str = 'foo bar baz';
$str =~ s/$foo/eval('qq{'.$bar.'}')/e;

print "Out: $str\n";

A few words: { and } needed to be escaped to handle cases where $bar contains either of them. This type of code can be very dangerous, because it can leak arbitrary inner variables! If you wish to use something like this in a sensitive environment (web pages, scripts with the suid bit set, etc), think twice. There is of course a CPAN module for this: String::Interpolate, which also lists the security problems that can occur. So take a look at it and consider if the need for flexibility overweights the need for security.

0 comments:

Post a Comment

You can use some HTML tags, such as <b>, <i>, <a>. Comments are moderated, so there will be a delay until the comment appears. However if you comment, I follow.