2012-08-15 11 views
34

huh?Cómo protegerse diacríticos como Zalgo texto

El carácter foto de arriba fue tuiteó hace unos meses por Mikko Hyppönen, un experto en seguridad informática conocida por su trabajo sobre los virus informáticos y TED talks sobre seguridad informática. Respecto a SO, solo publicaré una imagen de eso, pero entiendes la idea. Obviamente, no es algo que quieras difundir en tu sitio web y enloquecer a los visitantes.

Tras una inspección adicional, el personaje parece ser una letra del alfabeto tailandés combinada con más de 87 diacríticos (¿hay incluso un límite?). Esto me hizo pensar en la seguridad, la localización y cómo se podría manejar este tipo de información. Mi búsqueda me llevó al this question en Stack, y a su vez una publicación en el blog de Michael Kaplan en stripping diacritics. En él, se muestra cómo se puede descomponer una cadena en sus caracteres "base" (simplificado aquí en aras de la brevedad):

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 

puedo ver cómo que esto es sería útil en algunos casos, pero en términos de entrada del usuario, sería eliminar TODOS los signos diacríticos. Como señala Kaplan, eliminar los signos diacríticos en algunos idiomas puede cambiar completamente el significado de la palabra. Esto nos lleva a la pregunta: ¿Cómo se permiten algunos signos diacríticos en la entrada/salida del usuario, pero se excluyen otros casos extremos como el personaje über de Mikko Hyppönen?

+1

¿Incluido en la lista blanca a través de una clase de clase/utilidad estática? Y merece seguir en programmers.stackexchange.com. –

+2

@MonsterTruck, es suficiente, pero ¿en la lista blanca qué es exactamente? Estos son caracteres Unicode de los que estoy hablando. –

+4

Puede establecer un número máximo de signos diacríticos por carácter base. Elija un valor lo suficientemente alto para que vietnamita y griego sigan siendo válidos, pero lo suficientemente bajos como para rechazar los casos dementes. –

Respuesta

20

también hay de un límite ?!

No intrínsecamente en Unicode. Existe el concepto de un formato 'Stream-Safe' en UAX-15 que establece un límite de 30 combinadores ... En general, no se garantiza que las cadenas Unicode sean Stream-Safe, pero esto podría tomarse como una señal de que Unicode no pretendemos estandarizar nuevos caracteres que requerirían un clúster de grafemas más largo que eso.

30 sigue siendo un montón. El clúster de grafemas de lenguaje natural más largo conocido es el tibetano Hakṣhmalawarayaṁ en 1 base más 8 combinadores, por lo que por ahora sería razonable normalizar a NFD y no permitir ninguna secuencia de más de 8 combinadores en una fila.

Si solo te importan los idiomas comunes de Europa occidental, probablemente puedas reducir eso a 2. Por lo tanto, puedes llegar a un compromiso entre ellos.

2

Creo que encontré una solución usando NormalizationForm.FormC en lugar de NormalizationForm.FormD. De acuerdo con la MSDN:

[FormC] Indica que una cadena Unicode se normaliza usando completo descomposición canónica, seguido de la sustitución de secuencias con sus compuestos primarios, si es posible.

Supongo que descompone los caracteres en su forma base, luego los recompone basándose en un conjunto de reglas que se mantienen consistentes. Entiendo que esto es útil para fines de comparación, pero en mi caso funciona perfecto. Los personajes como ü, é y Ä se descomponen/recompuesto con precisión, mientras que los personajes falsos no pueden recomponer, y por lo tanto permanecen en su forma de base:

enter image description here

+2

Requerir solo caracteres compilados es correcto si desea limitar las cadenas a los caracteres utilizados históricamente. Unicode incluye caracteres compilados para todos los caracteres compilados en una codificación heredada, para compatibilidad. Sin embargo, las nuevas adiciones a Unicode solo pueden estar disponibles en forma descompuesta. – bobince

+0

Sugiera buscar SpacingCombiningMark o EnclosingMark, así como NonSpacingMark, para obtener otros combinadores. Además, al iterar en 'char' se pasarán las unidades de código UTF-16, por lo que no podrá verificar los caracteres fuera del plano multilingüe básico para el que solo verá los sustitutos. Sugiera usar una expresión regular para buscar y reemplazar clases de caracteres en toda la cadena a la vez. – bobince

+0

¡Gracias por la información! Si esto solo funciona con los personajes utilizados históricamente, configurar un límite de 2-8 combinadores parece una solución mucho mejor. Para ampliar su punto, este método reduce el símbolo tibetano a ཧ. ¡Intenta explicar eso a un monje tibetano! –

1

Here's regex que deberían pescar todos los zalgo, incluidos los anulados en el rango "normal".

([\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,}) 

Lo más difícil es identificarlos, una vez que hayas hecho eso, hay una multitud de soluciones.

Espero que esto te ahorre algo de tiempo.

Cuestiones relacionadas