2009-12-31 50 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