「天安門」禁止フィルタが「天安⾨」なら通る話
概要
ネットゲームでよくある、名前やプロフィール欄に入力できない禁止ワード。
おおむね初期の実装は簡素なもので、異体字を使うと通ってしまう。
天安門
を例にした場合
天安⾨
ならフィルタに引っかからず大丈夫。
これは「門」の部分が「門(u9580)」ではなく「⾨(u2fa8)」という別の文字になっており、通常の「天安門」では文字列の検索でヒットしなくなってしまうため。
解決するには
では、これらはどうやって解決すればよいのか。
さまざま手段はあるが、一例として正規表現での解決を記す。
正規表現で対応する例
正規表現では一致させたいキーワードを複数パターン持つことができる。
例えば、「えび」と「いくら」を一致させたい場合
(えび|いくら)
と書くことで、両方に一致させることができる。
天安門も同様に
(天安門|天安⾨)
とすることで、問題を回避できる。
と思った?残念!
では「天安門」でも「天安⾨」でもなく、「㆝安門」ならどうだろうか?
ダメ。
これは、今度は「天」の文字が「天(u5929)」ではなく「㆝(u319d)」となっている。
いたちごっこの始まりである。
さらに、正規表現で対応する例
ではどう対応するか、正規表現では一文字単位で複数のキーワードを持つことができる。
例えば、「最高」と「最低」を一致させたい場合
最[高低]
と書くことで、両方に一致させることができる。
つまり天安門は
[天㆝]安[門⾨]
と書くことで異体字に対応できる。
やった!解決!と思った?
異体字でのフィルタ回避は問題の一例であり、その他にもフィルタの回避方法は存在する。
(パッと説明できる物が思いつかないのでここには書かないでおく)
新たな回避策にどう対応するか、さまざまな知識が必要となる。
そして、その問題への調査・対応には膨大な人的コストが必要となってくる。
正規表現について
正規表現、めちゃくちゃおもしろいので勉強すると楽しいですよ。
お仕事でめちゃくちゃ活躍します。
参考:
正規表現のサンプル一覧
正規表現チェッカー
後日談 (2020/09/30 追記)
Unicode正規化を使えばいい、とコメントをもらう。
何これ!ズルい!
みんなも Chrome で F12 → Esc
と押して出てきた Console 欄に以下を入力して試してみよう!
"天安⾨".match(/天安門/)
"天安⾨".normalize('NFKC').match(/天安門/)
参考:
String.prototype.normalize() - JavaScript | MDN
正規化形式別のユニコード正規化の振る舞いの違いを見てみる | 分析ノート
Discussion