Perl regex substitution using external parameters

后端 未结 2 534
独厮守ぢ
独厮守ぢ 2021-01-05 15:18

Consider the following example:

my $text = \"some_strange_thing\";
$text =~ s/some_(\\w+)_thing/no_$1_stuff/;
print \"Result: $text\\n\";  

2条回答
  •  走了就别回头了
    2021-01-05 15:26

    Essentially the same approach as the accepted solution, but I kept the initial lines the same as the problem statement, since I thought that might make it easier to fit into more situations:

    my $match = "some_(\\w+)_thing";
    my $repl = "no_\$1_stuff";
    
    my $qrmatch = qr($match);
    my $code = $repl;
    
    $code =~ s/([^"\\]*)(["\\])/$1\\$2/g;
    $code = qq["$code"];
    
    if (!defined($code)) {
      die "Couldn't find appropriate quote marks";
    }
    
    my $text = "some_strange_thing";
    $text =~ s/$qrmatch/$code/ee;
    print "Result: $text\n";
    

    Note that this works no matter what is in $repl, whereas the naive solution has issues if $repl contains a double quote character itself, or ends in a backslash.

    Also, assuming that you're going to run the three lines at the end (or something like it) in a loop, do make sure that you don't skip the qr line. It will make a huge performance difference if you skip the qr and just use s/$match/$code/ee.

    Also, even though it's not as trivial to get arbitrary code execution with this solution as it is with the accepted one, it wouldn't surprise me if it's still possible. In general, I'd avoid solutions based on s///ee if the $match or $repl come from untrusted users. (e.g., don't build a web service out of this)

    Doing this kind of replacement securely when $match and $repl are supplied by untrusted users should be asked as a different question if your use case includes that.

提交回复
热议问题