2

我需要一种非常简单的基于行(空格分隔)的“语言”,通常会寻找一些预定义的“动作”(第一个字段),并使用参数(行中的其他字段)执行定义的 perl subs。

许多操作之一是“定义变量值”应该在接下来的操作中可用。

代码片段(输入在DATA中):

use 5.012;
use strict;
use warnings;
use Data::Dumper;

my $VARS;
while(my $line = <DATA>) {
    chomp $line;
    next unless ($line =~ m/^\s*(def|echo|SOME|OTHER|ACTIONS|HERE)\s+(.*)/ );
    my $action = $1;
    my $args = $2;
    my(@fld) = split /\s+/, $args;
    for ($action) {
        when (/^def$/) { $VARS->{$fld[0]} = expandvars($fld[1]); } #expand and store
        when (/^echo$/) { say expandvars($args); }  #echo
    }
    #say Dumper($VARS);
}

sub expandvars {
    my($str) = @_;
    if( $str =~ /\$\{(\w+?)\}/ ) {
        ##############################################
        #is this SAFE or Dangerous? 
        $str =~ s/\$\{(\w+?)\}/$VARS->{$1}/xeg;
        ##############################################
    }
    return $str;
}
__DATA__
#"action" define aaa
def aaa somestring

#define bbb
def bbb ===${aaa}===

#echo 
echo this is ${bbb} here

#here will continue another "actions", but they're
#not needed for the question

该程序正在运行(可能远非“最佳”),给出了想要的结果

this is ===somestring=== here

但我的问题是:

我如何替换变量SAFE的方式是什么?那么,如果用户给出一些其他行(程序将从标准输入中读取它们)是否有可能构造一些危险的东西?上述方式对于变量扩展是否合理安全?或者如果它是错误的,我可以在哪里学习正确的方法?:)

4

2 回答 2

1

An attacker would have to put characters in that either close brackets or open new ones. If you narrow it to word characters, I don't see how it can be not safe.

Incidentally, you can speed up your regex by making the capture expression a solid + for the variable name. If you run into a close-curly, you will not consume it with a \w having been specified.

s/\$\{(\w+)\}/$VARS->{$1}/xeg;
于 2013-05-07T12:27:28.963 回答
1

Your code is safe in the sense that I can see no way for injection attacks. However, this isn't an especially well-designed templating language:

def .   invisible
def var no-vars-with spaces
echo ${.}
echo ${var}

should output

${.}
no-vars-with

Your code could probably be factored better, but that is largely irrelevant.

The /e flag on your substitution does nothing in this case: There is effectively no difference between qq/$var/ and $var.

于 2013-05-07T12:27:41.233 回答