ก็็็็็็็็็็็็็็็็็็็็ก็็็็็็็็็็็็็็็็็็็็ก้้้้้้้้้้้้้้้้้้้้ก้้้้้้้้้้้้้้้้้้้้กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก้้้้้้้้้้้้้้้้้้้้กิิิิิิิิิิิิิิิิิิิิ
这些最近出现在Facebook的评论部分。
我们该如何消毒呢?
ก็็็็็็็็็็็็็็็็็็็็ก็็็็็็็็็็็็็็็็็็็็ก้้้้้้้้้้้้้้้้้้้้ก้้้้้้้้้้้้้้้้้้้้กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก้้้้้้้้้้้้้้้้้้้้กิิิิิิิิิิิิิิิิิิิิ
这些最近出现在Facebook的评论部分。
我们该如何消毒呢?
Answers:
这些unicode字符怎么了?
那是一个带有一系列组合字符的字符。因为所讨论的组合字符要高于基本字符,所以它们会堆叠在一起(字面上)。例如,
ก้้้้้้้้้้้้้้้้้้้้
...这是一个ก(泰国字符ko kai)(U + 0E01),后跟20个泰语组合字符mai tho(U + 0E49)。
我们该如何消毒呢?
您可以预处理文本并限制可以应用于单个字符的组合字符的数量,但是付出的努力可能不值得。您需要所有当前字符的数据表,以便知道它们是在组合还是在组合,并且您需要确保至少允许一些,因为某些语言是在同一基础上写有几种变音符号的。现在,如果您想将注释限制为拉丁字符集,那将是一个更容易的范围检查,但是,如果要将注释限制为仅几种语言,那当然是唯一的选择。有关更多信息,代码表等,请访问unicode.org。
顺便说一句,如果您想知道某个字符是如何构成的,那么对于最近的另一个问题,我在JSBin上编写了一个肮脏的“ Unicode Show Me”页面。您只需将文本复制并粘贴到文本区域中,即可显示该文本所组成的所有代码点(〜字符),并带有诸如以上指向每个字符的页面的链接。它仅适用于U + FFFF及以下范围内的代码点,因为它是用JavaScript编写的,并且要处理JavaScript中U + FFFF以上的字符,您需要做的工作比我想做的要多(因为在JavaScript中, “字符” 始终 16位,这意味着对于某些语言,可以将一个字符分割成两个单独的JavaScript“字符”,但我没有考虑),但是对于大多数文本来说,它很方便...
如果您拥有具有不错的Unicode支持的正则表达式引擎,则清理这种字符串很简单。例如,在Perl中,您可以从每个(用户感知到的)字符中删除除第一个组合标记以外的所有标记,如下所示:
#!/usr/bin/perl
use strict;
use utf8;
binmode(STDOUT, ':utf8');
my $string = "กิิ ก้้ ก็็ ก็็ กิิ ก้้ ก็็ กิิ ก้้ กิิ ก้้ ก็็ ก็็ กิิ ก้้ ก็็ กิิ ก้้";
$string =~ s/(\p{Mark})\p{Mark}+/$1/g; # Strip excess combining marks
print("$string\n");
这将打印:
<base><macron><overline><macron><overline>...
。因此,如果您的文本需要多个不同的组合字符,则可以顺利通过;并且仍然可以构建恶意文本。
好的,这花了我一段时间,我给人留下了深刻的印象,那就是将字符组合成zalgo 仅限于这些。因此,我期望遵循regex来抓狂。
([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]{2,})
而且没有用...
给我一个提示的是"ก้้้้้้้้้้้้้้้้้้้้".charCodeAt(2).toString(16)
=“ e49”,它不在组合的范围内,属于“私人使用”。
在C#中,它们属于UnicodeCategory.NonSpacingMark
以下脚本,将其冲洗掉:
[Test]
public void IsZalgo()
{
var zalgo = new[] { UnicodeCategory.NonSpacingMark };
File.Delete("IsModifyLike.html");
File.AppendAllText("IsModifyLike.html", "<table>");
for (var i = 0; i < 65535; i++)
{
var c = (char)i;
if (zalgo.Contains(Char.GetUnicodeCategory(c)))
{
File.AppendAllText("IsModifyLike.html", string.Format("<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>A&#{3};&#{3};&#{3}</td></tr>\n", i.ToString("X"), c, Char.GetUnicodeCategory(c), i));
}
}
File.AppendAllText("IsModifyLike.html", "</table>");
}
通过查看生成的表,您应该能够看到哪些堆栈。维基上缺少的一个范围是06D6-06DC
另一个0730-0749
。
更新:
这是更新后的正则表达式,它应可以将所有zalgo(包括绕过“正常”范围的zalgo)捕获。
([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F\u0483-\u0486\u05C7\u0610-\u061A\u0656-\u065F\u0670\u06D6-\u06ED\u0711\u0730-\u073F\u0743-\u074A\u0F18-\u0F19\u0F35\u0F37\u0F72-\u0F73\u0F7A-\u0F81\u0F84\u0e00-\u0eff\uFC5E-\uFC62]{2,})
一旦完成,最困难的是识别它们-上面有很多好的解决方案。
希望这可以节省您一些时间。
([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]{2,})
不起作用的原因。您是否感到有趣的是,堆叠unicode不仅限于wiki上的内容?“失去答案的问题”是什么意思?编辑:您可能会发现对3年之久的问题添加答案很奇怪,但是由于花了我一段时间才弄清楚这种类型的zalgo为何起作用,所以我不能浪费这种知识。下一个家伙会节省一些时间。