Lo que podría ser una manera de recuperar una lista de todos los personajes de una clase de caracteres dada (como blank, alpha, digit...) en la localización actual.
Por ejemplo,
LC_ALL=en_GB.UTF-8 that-command blank
idealmente, en mi sistema Debian, mostraría algo como:
09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE
e1 9a 80 U+1680 OGHAM SPACE MARK
e1 a0 8e U+180E MONGOLIAN VOWEL SEPARATOR
e2 80 80 U+2000 EN QUAD
e2 80 81 U+2001 EM QUAD
e2 80 82 U+2002 EN SPACE
e2 80 83 U+2003 EM SPACE
e2 80 84 U+2004 THREE-PER-EM SPACE
e2 80 85 U+2005 FOUR-PER-EM SPACE
e2 80 86 U+2006 SIX-PER-EM SPACE
e2 80 88 U+2008 PUNCTUATION SPACE
e2 80 89 U+2009 THIN SPACE
e2 80 8a U+200A HAIR SPACE
e2 81 9f U+205F MEDIUM MATHEMATICAL SPACE
e3 80 80 U+3000 IDEOGRAPHIC SPACE
Y en la configuración regional C podría mostrar algo como:
09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE
Es decir, la representación del carácter en la configuración regional en términos de matrices de bytes (como UTF-8 en el primer ejemplo y un solo byte en el segundo), el punto de código de caracteres Unicode equivalente y una descripción.
Contexto
(editar) Ahora que la vulnerabilidad ha sido parcheada y revelada por mucho tiempo, puedo agregar un poco de contexto.
Hice esa pregunta en el momento en que estaba investigando CVE 2014-0475 . glibctenía un error en el sentido de que permitía al usuario usar configuraciones regionales como las LC_ALL=../../../../tmp/evil-localeque se resuelven en relación con la ruta de búsqueda de configuración regional del sistema estándar y, por lo tanto, permite usar cualquier archivo como definición de configuración regional.
Podría crear un entorno local malicioso, por ejemplo, con un solo byte por juego de caracteres donde la mayoría de los caracteres excepto s, hy algunos otros se consideraron espacios en blanco y eso se bashejecutaría shal analizar un /etc/bash.bashrcarchivo Debian típico (y eso podría usarse para obtener acceso de shell en un gitel servidor de alojamiento, por ejemplo, bashse utiliza como el shell de inicio de sesión del usuario del gitservidor y que el sshservidor acepta LC_*/ LANGvariables y que el atacante puede cargar archivos al servidor).
Ahora, si alguna vez encontré una LC_CTYPE(definición de configuración regional compilada) /tmp/evil, ¿cómo podría descubrir que era una canalla y de qué manera?
Por lo tanto, mi objetivo es descompilar esas definiciones de configuración regional y, si no, al menos saber qué caracteres (junto con su codificación) están en una clase de caracteres dada.
Así que con eso en mente:
- Las soluciones que miran los archivos de origen para la configuración regional (las definiciones de configuración regional como las
/usr/share/i18n/localede Debian) no son útiles en mi caso. - Las propiedades de los caracteres Unicode son irrelevantes. Solo me importa lo que dice la localidad. En un sistema Debian, incluso entre dos configuraciones regionales del sistema UTF-8, y mucho menos las falsas, la lista de caracteres en una clase puede ser diferente.
- Las herramientas como
recode,pythonoperlque realizan la conversión de byte / multi-byte a / desde caracteres no pueden usarse, ya que pueden (y en la práctica lo hacen) realizar la conversión de una manera diferente a la configuración regional.
fuente

/usr/share/i18n/locales/i18n... que, por supuesto, proviene en gran medida de la base de datos de caracteres Unicode. Por supuesto, sería bueno tener un comandolocale(al menos la de GNU) recupera muchas de las informaciones almacenadas en muchas de las categorías, cosas que no son las más importantes en LC_CTYPE y LC_COLLATE. Me pregunto si hay una API oculta para recuperar esa información o descompilar la información del entorno local.recodeyuconvpuede darle lo que usted dice que está buscando. Posiblemente incluso justoluityodsupongo ...perlnada, creo.LC_CTYPEconod -A n -t c <LC_CTYPE | tsortProbablemente ya lo hayas probado, pero nunca antes había oído hablar de eso y estaba leyendoinfoy me recordó esto, y parece funcionar. También hay,ptxpero creo que es menos relevante. De todos modos, si no lo ha intentado y decide hacerlo, advertencia justa, requiere un poco de paciencia. lehman.cuny.edu/cgi-bin/man-cgi?tsort+1Respuestas:
POSIBLE SOLUCIÓN FINAL
Así que tomé toda la información a continuación y llegué a esto:
NOTA :
Lo uso
odcomo el filtro final anterior por preferencia y porque sé que no trabajaré con caracteres de varios bytes, que no manejará correctamente.recode u2..dumpambos generarán una salida más parecida a la especificada en la pregunta y manejarán los caracteres anchos correctamente.SALIDA
API DEL PROGRAMADOR
Como lo demuestro a continuación,
recodele proporcionaré su mapa completo de personajes. De acuerdo con su manual, lo hace de acuerdo con el valor actual de laDEFAULT_CHARSETvariable de entorno o, en su defecto, funciona exactamente como usted especifica:También vale la pena señalar
recodeque es una API :#include <recode.h>Para una comparación de cadenas internacionalmente amigable Los estándares
POSIXyCdefinen lastrcoll()función:Aquí hay un ejemplo de su uso ubicado por separado :
Con respecto a las
POSIXclases de caracteres, ya has notado que usaste laCAPI para encontrarlos. Para caracteres y clases unicode, puede usar el juego de caracteresrecode'sdump-with-names para obtener el resultado deseado. De su manual nuevamente :Utilizando una sintaxis similar a la anterior combinada con su conjunto de datos de prueba incluido , puedo obtener mi propio mapa de caracteres con:
SALIDA
Pero para los personajes comunes,
recodeaparentemente no es necesario. Esto debería darle caracteres con nombre para todo en el conjunto de caracteres de 128 bytes:SALIDA
Por supuesto, solo se representan 128 bytes, pero eso se debe a que mi configuración regional, utf-8 charmaps o no, usa el juego de caracteres ASCII y nada más. Entonces eso es todo lo que obtengo. Sin
luitembargo, si lo ejecutara sin filtrarlo,odlo rodaría e imprimiría el mismo mapa nuevamente hasta\0400.Sin embargo, hay dos problemas principales con el método anterior. Primero está el orden de clasificación del sistema: para los entornos locales que no son ASCII, los valores de mordida de los conjuntos de caracteres no son simplemente in
sequence, lo que, según creo, es probablemente el núcleo del problema que está tratando de resolver.Bueno, la
tr's manpágina de GNU afirma que expandirá las[:upper:][:lower:]clases en orden, pero eso no es mucho.Me imagino que podría implementarse una solución de mano dura,
sortpero sería una herramienta bastante difícil de manejar para una API de programación de back-end.recodehará esto correctamente, pero el otro día no parecías demasiado enamorado del programa. Tal vez las ediciones de hoy arrojen una luz más amigable o tal vez no.GNU también ofrece la
gettextbiblioteca de funciones, y parece ser capaz de abordar este problema al menos para elLC_MESSAGEScontexto:También puede usar categorías de caracteres Unicode nativas , que son independientes del idioma y renuncian a las clases POSIX por completo, o tal vez recurrir a las primeras para proporcionarle suficiente información para definir las últimas.
El mismo sitio web que proporcionó la información anterior también analiza
Tclla propia implementación de expresiones regulares que cumple con POSIX, que podría ser otra forma de lograr su objetivo.Y por último, entre las soluciones, sugeriré que puede interrogar el
LC_COLLATEarchivo en sí para obtener el mapa de caracteres del sistema completo y en orden . Puede que esto no parezca fácil, pero logré algo de éxito con lo siguiente después de compilarlolocaledefcomo se muestra a continuación:Es, sin duda, actualmente defectuoso, pero espero que al menos demuestre la posibilidad.
AL PRIMER RUBOR
Realmente no parecía mucho, pero luego comencé a notar
copycomandos en toda la lista. El archivo anterior parece estarcopyen "en_US", por ejemplo, y otro muy grande que parece que todos comparten hasta cierto punto esiso_14651_t1_common.Es bastante grande:
Aquí está la introducción a
/usr/share/i18n/locales/POSIX:...
Puede hacerlo,
greppor supuesto, pero podría simplemente:En lugar. Obtendrías algo como esto:
... Y MÁS
También hay
luitunptydispositivo de traducción UTF-8 terminal , supongo que actúa como intermediario para XTerms sin soporte UTF-8. Maneja muchos modificadores, como registrar todos los bytes convertidos en un archivo o-ccomo un|pipefiltro simple .Nunca me di cuenta de que había tanto en esto: las configuraciones regionales y los mapas de caracteres y todo eso. Aparentemente esto es un gran problema, pero supongo que todo sucede detrás de escena. Hay, al menos en mi sistema, un par de cientos de
man 3resultados relacionados para búsquedas relacionadas con la configuración regional.Y también hay:
Eso va a continuar por un muy largo tiempo.
Las
Xlibfunciones manejan esto todo el tiempo,luites parte de ese paquete.Las
Tcl_uni...funciones también pueden resultar útiles.solo un poco de
<tab>finalización ymanbúsquedas, y he aprendido bastante sobre este tema.Con
localedef: puede compilarlolocalesen suI18Ndirectorio. El resultado es funky y no extraordinariamente útil, no comocharmapsen absoluto, pero puede obtener el formato sin procesar tal como lo especificó anteriormente como lo hice yo:Luego con
odusted puede leerlo: bytes y cadenas:Aunque está muy lejos de ganar un concurso de belleza, esa es una salida utilizable. Y
odes tan configurable como quieras que sea, por supuesto.Supongo que también me olvidé de estos:
Probablemente me olvidé de ellos porque no pude hacer que trabajaran. Supongo que nunca uso
Perly no sé cómo cargar un módulo correctamente. Pero lasmanpáginas se ven muy bien. En cualquier caso, algo me dice que encontrarás que llamar a un módulo de Perl es al menos un poco menos difícil que yo. Y, nuevamente, estos ya estaban en mi computadora, y ni siquiera uso Perl. También hay notablemente algunosI18Nque me desplacé con melancolía sabiendo muy bien que tampoco los haría funcionar.fuente
i18n) que pueden o no haber sido utilizados para generar la configuración regional que estoy usando actualmente. La información del entorno local probablemente proviene de/usr/lib/locale/locale-archiveo/some/dir/LC_CTYPE, y esa es la parte relevante para mi entorno local que se almacena en los archivos que busco.LC_STUFFarchivo del archivolocaledef, también lo hace. Puedo demostrar eso también, supongo. También puede ver eso y prácticamente todo lo demás constringso conodel resto. Lo hice, de todos modos. Pero, por cierto,charmapsson la configuración regional que está utilizando actualmente, ylocaledeftambién informará sobre eso. También eso es lo querecodehace también.od,recode,uconvy el resto. Pero fue mi error, no eslocaledefque lo extraiga, esrecodeeso lo hará. Tienes que echarle un vistazoinfo recode, y además delrecodecomando de tabla que muestro hay casi lo mismo, y creo que manejará las cosas de la misma manera. No solo saca su juego de caracteres de la nada. En cualquier caso, tenía muchas esperanzas para esosperlmódulos. ¿Probaste alguno?iswblank(3)para todos los valores de caracteres posibles.Al menos en los sistemas GNU, FreeBSD o Solaris, este enfoque de fuerza bruta funciona:
Si bien según C / POSIX,
wchar_tes un tipo opaco que no tiene relación con Unicode y solo se garantiza que cubre todos los caracteres admitidos por la configuración regional del sistema, en la práctica, en la mayoría de los sistemas que admiten Unicode, los valores sí corresponden a los puntos de código Unicode y las definiciones locales están basadas en Unicode.Unicode está destinado a ser un superconjunto de todos los conjuntos de caracteres conocidos, por lo que recorrer todos los puntos de código válidos en Unicode (0 a 0xD7FF y 0xE000 a 0x10FFFF) debe enumerar al menos todos los caracteres admitidos por un conjunto de caracteres dado.
Aquí, estamos utilizando la API estándar de la configuración regional del sistema para verificar cuáles son de un tipo determinado y convertirlo a su forma codificada en la codificación de la configuración regional. Usamos
perly sucharnamesmódulo solo para obtener el nombre de un punto de código Unicode dado.En las configuraciones regionales que usan codificaciones con estado como ISO-2022-JP, nos aseguramos de que el formulario codificado se muestre desde un estado inicial predeterminado.
No he encontrado un sistema que haya instalado entornos locales con una codificación de caracteres con estado, pero al menos en los sistemas GNU, es posible generar algunos para que se pueda hacer un entorno local no autorizado (y al menos las herramientas GNU no funcionan correctamente en esos sistemas). locales). Por ejemplo, con una configuración regional personalizada que utiliza ISO-2022-JP con una
ja_JPconfiguración regional normal , obtengo:Comparar con:
En ISO-2022-JP, la
1B 24 42secuencia (\e$B) cambia de ASCII a un estado donde los caracteres se expresan como 2 bytes (7 bits) (aquí 21 21 para ese ESPACIO IDEOGRÁFICO). Mientras que en EUCJP, son los mismos bytes, pero el cambio de estado se realiza al voltear el 8vo bit (A1 = 21 | 0x80), lo que lo hace más apátrida.Eso significa que en esas codificaciones con estado, hay varias formas de escribir un carácter dado (por ejemplo, insertando varias de esas secuencias de cambio de estado ), y la secuencia que se muestra con ese código anterior es solo una de ellas (la canónica de una inicial estado predeterminado).
Mientras que para un escenario normal, los personajes no pueden estar fuera 0..0xD7FF, 0xE000..0x10FFFF, para un pícaro local, cualquier carácter en la gama que admite wchar_t puede ser. Por ejemplo, podría crear un entorno local donde U + DCBA o U + 12345678 caracteres (o serían caracteres si se permitieran) son espacios en blanco . Es por eso que querría compilar ese código
-D SUPPORT_ROGUE_LOCALESpara cubrirlos, aunque eso significa que lleva mucho más tiempo escanear toda la lista.No pude usar la solución de @ mikeserv ya que
recodeusa sus propias conversiones, ya no se mantiene y solo admite caracteres Unicode hasta 0xFFFF, y GNUtral menos no funciona con caracteres de varios bytes.No pude usar @ ChrisDown ya
pythonque no tiene interfaces para las clases de caracteres POSIX.Intenté con Perl, pero es falso para puntos de código entre 128 y 255 para entornos locales de varios bytes que no sean UTF-8 y no usa las bibliotecas de conversión del sistema.
fuente
combiningycombining_level3(a saberiswctype(i, wctype("combining")))