in reply to Substitution with regexes in variables

s/// is an operator, so that means your variable contains Perl code. eval EXPR can be used to execute it.

But that's rather unsafe. I assume you don't want to allow arbitrary code execution (variable lookups, (?{}), (??{}) and /e). If so, you can use the following:

my ($pat, $repl, $mods) = $substitution =~ m{ ^s/ ( (?:[^/\\]+|\\.)* ) / ( .* ) / ( [a-z]* ) \z }xs or die("Bad substitution\n"); my %mods = map { $_ => 1 } $mods =~ /./sg; my $global = delete($mods{g}); $mods = join('', delete(@mods{qw( i m s x )})) and $pat = "(?$mods:$pat)"; die("Unknown modifiers \"", keys(%mods), "\"\n") if %mods; no re 'eval'; if ($global) { $candidate =~ s/$pat/$repl/g; } else { $candidate =~ s/$pat/$repl/; }

Replies are listed 'Best First'.
Re^2: Substitution with regexes in variables
by JadeNB (Chaplain) on Nov 15, 2009 at 07:38 UTC
    It is probably better to use Text::Balanced's extract_quotelike function rather than hand-rolling a substitution parser. (At least, the documentation suggests that it will handle s///'s correctly; and your code makes no effort to handle differently delimited patterns, among the (I assume) many other possible perversions.)

      That would allow other delimiters, but that would make it *more* complicated from a security standpoint. I didn't want to spend time thinking of the implications.

        That would allow other delimiters, but that would make it *more* complicated from a security standpoint.
        Ah, I guess in the sense that it wouldn't strip out refuse to allow escapes (as you have done), and that sort of thing?