Curious TechieDev Toolbox
すべてのガイド/テキスト処理8 min read

正規表現(Regex)の動作原理とReDoS脆弱性対策

有限オートマトン解析エンジン、文字クラス、量指定子、先読み・後読み、カタストロフィック・バックトラッキングの防護。

重要ポイント (要約)
  • 正規表現は、有限オートマトン(DFA/NFA)によって解釈される形式的なパターンマッチング記法です。
  • 文字クラス([0-9])、量指定子(+, *)、アンカー(^, $)が基本骨格を成します。
  • 量指定子のネストが原因で計算量が指数関数的に爆発するReDoS(正規表現DoS攻撃)に注意が必要です。
  • 先読み・後読み(Lookaround)は、文字を消費せずに特定条件の一致を判定します。

正規表現(Regular Expression / Regex)は、文字列、ソースコード、ログファイル、ユーザー入力値の中から複雑なテキストパターンを照合・抽出・検証するための強力かつ簡潔な記法体系です。

1. 正規表現の基礎文法とメタ文字

正規表現パターンは、文字通りのリテラル文字(例:abc)または文字集合を表す特殊なメタ文字によって評価されます:

  • \d: 任意の半角数字(0-9)。
  • \w: 任意の単語構成文字(英数字およびアンダースコア)。
  • \s: 任意の空白文字(半角スペース、タブ、改行)。
  • [a-z0-9]: 指定範囲のカスタム文字クラス。

2. 貪欲(Greedy)と非貪欲(Lazy)な量指定子の比較

デフォルトの量指定子 *(0回以上)や +(1回以上)は貪欲マッチ(Greedy)であり、条件を満たす最も長い文字列に一致します。直後に ?(例:*?+?)を付与すると非貪欲マッチ(Lazy / 控えめ)になり、最も短い文字列に一致します。

3. 先読み(Lookahead)と戻り読み(Lookbehind)の肯定・否定

ゼロ幅アサーションは、文字列を消費(抽出)することなく位置条件のみを検証します:

  • (?=...) 肯定先読み (Positive Lookahead): 指定パターンが直後に続く場合に一致。
  • (?!...) 否定先読み (Negative Lookahead): 指定パターンが直後に続かない場合に一致。
  • (?<=...) 肯定戻り読み (Positive Lookbehind): 指定パターンが直前に先行する場合に一致。
  • (?<!...) 否定戻り読み (Negative Lookbehind): 指定パターンが直前に先行しない場合に一致。

4. 破滅的なバックトラッキング(ReDoS)の防止策

NFA正規表現エンジンにおいて、ネストされた無制限の量指定子(例:([a-zA-Z]+)+$)を持つパターンに不一致の長い文字列が与えられると、計算量が指数関数的(O(2^n))に爆発し、CPU使用率100%のままスレッドを停止させる正規表現DoS(ReDoS)を引き起こします。