我想编写一个允许用户根据正则表达式匹配数据的函数,但我担心用户字符串的卫生。我知道使用SQL查询可以使用绑定变量来避免SQL注入攻击,但我不确定是否有这样的regexp机制。我看到有Regexp.escape,但我想允许有效的正则表达式。
以下是示例函数:
def tagged?(text)
tags.each do |tag|
return true if text =~ /#{tag.name}/i
end
return false
end
由于我只是直接在tag.name
上进行匹配,是否有人可以插入一个Proc调用或某些东西来打破正则表达式并导致破坏?
任何关于最佳实践的建议都将受到赞赏。
答案 0 :(得分:5)
Regexp中的插值字符串不会被执行,但会产生恼人的警告:
/#{exit -3}/.match('test')
# => exits
foo = '#{exit -3}'
/#{foo}/.match('test')
# => warning: regexp has invalid interval
# => warning: regexp has `}' without escape
这两个警告似乎分别与开场#{和结束}有关,并且是独立的。
作为一种更高效的策略,您可能希望将标记列表清理为可以运行一次的组合正则表达式。构造和测试N个正则表达式的效率通常远远低于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
如果执行了退出调用,程序将暂停,但它只是将其解释为文字字符串。为了避免警告,它会被反斜杠转义。
答案 1 :(得分:1)
您应该创建一个Regexp
类的实例。
def tagged?(text)
return tags.any? { |tag| text =~ Regexp.new(tag.name, Regexp::IGNORECASE) }
end