Apa yang bisa menjadi cara untuk mengambil daftar semua karakter dalam kelas karakter tertentu (seperti blank
, alpha
, digit
...) di lokal saat ini.
Contohnya,
LC_ALL=en_GB.UTF-8 that-command blank
idealnya, pada sistem Debian saya, akan menampilkan sesuatu seperti:
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
Dan di lokal C dapat menampilkan sesuatu seperti:
09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE
Yaitu, representasi karakter di lokal dalam hal array byte, (seperti UTF-8 dalam contoh pertama, dan byte tunggal pada yang kedua), kode karakter Unicode yang setara, dan deskripsi.
Konteks
(sunting) Sekarang kerentanan telah lama ditambal dan diungkapkan, saya dapat menambahkan sedikit konteks.
Saya mengajukan pertanyaan itu pada saat saya sedang menyelidiki CVE 2014-0475 . glibc
memiliki bug yang memungkinkan pengguna menggunakan lokal seperti LC_ALL=../../../../tmp/evil-locale
yang diselesaikan relatif terhadap jalur pencarian lokal sistem standar dan dengan demikian memungkinkan untuk menggunakan file apa pun sebagai definisi lokal.
Saya bisa membuat lokal nakal misalnya dengan satu byte per karakter charset di mana sebagian besar karakter kecuali s
, h
dan beberapa lainnya dianggap kosong dan itu akan bash
dijalankan sh
ketika mengurai /etc/bash.bashrc
file Debian yang khas (dan yang dapat digunakan untuk mendapatkan akses shell pada sebuah git
hosting server misalnya disediakan bash
digunakan sebagai shell login dari git
pengguna server dan bahwa ssh
server menerima LC_*
/ LANG
variabel dan bahwa penyerang dapat mengunggah file ke server).
Sekarang, jika saya menemukan LC_CTYPE
(mengkompilasi definisi lokal) di /tmp/evil
, bagaimana saya mengetahui itu adalah sesuatu yang jahat dan dengan cara apa.
Jadi tujuan saya adalah untuk meng-un-compile definisi lokal tersebut, dan jika tidak, setidaknya tahu karakter mana (bersama dengan encoding mereka) yang ada di kelas karakter yang diberikan.
Maka dengan itu dalam pikiran:
- Solusi yang melihat file sumber untuk lokal (definisi lokal seperti yang ada di
/usr/share/i18n/locale
Debian) tidak ada gunanya dalam kasus saya. - Properti karakter Unicode tidak relevan. Saya hanya peduli dengan apa yang dikatakan penduduk setempat. Pada sistem Debian, bahkan di antara dua lokal sistem UTF-8, apalagi yang nakal, daftar karakter di kelas dapat berbeda.
- Alat-alat seperti
recode
,python
atauperl
yang melakukan byte / multi-byte ke / dari konversi karakter tidak dapat digunakan karena mereka dapat (dan dalam praktiknya melakukan) membuat konversi dengan cara yang berbeda dari lokal.
sumber
/usr/share/i18n/locales/i18n
... yang tentu saja sebagian besar berasal dari Database Karakter Unicode. Tentu saja, akan menyenangkan memiliki perintahlocale
(setidaknya yang GNU) mengambil banyak informasi yang disimpan dalam banyak kategori, hal-hal yang tidak penting adalah LC_CTYPE dan LC_COLLATE. Saya ingin tahu apakah ada API tersembunyi untuk mengambil informasi itu atau mengompilasi informasi lokal.recode
danuconv
dapat memberi Anda apa yang Anda katakan Anda cari. Mungkin bahkan adilluit
danod
kurasa ...perl
sama sekali, saya pikir.LC_CTYPE
hanya denganod -A n -t c <LC_CTYPE | tsort
Mungkin Anda sudah mencobanya, tetapi saya belum pernah mendengarnya sebelumnya dan saya membacanyainfo
dan mengingatkan saya akan hal ini - dan sepertinya berhasil. Ada jugaptx
tapi saya pikir itu kurang relevan. Bagaimanapun, jika Anda belum mencobanya dan memutuskan untuk melakukannya - peringatan yang adil - itu memang membutuhkan sedikit kesabaran. lehman.cuny.edu/cgi-bin/man-cgi?tsort+1Jawaban:
SOLUSI AKHIR YANG MUNGKIN
Jadi saya telah mengambil semua informasi di bawah ini dan menghasilkan ini:
CATATAN :
Saya menggunakan
od
sebagai filter terakhir di atas untuk preferensi dan karena saya tahu saya tidak akan bekerja dengan karakter multi-byte, yang tidak akan ditangani dengan benar.recode u2..dump
keduanya akan menghasilkan keluaran lebih seperti yang ditentukan dalam pertanyaan dan menangani karakter lebar dengan benar.KELUARAN
API PROGRAMMER
Seperti yang saya tunjukkan di bawah,
recode
akan memberi Anda peta karakter lengkap Anda. Menurut manualnya, ia melakukan ini pertama sesuai dengan nilai saat ini dariDEFAULT_CHARSET
variabel lingkungan, atau, jika gagal, ia beroperasi persis seperti yang Anda tentukan:Juga perlu diperhatikan
recode
adalah bahwa ini adalah api :#include <recode.h>
Untuk perbandingan string yang ramah internasional
POSIX
danC
standar mendefinisikanstrcoll()
fungsi:Berikut ini adalah secara terpisah terletak contoh penggunaannya:
Mengenai
POSIX
kelas karakter, Anda telah mencatat Anda menggunakanC
API untuk menemukannya. Untuk karakter dan kelas unicode Anda bisa menggunakan charsetrecode's
dump-with-names untuk mendapatkan hasil yang diinginkan. Dari manualnya lagi :Menggunakan sintaksis yang mirip dengan yang di atas dikombinasikan dengan dataset tes yang disertakan saya bisa mendapatkan peta karakter saya sendiri dengan:
KELUARAN
Tetapi untuk karakter umum,
recode
tampaknya tidak perlu. Ini akan memberi Anda charset bernama untuk semua yang ada di charset 128 byte:KELUARAN
Tentu saja, hanya 128-byte yang diwakili, tetapi itu karena lokal saya, utf-8 charmaps atau tidak, menggunakan charset ASCII dan tidak lebih. Jadi hanya itu yang saya dapat. Jika saya menjalankannya tanpa
luit
menyaringnya,od
akan menggulungnya kembali dan mencetak peta yang sama lagi\0400.
Ada dua masalah utama dengan metode di atas. Pertama, ada susunan susunan sistem - untuk non-ASCII lokal nilai-nilai gigitan untuk rangkaian tidak hanya
seq
mempengaruhi, yang, seperti yang saya pikirkan, kemungkinan merupakan inti dari masalah yang Anda coba selesaikan.Yah,
tr's man
halaman GNU menyatakan bahwa itu akan memperluas[:upper:]
[:lower:]
kelas secara berurutan - tapi itu tidak banyak.Saya membayangkan beberapa solusi yang berat dapat diimplementasikan dengan
sort
tetapi itu akan menjadi alat yang agak sulit untuk API pemrograman backend.recode
akan melakukan hal ini dengan benar, tetapi Anda sepertinya tidak terlalu menyukai program tersebut tempo hari. Mungkin suntingan hari ini akan memberikan cahaya yang lebih bersahabat atau mungkin tidak.GNU juga menawarkan
gettext
fungsi perpustakaan, dan tampaknya mampu mengatasi masalah ini setidaknya untukLC_MESSAGES
konteksnya:Anda juga dapat menggunakan kategori karakter Unicode asli , yang independen terhadap bahasa dan melepaskan kelas POSIX, atau mungkin memanggil yang pertama untuk memberi Anda cukup informasi untuk mendefinisikan yang terakhir.
Website yang sama yang memberikan informasi atas juga membahas
Tcl
sendiri 's POSIX compliant implementasi regex yang mungkin cara lain untuk mencapai tujuan Anda.Dan yang terakhir di antara solusi saya akan menyarankan agar Anda dapat menginterogasi
LC_COLLATE
file itu sendiri untuk peta karakter sistem lengkap dan teratur . Ini mungkin tampaknya tidak mudah dilakukan, tetapi saya mencapai beberapa keberhasilan dengan yang berikut setelah mengkompilasinyalocaledef
seperti yang ditunjukkan di bawah ini:Memang, saat ini, cacat, tapi saya harap itu menunjukkan kemungkinan setidaknya.
DI BLUSH PERTAMA
Itu benar-benar tidak terlihat banyak tetapi kemudian saya mulai memperhatikan
copy
perintah di seluruh daftar. File di atas tampaknyacopy
di "en_US" misalnya, dan satu lagi yang benar-benar besar yang tampaknya mereka semua bagikan pada tingkat tertentuiso_14651_t1_common
.Cukup besar:
Inilah intro untuk
/usr/share/i18n/locales/POSIX
:...
Anda dapat
grep
melalui ini tentu saja, tetapi Anda mungkin hanya:Sebagai gantinya. Anda akan mendapatkan sesuatu seperti ini:
... DAN LEBIH BANYAK
Ada juga perangkat terjemahan
luit
terminal UTF-8 yangpty
saya kira berfungsi sebagai perantara untuk XTerms tanpa dukungan UTF-8. Ini menangani banyak switch - seperti mencatat semua byte yang dikonversi ke file atau-c
sebagai|pipe
filter sederhana .Saya tidak pernah menyadari ada begitu banyak hal ini - peta karakter dan lokal dan semua itu. Ini tampaknya masalah yang sangat besar tapi saya kira itu semua terjadi di belakang layar. Ada - setidaknya di sistem saya - beberapa ratus
man 3
hasil terkait untuk pencarian terkait lokal.Dan juga ada:
Itu akan berlangsung untuk waktu yang sangat lama.
The
Xlib
fungsi menangani ini semua waktu -luit
adalah bagian dari paket itu.The
Tcl_uni...
fungsi mungkin terbukti bermanfaat juga.hanya sedikit
<tab>
penyelesaian danman
pencarian dan saya sudah belajar banyak tentang hal ini.Dengan
localedef
- Anda dapat mengkompilasilocales
dalamI18N
direktori Anda . Outputnya funky, dan tidak terlalu berguna - tidak seperticharmaps
sama sekali - tetapi Anda bisa mendapatkan format mentah seperti yang Anda tentukan di atas seperti yang saya lakukan:Kemudian dengan
od
Anda dapat membacanya - byte dan string:Meskipun masih jauh dari memenangkan kontes kecantikan, itu adalah hasil yang dapat digunakan. Dan
od
dapat dikonfigurasi seperti yang Anda inginkan juga, tentu saja.Saya kira saya juga lupa tentang ini:
Saya mungkin lupa tentang mereka karena saya tidak bisa membuatnya bekerja. Saya tidak pernah menggunakan
Perl
dan saya tidak tahu cara memuat modul dengan benar saya kira. Tapiman
halaman - halamannya terlihat cukup bagus. Bagaimanapun, ada sesuatu yang memberitahu saya Anda akan menemukan memanggil modul Perl setidaknya sedikit lebih sulit daripada saya. Dan, sekali lagi, ini sudah ada di komputer saya - dan saya bahkan tidak pernah menggunakan Perl. Ada juga beberapaI18N
yang saya gulir secara salah dengan mengetahui sepenuhnya bahwa saya tidak akan membuat mereka bekerja juga.sumber
i18n
) yang mungkin atau mungkin tidak digunakan untuk menghasilkan lokal yang saya gunakan saat ini. Informasi lokal mungkin berasal dari/usr/lib/locale/locale-archive
atau/some/dir/LC_CTYPE
, dan itulah bagian yang relevan dengan lokal saya yang disimpan dalam file-file yang saya cari.LC_STUFF
dari arsip Anda denganlocaledef
- itu juga. Saya bisa demo juga, saya kira. Anda juga dapat melihat itu dan hampir semua yang lainnya denganstrings
atauod
yang lainnya. Bagaimanapun, saya melakukannya. Tapi omong-omong -charmaps
adalah lokasi yang Anda gunakan saat ini - danlocaledef
akan melaporkannya juga. Itu juga aparecode
.od,
recode
,uconv
, dan sisanya. Tetapi itu adalah kesalahan saya - bukanlocaledef
itu yang mengekstraknya, tapi iturecode
yang akan. Anda harus memeriksainfo recode
- dan selainrecode
perintah tabel yang saya tunjukkan ada banyak hal yang sama - dan itu akan menangani hal-hal dengan cara yang sama, saya pikir. Itu tidak hanya menarik charset Anda keluar dari udara tipis. Dalam kasus apa pun saya memang memiliki harapan besar untukperl
modul - modul tersebut - apakah Anda mencobanya?iswblank(3)
untuk semua nilai karakter yang mungkin.Setidaknya pada sistem GNU, FreeBSD atau Solaris, pendekatan brute-force ini bekerja:
Sementara per C / POSIX,
wchar_t
adalah tipe buram yang tidak memiliki hubungan dengan Unicode dan hanya dijamin untuk mencakup semua karakter yang didukung oleh lokal sistem, dalam praktiknya, di sebagian besar sistem yang mendukung Unicode, nilainya sesuai dengan poin kode Unicode dan definisi lokal sendiri didasarkan pada Unicode.Unicode dimaksudkan sebagai superset dari semua charset yang dikenal, jadi mengulang semua poin kode yang valid di Unicode (0 hingga 0xD7FF dan 0xE000 hingga 0x10FFFF) harus mencantumkan setidaknya semua karakter yang didukung oleh charset yang diberikan.
Di sini, kami menggunakan API standar lokal sistem untuk memeriksa yang mana dari jenis yang diberikan dan mengonversinya ke bentuk yang disandikan dalam pengkodean lokal. Kami menggunakan
perl
dancharnames
modulnya hanya untuk mendapatkan nama dari titik kode Unicode yang diberikan.Pada lokal yang menggunakan penyandian stateful seperti ISO-2022-JP, kami memastikan formulir yang disandikan ditampilkan dari keadaan awal default.
Saya tidak menemukan sistem yang telah menginstal lokal dengan pengkodean karakter stateful tetapi setidaknya pada sistem GNU, dimungkinkan untuk menghasilkan beberapa sehingga lokal jahat dapat dibuat untuk (dan setidaknya alat GNU tidak berfungsi dengan baik pada mereka lokal). Misalnya, dengan lokal kustom yang menggunakan ISO-2022-JP dengan
ja_JP
lokal normal , saya mendapatkan:Dibandingkan dengan:
Dalam ISO-2022-JP,
1B 24 42
urutan (\e$B
) beralih dari ASCII ke keadaan di mana karakter dinyatakan sebagai 2 (7-bit) byte (di sini 21 21 untuk ruang IDEOGRAPHIC itu). Sementara di EUCJP, itu adalah byte yang sama tetapi pengalihan status dilakukan dengan membalik bit ke-8 (A1 = 21 | 0x80
) yang membuatnya lebih stateless.Itu berarti bahwa dalam pengkodean stateful, ada beberapa cara untuk menulis karakter yang diberikan (misalnya dengan memasukkan beberapa urutan switching keadaan ), dan urutan yang ditunjukkan oleh kode di atas hanya salah satunya (yang kanonik dari inisial keadaan default).
Sedangkan untuk lokal normal, karakter tidak boleh di luar 0..0xD7FF, 0xE000..0x10FFFF, untuk lokal jahat , karakter apa pun dalam kisaran yang didukung oleh wchar_t mungkin. Misalnya, saya dapat membuat lokal tempat karakter U + DCBA atau U + 12345678 (atau akan menjadi karakter jika diizinkan) kosong . Itu sebabnya Anda ingin mengkompilasi kode itu dengan
-D SUPPORT_ROGUE_LOCALES
untuk menutupi itu, meskipun itu berarti dibutuhkan lebih banyak waktu untuk memindai seluruh daftar.Saya tidak dapat menggunakan solusi @ mikeserv karena
recode
menggunakan konversi sendiri, tidak lagi dipertahankan dan hanya mendukung karakter Unicode hingga 0xFFFF, dantr
setidaknya GNU tidak bekerja dengan karakter multi-byte.Saya tidak bisa menggunakan @ ChrisDown karena
python
tidak memiliki antarmuka ke kelas karakter POSIX.Saya mencoba Perl, tetapi itu palsu untuk titik kode antara 128 dan 255 untuk multi-byte lokal selain UTF-8 dan tidak menggunakan perpustakaan konversi sistem.
sumber
combining
dancombining_level3
(yaituiswctype(i, wctype("combining"))
)