如何防止像Zalgo文本这样的变音符号

Der*_*ker 37 c# unicode user-input diacritics zalgo

是吧?

上面描绘的角色是几个月前由计算机安全专家MikkoHyppönen发推的,他以计算机病毒和TED谈论计算机安全而闻名.关于SO,我只会发布它的图像,但你明白了.这显然不是你想要在你的网站上传播并吓跑游客的东西.

经过进一步检查,该字符似乎是一个泰语字母和超过87个变音符号的字母(是否有限制?!).这让我想到了安全性,本地化以及如何处理这种输入.我的搜索引导我在Stack上提出这个问题,然后是迈克尔卡普兰关于剥离变音符号的博客文章.在其中,他演示了如何将字符串分解为其"基本"字符(为简洁起见,此处简化):

StringBuilder sb = new StringBuilder();
foreach (char c in "façade".Normalize(NormalizationForm.FormD))
{
    if (char.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
        sb.Append(c);
}
Response.Write(sb.ToString()); // facade 
Run Code Online (Sandbox Code Playgroud)

我可以看到这在某些情况下是如何有用的,但就用户输入而言,它将剥离所有变音符号.正如卡普兰指出的那样,删除一些语言中的变音符号可以完全改变单词的含义.这引出了一个问题:如何在用户输入/输出中允许一些变音符号,但排除其他极端情况,例如MikkoHyppönen的超级字符?

bob*_*nce 25

还有限制吗?!

在Unicode中本质上不是.在UAX-15中存在"流安全"格式的概念,其设置了30个组合器的限制......通常不保证Unicode字符串是流安全的,但这当然可以作为Unicode的标志.不打算标准化需要比这更长的字形簇的新字符.

30仍然是一个可怕的很多.已知时间最长的自然语言字形集群是1个基地的藏文Hakṣhmalawaraya,加上8个合并器,因此现在将NFD归一化并且不允许连续超过8个组合器的任何序列是合理的.

如果您只关心常见的西欧语言,您可能会将其降低到2.因此可能会在这些语言之间产生影响.