Was könnte ein Weg sein , eine Liste aller Zeichen in einem bestimmten Zeichenklasse abzurufen (wie blank
, alpha
, digit
...) in der aktuellen Locale.
Zum Beispiel,
LC_ALL=en_GB.UTF-8 that-command blank
Im Idealfall würde auf meinem Debian-System Folgendes angezeigt:
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
Und im C-Gebietsschema könnte so etwas angezeigt werden:
09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE
Das heißt, die Darstellung des Zeichens im Gebietsschema in Form von Arrays von Bytes (wie UTF-8 im ersten Beispiel und Einzelbyte im zweiten), dem entsprechenden Unicode-Zeichen-Codepunkt und einer Beschreibung.
Kontext
(edit) Nachdem die Sicherheitsanfälligkeit lange behoben und aufgedeckt wurde, kann ich ein wenig Kontext hinzufügen.
Ich habe diese Frage gestellt, als ich CVE 2014-0475 untersuchte . glibc
hatte den Fehler, dass der Benutzer solche Gebietsschemas verwenden konnte LC_ALL=../../../../tmp/evil-locale
, die relativ zum standardmäßigen Suchpfad für das Gebietsschema des Systems aufgelöst wurden, und daher jede Datei als Gebietsschemadefinition verwenden konnte.
Ich könnte einen Schelm locale erstellen zum Beispiel mit einem Byte pro Zeichen charset , wo die meisten Zeichen außer s
, h
und ein paar andere wurden als Leerstellen und das würde bash
laufen , sh
während eine typische Debian - Parsing - /etc/bash.bashrc
Datei (und das verwendet werden könnte , Shell - Zugriff auf einem bekommen git
Der zum Beispiel bereitgestellte Hosting-Server bash
wird als Anmeldeshell des git
Serverbenutzers verwendet, und der ssh
Server akzeptiert LC_*
/ LANG
Variablen und der Angreifer kann Dateien auf den Server hochladen.
Wenn ich jemals eine LC_CTYPE
(kompilierte Gebietsschemadefinition) in gefunden hätte /tmp/evil
, wie würde ich dann herausfinden, dass es eine Schurken- Definition war und auf welche Weise.
Mein Ziel ist es daher, diese Gebietsschemadefinitionen zu dekompilieren und, falls nicht, zumindest zu wissen, welche Zeichen (zusammen mit ihrer Codierung) in einer bestimmten Zeichenklasse enthalten sind.
In diesem Sinne:
- Lösungen, die sich die Quelldateien für das Gebietsschema ansehen (die Gebietsschemadefinitionen wie die in
/usr/share/i18n/locale
Debian), sind in meinem Fall nicht von Nutzen. - Unicode-Zeicheneigenschaften sind irrelevant. Mir ist nur wichtig, was das Gebietsschema sagt. Auf einem Debian-System kann die Liste der Zeichen in einer Klasse sogar zwischen zwei UTF-8-System-Gebietsschemata unterschiedlich sein, geschweige denn zwischen falschen.
- Tools wie
recode
,python
oderperl
das tun , um die Byte / Multi-Byte zu / von Zeichenkonvertierung nicht verwendet werden können , wie sie können (und in der Praxis tun) , um die Umwandlung in einer anderen Art und Weise machen als die locale.
quelle
/usr/share/i18n/locales/i18n
... die natürlich größtenteils aus der Unicode- Zeichendatenbank stammen. Natürlich wäre es schön, ein Kommando zu habenlocale
(zumindest die GNU- Version ) viele der in vielen Kategorien gespeicherten Informationen abruft, sind dies nicht die wichtigsten in LC_CTYPE und LC_COLLATE. Ich frage mich, ob es eine versteckte API gibt, um diese Informationen abzurufen oder die Gebietsschemainformationen zu dekompilieren.recode
unduconv
kann Ihnen geben, was Sie sagen, was Sie suchen. Möglicherweise sogar nurluit
undod
ich denke ...perl
überhaupt nicht, denke ich.LC_CTYPE
mit zu extrahieren.od -A n -t c <LC_CTYPE | tsort
Wahrscheinlich haben Sie ihn bereits ausprobiert, aber ich hatte noch nie zuvor davon gehört, und ich habe durchgeleseninfo
und es hat mich daran erinnert - und es scheint zu funktionieren. Es gibt auch,ptx
aber ich denke, es ist weniger relevant. Wie auch immer, wenn Sie es noch nicht ausprobiert haben und sich dazu entschließen - eine faire Warnung -, erfordert es ein wenig Geduld. lehman.cuny.edu/cgi-bin/man-cgi?tsort+1Antworten:
MÖGLICHE LÖSUNG
Daher habe ich die folgenden Informationen zusammengestellt:
HINWEIS :
Ich benutze
od
als letzten Filter oben und weil ich weiß, dass ich nicht mit Multi-Byte-Zeichen arbeiten werde, die es nicht richtig handhaben wird.recode u2..dump
Beide erzeugen eine Ausgabe, die der in der Frage angegebenen ähnelt, und verarbeiten breite Zeichen korrekt.AUSGABE
PROGRAMMER'S API
Wie ich unten demonstriere,
recode
bekommst du deine komplette Charakterkarte. Entsprechend dem Handbuch wird dies zuerst anhand des aktuellen Werts derDEFAULT_CHARSET
Umgebungsvariablen ausgeführt. Andernfalls wird genau so vorgegangen, wie Sie es angegeben haben:Erwähnenswert
recode
ist auch, dass es sich um eine API handelt :#include <recode.h>
Für einen international freundlichen Stringvergleich definieren Die
POSIX
undC
Standards diestrcoll()
Funktion:Hier ist ein separat platziertes Beispiel für die Verwendung:
In Bezug auf die
POSIX
Zeichenklassen haben Sie bereits festgestellt, dass Sie dieC
API verwendet haben, um diese zu finden. Für Unicode-Zeichen und -Klassen können Sie den Zeichensatzrecode's
dump-with-names verwenden , um die gewünschte Ausgabe zu erhalten. Nochmals aus dem Handbuch :Wenn ich eine ähnliche Syntax wie oben in Kombination mit dem enthaltenen Testdatensatz verwende, kann ich meine eigene Zeichentabelle erstellen mit:
AUSGABE
Aber für gewöhnliche Charaktere
recode
ist das anscheinend nicht nötig. Dies sollte Ihnen benannte Zeichen für alles im 128-Byte-Zeichensatz geben:AUSGABE
Natürlich werden nur 128 Bytes dargestellt, aber das liegt daran, dass mein Gebietsschema, utf-8 charmaps oder nicht, den ASCII- Zeichensatz verwendet und sonst nichts. Das ist alles was ich bekomme. Wenn ich es
luit
laufen lassenod
würde, ohne es zu filtern, würde ich es zurückrollen und die gleiche Karte erneut drucken, bis\0400.
Es gibt jedoch zwei Hauptprobleme bei der obigen Methode. Erstens gibt es die Sortierreihenfolge des Systems - für Nicht-ASCII-Gebietsschemata sind die Bite-Werte für die Zeichensätze nicht einfach von
seq
Bedeutung, was, wie ich denke, der Kern des Problems ist, das Sie zu lösen versuchen.Nun, auf der GNU-
tr's man
Seite heißt es, dass die[:upper:]
[:lower:]
Klassen der Reihe nach erweitert werden - aber das ist nicht viel.Ich stelle mir vor
sort
, dass eine schwierige Lösung implementiert werden könnte, aber das wäre ein ziemlich unhandliches Werkzeug für eine Backend-Programmierschnittstelle.recode
Ich werde das richtig machen, aber Sie schienen neulich nicht allzu verliebt in das Programm zu sein. Vielleicht werden die heutigen Änderungen ein freundlicheres Licht darauf werfen oder vielleicht auch nicht.GNU bietet auch die
gettext
Funktionsbibliothek an, und es scheint in der Lage zu sein , dieses Problem zumindest für denLC_MESSAGES
Kontext anzugehen :Sie könnten auch die native verwenden Unicode - Zeichenkategorien , die sprachunabhängig sind und die POSIX - Klassen ganz verzichten, oder vielleicht auf dem ehemaligen rufen Sie genügend Informationen , um die letztere zu definieren.
Auf derselben Website, auf der die oben genannten Informationen bereitgestellt wurden, wird auch die
Tcl
eigene POSIX- konforme Regex-Implementierung erläutert , die möglicherweise ein weiterer Weg ist, Ihr Ziel zu erreichen.Und als letztes unter den Lösungen schlage ich vor, dass Sie die
LC_COLLATE
Datei selbst nach der vollständigen und in der Reihenfolge angeordneten Systemzeichentabelle abfragen können . Dies scheint nicht einfach zu sein, aber ich habe einige Erfolge erzielt, nachdem ich eslocaledef
wie folgt kompiliert habe :Es ist zwar derzeit fehlerhaft, aber ich hoffe, es zeigt zumindest die Möglichkeit.
AUF DEN ERSTEN BLUSH
Es sah wirklich nicht nach viel aus, aber dann bemerkte ich die
copy
Befehle in der Liste. Die obige Datei scheint zum Beispielcopy
in "en_US" zu sein, und eine andere wirklich große Datei , die sie alle zu einem gewissen Grad zu teilen scheinen, istiso_14651_t1_common
.Es ist ziemlich groß:
Hier ist das Intro zu
/usr/share/i18n/locales/POSIX
:...
Sie können
grep
dies natürlich durchmachen, aber Sie könnten einfach:Stattdessen. Sie würden so etwas bekommen:
... UND MEHR
Es gibt auch ein
luit
UTF-8-pty
Übersetzungsgerät für Endgeräte, das für XTerms ohne UTF-8-Unterstützung als Vermittler fungiert. Es verarbeitet eine Vielzahl von Schaltern - z. B. das Protokollieren aller konvertierten Bytes in einer Datei oder-c
als einfacher|pipe
Filter.Ich habe nie bemerkt, dass es so viel zu diesem Thema gibt - die Locales und Charakterkarten und all das. Dies ist anscheinend eine sehr große Sache, aber ich denke, dass alles hinter den Kulissen weitergeht. Zumindest auf meinem System gibt es ein paar hundert
man 3
ähnliche Ergebnisse für die Suche nach Gebietsschemas.Und auch da ist:
Das wird noch sehr lange dauern.
Die
Xlib
Funktionen erledigen dies die ganze Zeit - diesluit
ist ein Teil dieses Pakets.Die
Tcl_uni...
Funktionen könnten sich ebenfalls als nützlich erweisen.nur ein wenig
<tab>
vervollständigen undman
suchen und ich habe ziemlich viel zu diesem Thema gelernt.Mit
localedef
- können Sie dielocales
in IhremI18N
Verzeichnis zusammenstellen. Die Ausgabe ist flippig und nicht außerordentlich nützlich - überhaupt nicht wie diecharmaps
- aber Sie können das Rohformat so wie oben angegeben erhalten, wie ich es getan habe:Dann
od
können Sie es mit lesen - Bytes und Strings:Obwohl es noch ein langer Weg ist, einen Schönheitswettbewerb zu gewinnen, ist dies eine brauchbare Ausgabe. Und
od
ist natürlich so konfigurierbar, wie Sie es möchten.Ich denke, ich habe auch diese vergessen:
Ich habe sie wahrscheinlich vergessen, weil ich sie nicht zur Arbeit bringen konnte. Ich benutze es nie
Perl
und ich weiß nicht, wie ich ein Modul richtig laden soll. Aber dieman
Seiten sehen ziemlich gut aus. In jedem Fall sagt mir etwas, dass es für Sie weniger schwierig ist, ein Perl-Modul aufzurufen als ich. Und auch diese befanden sich bereits auf meinem Computer - und ich verwende niemals Perl. Es gibt auch einigeI18N
, bei denen ich wehmütig gescrollt habe, weil ich wusste, dass ich sie auch nicht zum Arbeiten bringen würde.quelle
i18n
), die möglicherweise verwendet wurden, um das aktuell verwendete Gebietsschema zu generieren. Die Gebietsschemainformationen stammen wahrscheinlich von/usr/lib/locale/locale-archive
oder/some/dir/LC_CTYPE
, und das ist der Teil, der für mein Gebietsschema relevant ist und in den Dateien gespeichert ist, nach denen ich suche.LC_STUFF
aus dem Archiv mitlocaledef
- es macht das auch. Das kann ich wohl auch testen. Das und so ziemlich alles andere können Sie auch mitstrings
oderod
oder dem Rest ansehen . Ich habe es trotzdem getan. Aber im Übrigen - dascharmaps
ist das Gebietsschema, das Sie derzeit verwenden - und darüberlocaledef
wird auch berichtet. Auch das ist was auchrecode
tut.od,
recode
,uconv
und den Rest. Aber es war mein Fehler - eslocaledef
extrahiert es nicht, es ist derrecode
Wille. Sie müssen auscheckeninfo recode
- und abgesehen von demrecode
Tabellenbefehl, den ich zeige, gibt es fast das Gleiche - und es wird die Dinge auf die gleiche Weise behandeln, denke ich. Es zieht nicht nur Ihren Zeichensatz aus der Luft. Auf jeden Fall hatte ich große Hoffnungen auf dieseperl
Module - haben Sie welche ausprobiert?iswblank(3)
für alle möglichen Zeichenwerte.Zumindest auf GNU-, FreeBSD- oder Solaris-Systemen funktioniert dieser Brute-Force-Ansatz:
Während es sich bei C / POSIX
wchar_t
um einen undurchsichtigen Typ handelt, der keine Beziehung zu Unicode hat und garantiert nur alle vom Gebietsschema des Systems unterstützten Zeichen abdeckt, entsprechen die Werte in der Praxis in den meisten Systemen, die Unicode unterstützen, den Unicode-Codepunkten und die Gebietsschemadefinitionen basieren selbst auf Unicode.Unicode soll eine Obermenge aller bekannten Zeichensätze sein. Wenn Sie also alle gültigen Codepunkte in Unicode (0 bis 0xD7FF und 0xE000 bis 0x10FFFF) durchlaufen, sollten Sie mindestens alle Zeichen auflisten, die von einem bestimmten Zeichensatz unterstützt werden.
Hier verwenden wir die Standard-API für das Gebietsschema des Systems, um zu überprüfen, welche von einem bestimmten Typ sind, und um sie in ihre codierte Form in der Codierung des Gebietsschemas zu konvertieren. Wir verwenden
perl
und seincharnames
Modul nur, um den Namen eines bestimmten Unicode-Codepunkts zu erhalten.Bei Gebietsschemata, die zustandsbehaftete Codierungen wie ISO-2022-JP verwenden, stellen wir sicher, dass das codierte Formular von einem Standardausgangszustand aus angezeigt wird.
Ich habe kein System gefunden, auf dem Gebietsschemas mit einer statusbehafteten Zeichencodierung installiert waren, aber zumindest auf GNU-Systemen ist es möglich, einige zu generieren, damit ein falsches Gebietsschema erstellt werden kann (und zumindest funktionieren GNU-Tools in diesen nicht richtig Gebietsschemas). Mit einem benutzerdefinierten Gebietsschema, das ISO-2022-JP mit einem normalen
ja_JP
Gebietsschema verwendet, erhalte ich beispielsweise Folgendes:Vergleichen mit:
In ISO-2022-JP wechselt
1B 24 42
sequence (\e$B
) von ASCII in einen Zustand, in dem Zeichen als 2 (7-Bit) Bytes ausgedrückt werden (hier 21 21 für diesen IDEOGRAPHIC SPACE). In EUCJP sind es die gleichen Bytes, aber die Zustandsumschaltung erfolgt durch Umdrehen des 8. Bits (A1 = 21 | 0x80
), wodurch es zustandsloser wird.Das bedeutet, dass es in diesen zustandsbehafteten Codierungen mehrere Möglichkeiten gibt, ein bestimmtes Zeichen zu schreiben (z. B. durch Einfügen mehrerer dieser Zustandswechselsequenzen ), und die durch diesen obigen Code gezeigte Sequenz ist nur eine davon (die kanonische aus einer Initiale) Standardzustand).
Während bei einem normalen locale, Zeichen nicht außerhalb 0..0xD7FF, 0xE000..0x10FFFF, für eine sein können Rogue locale kann jedes Zeichen im Bereich von Wchar_t unterstützt werden. Beispielsweise könnte ich ein Gebietsschema erstellen, in dem U + DCBA- oder U + 12345678-Zeichen (oder Zeichen, wenn sie zulässig wären) Leerzeichen sind . Aus diesem Grund möchten Sie diesen Code kompilieren,
-D SUPPORT_ROGUE_LOCALES
um diese abzudecken. Das bedeutet jedoch, dass das Durchsuchen der gesamten Liste viel mehr Zeit in Anspruch nimmt.Ich konnte @ mikeservs Lösung nicht verwenden, da sie
recode
ihre eigenen Konvertierungen verwendet, nicht länger gewartet wird und nur Unicode-Zeichen bis zu 0xFFFF unterstützt, und GNUtr
funktioniert zumindest nicht mit Multi-Byte-Zeichen.Ich konnte @ ChrisDown's nicht verwenden , da
python
es keine Schnittstellen zu den POSIX-Zeichenklassen gibt.Ich habe Perl ausprobiert, aber es ist falsch für Codepunkte zwischen 128 und 255 für Gebietsschemata mit mehreren Bytes außer UTF-8 und verwendet nicht die Konvertierungsbibliotheken des Systems.
quelle
combining
undcombining_level3
(d.iswctype(i, wctype("combining"))