2009-12-31 42 views
4

我想编写一个允许用户根据正则表达式匹配数据的函数,但我担心用户字符串的卫生问题。我知道SQL查询可以使用绑定变量来避免SQL注入攻击,但我不确定是否有这样的正则表达式机制。我看到有Regexp.escape,但我想允许有效的正则表达式。消毒用户正则表达式

这里是样本函数:

def tagged?(text) 
    tags.each do |tag| 
     return true if text =~ /#{tag.name}/i 
    end 
    return false 
    end 

因为我只是tag.name直接匹配的是有一个机会,有人可以插入一个Proc来电或东西打出来的正则表达式,并造成破坏?

任何意见的最佳做法,将不胜感激。

回答

5

插值字符串不执行,但也产生恼人的警告:

/#{exit -3}/.match('test') 
# => exits 

foo = '#{exit -3}' 
/#{foo}/.match('test') 
# => warning: regexp has invalid interval 
# => warning: regexp has `}' without escape 

两次警告的似乎属于分别开#{和结束},并且是独立的。

作为一种更高效的策略,您可能希望将标记列表清理为可以运行一次的组合正则表达式。对N个正则表达式进行构造和测试的效率通常低于1个具有N个部分的效率。

也许沿此线的东西:

class Taggable 
    def tags 
    @tags 
    end 

    def tags=(value) 
    @tags = value 

    @tag_regexp = Regexp.new(
     [ 
     '^(?:', 
     @tags.collect do |tag| 
      '(?:' + tag.sub(/\#\{/, '\\#\\{').sub(/([^\\])\}/, '\1\\}') + ')' 
     end.join('|'), 
     ')$' 
     ].to_s, 
     Regexp::IGNORECASE 
    ) 
    end 

    def tagged?(text) 
    !!text.match(@tag_regexp) 
    end 
end 

这可以像这样使用:

e = Taggable.new 
e.tags = %w[ #{exit-3} .*\.gif .*\.png .*\.jpe?g ] 

puts e.tagged?('foo.gif').inspect 

如果退出调用被执行时,程序将停止存在,但它只是解释作为一个文字字符串。为了避免警告,它使用反斜杠进行转义。

+0

我正在尝试插入一个proc并得到相同的错误。分配给activerecord对象时,它看起来像被转义了: # 我得到了与实际尝试将它用作一个正则表达式。我只是不确定是否有一些我错过了。 – 2009-12-31 18:25:13

1

您应该改为创建一个Regexp类的实例。在正则表达式

def tagged?(text) 
    return tags.any? { |tag| text =~ Regexp.new(tag.name, Regexp::IGNORECASE) } 
end