5

ユーザーが正規表現に基づいてデータを照合できるようにする関数を書きたいのですが、ユーザー文字列のサニテーションが心配です。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 呼び出しまたは何かを挿入して正規表現から抜け出して大混乱を引き起こす可能性はありますか?

ベストプラクティスに関するアドバイスをいただければ幸いです。

4

2 に答える 2

5

正規表現で補間された文字列は実行されませんが、迷惑な警告が生成されます:

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

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

2 つの警告は、それぞれ開始 #{ と終了 } に関連しているようで、独立しています。

より効率的な戦略として、タグのリストを一度実行できる結合された正規表現にサニタイズすることをお勧めします。一般に、N 個の正規表現を作成してテストするのは、N 個の部分を持つ 1 つよりもはるかに効率的ではありません。

おそらく、これに沿った何か:

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

exit 呼び出しが実行された場合、プログラムはそこで停止しますが、それをリテラル文字列として解釈するだけです。警告を避けるために、バックスラッシュでエスケープされます。

于 2009-12-31T16:10:40.800 に答える
2

おそらく、Regexp代わりにクラスのインスタンスを作成する必要があります。

def tagged?(text)
  return tags.any? { |tag| text =~ Regexp.new(tag.name, Regexp::IGNORECASE) }
end
于 2009-12-31T15:34:16.857 に答える