Как защитить от диакритики, такой как Zalgo text

huh?

персонаж, изображенный выше, был опубликован в Твиттере несколько месяцев назад Микко Hyppönen, специалист по компьютерной безопасности, известный своей работой над компьютерными вирусами и Тед говорит на компьютерной безопасности. В отношении SO я только опубликую его изображение, но вы получите идею. Это, очевидно, не то, что вы хотели бы распространять вокруг своего сайта и пугать посетителей.

при дальнейшем осмотре символ кажется буквой тайского алфавита в сочетании с более чем 87 диакритиками (есть ли даже предел?!). Это заставило меня задуматься о безопасности, локализации и о том, как можно обрабатывать такой ввод. Мои поиски ведут меня к этот вопрос на стеке, и в свою очередь сообщение в блоге от Майкла Каплана на зачистки диакритические знаки. В нем он демонстрирует, как можно разложить строку на свою "базу" персонажей (упрощенный для краткости):

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 

Я понимаю, что это было бы полезно в некоторых случаях, но с точки зрения пользовательского ввода, это будет удаление всех диакритиков. Как указывает Каплан, удаление диакритики в некоторых языках может полностью изменить значение слова. Напрашивается вопрос:--17-->как можно разрешить некоторые диакритики в пользовательском вводе / выводе, но исключить другие экстремальные случаи, такие как über-символ Микко Гиппонена?

3 ответов


есть ли предел?!

Не внутренне в Unicode. Существует концепция "потокобезопасного" формата в UAX-15, который устанавливает предел 30 комбинаторов... Строки Unicode в целом не гарантируют потокобезопасность, но это, безусловно, может быть принято как знак того, что Unicode не намерен стандартизировать новые символы, для которых потребуется кластер графем дольше.

30-это еще очень много. Самый длинный из известных естественных языков графемный кластер-Тибетский Hakṣhmalawarayaṁ на 1 базе плюс 8 комбинаторов, поэтому на данный момент было бы разумно нормализовать NFD и запретить любую последовательность более 8 комбинаторов подряд.

Если вы заботитесь только об общих западноевропейских языках, вы, вероятно, можете уменьшить это до 2. Так что потенциально компромисс где-то между ними.


Я думаю, что нашел решение с помощью NormalizationForm.FormC вместо NormalizationForm.FormD. Согласно MSDN:

[FormC] указывает, что строка Юникода нормализуется с помощью full каноническое разложение с последующей заменой последовательностей на их основные составные части, если возможно.

Я понимаю, что это означает, что он разлагает символы на их базовую форму, а затем воссоздает их на основе набора правил, которые остаются согласованными. Я понял это. полезно для сравнения, но в моем случае он работает идеально. Символы ü, é и Ä разлагаются/перешитых точно, в то время как фиктивные персонажи не перемешиваются, и таким образом остаются в своей базовой форме:

enter image description here


вот регулярное выражение это должно выловить все 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,})

самое трудное-это определить их, как только вы это сделаете - есть множество решений.

надеюсь, это сэкономит вам время.