Что может быть способ , чтобы получить список всех символов в заданном классе символов (как blank
, alpha
, digit
...) в текущей локали.
Например,
LC_ALL=en_GB.UTF-8 that-command blank
в идеале в моей системе Debian должно отображаться что-то вроде:
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
А в локали C может отображаться что-то вроде:
09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE
То есть представление символа в локали в виде массивов байтов (например, UTF-8 в первом примере и одиночного байта во втором), эквивалентной кодовой точки символа Unicode и описания.
контекст
(править) Теперь, когда уязвимость уже давно исправлена и раскрыта, я могу добавить немного контекста.
Я задал этот вопрос во время расследования CVE 2014-0475 . glibc
была ошибка в том, что он позволял пользователю использовать такие локали LC_ALL=../../../../tmp/evil-locale
, которые разрешены относительно стандартного системного пути поиска локали и, таким образом, позволял использовать любой файл в качестве определения локали.
Я мог бы создать мошенническую локаль, например, с одним байтом на символьную кодировку, где большинство символов, за исключением s
, h
и некоторые другие считались пробелами, и это bash
выполнялось бы sh
при синтаксическом анализе типичного /etc/bash.bashrc
файла Debian (и это можно было бы использовать для получения доступа к оболочке в git
Например, предоставленный хост-сервер bash
используется как оболочка для входа git
пользователя сервера, и что ssh
сервер принимает LC_*
/ LANG
переменные и что злоумышленник может загружать файлы на сервер).
Теперь, если я когда-нибудь найду LC_CTYPE
(скомпилированное определение локали) /tmp/evil
, как я узнаю, что это было мошенническое и каким образом.
Поэтому моя цель состоит в том, чтобы откомпилировать эти определения локали и, если нет, хотя бы узнать, какие символы (вместе с их кодировкой) находятся в данном классе символов.
Итак, имея в виду:
- Решения, которые ищут исходные файлы для локали (определения локали, такие как в
/usr/share/i18n/locale
Debian), в моем случае бесполезны. - Свойства символов Юникода не имеют значения. Я забочусь только о том, что говорит язык. В системе Debian, даже между двумя локалями системы UTF-8, не говоря уже о мошеннических, список символов в классе может отличаться.
- Такие инструменты , как
recode
,python
илиperl
что делать байт / мульти-байт / с преобразования символов не может быть использован , как они могут (и на практике делают) сделать преобразование иначе , чем локали.
источник
/usr/share/i18n/locales/i18n
... который, конечно же, в основном из базы данных символов Unicode. Конечно, было бы неплохо иметь командуlocale
(по крайней мере, GNU) извлекает много информации, хранящейся во многих категориях, вещи, которые не являются наиболее важными в LC_CTYPE и LC_COLLATE. Интересно, есть ли скрытый API для извлечения этой информации или компиляции информации о локали.recode
иuconv
может дать вам то, что вы говорите, что вы ищете. Возможно, даже просто,luit
иod
я думаю ...perl
вообще, я думаю.LC_CTYPE
помощью,od -A n -t c <LC_CTYPE | tsort
вероятно, вы уже пробовали это, но я никогда не слышал об этом раньше, и я читал,info
и это напомнило мне об этом - и, похоже, работает. Там тоже,ptx
но я думаю, что это менее актуально. В любом случае, если вы еще не попробовали и решили это сделать - справедливое предупреждение - это требует немного терпения. lehman.cuny.edu/cgi-bin/man-cgi?tsort+1Ответы:
ВОЗМОЖНОЕ ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ
Итак, я взял всю нижеприведенную информацию и придумал это:
ПРИМЕЧАНИЕ :
Я использую
od
в качестве последнего фильтра выше для предпочтения и потому что я знаю, что я не буду работать с многобайтовыми символами, которые он не будет правильно обрабатывать.recode u2..dump
будет генерировать вывод, более похожий на указанный в вопросе, и правильно обрабатывать широкие символы.ВЫХОД
API ПРОГРАММИСТА
Как я покажу ниже,
recode
предоставлю вам полную карту персонажа. Согласно своему руководству, он делает это в соответствии с текущим значениемDEFAULT_CHARSET
переменной среды, или, в случае неудачи, работает точно так, как вы укажете:Также стоит отметить,
recode
что это API :#include <recode.h>
Для международно безвредного сравнения струны
POSIX
иC
стандарты определяютstrcoll()
функцию:Вот отдельно расположенный пример его использования:
Что касается
POSIX
классов персонажей, вы уже отметили, что использовалиC
API, чтобы найти их. Для символов и классов Юникода вы можете использовать кодировкуrecode's
dump-with-names для получения желаемого результата. Из руководства снова :Используя синтаксис, аналогичный приведенному выше, в сочетании с включенным тестовым набором данных, я могу получить свою собственную карту символов:
ВЫХОД
Но для общих персонажей,
recode
видимо, не нужно. Это должно дать вам именованные символы для всего в 128-байтовой кодировке:ВЫХОД
Конечно, представлены только 128 байтов, но это потому, что моя локаль, UTF -8 или нет, использует кодировку ASCII и ничего более. Так что это все, что я получаю. Если бы я запустил его без
luit
фильтрации, яod
бы развернул его и снова напечатал ту же карту до\0400.
Однако у вышеуказанного метода есть две основные проблемы. Во-первых, существует порядок сортировки системы - для локалей, отличных от ASCII, значения укусов для кодировок не просто
seq
влияют, что, как я думаю, вероятно, является ядром проблемы, которую вы пытаетесь решить.Ну, на
tr's man
странице GNU говорится, что она будет расширять[:upper:]
[:lower:]
классы по порядку, но это немного.Я полагаю, что можно было бы реализовать какое-то сложное решение,
sort
но это было бы довольно громоздким инструментом для API программирования бэкэнда.recode
будет делать это правильно, но вы, кажется, не слишком влюбились в программу на днях. Может быть, сегодняшние изменения проливают свет на это, а могут и нет.GNU также предлагает
gettext
библиотеку функций, и кажется, что она способна решить эту проблему, по крайней мере, дляLC_MESSAGES
контекста:Вы также можете использовать нативные категории символов Unicode , которые не зависят от языка и вообще отказываются от классов POSIX, или, возможно, обращаются к первым, чтобы предоставить вам достаточно информации для определения последних.
На том же веб-сайте, который предоставил вышеуказанную информацию, также обсуждается
Tcl
собственная реализация регулярных выражений, соответствующая POSIX, которая может стать еще одним способом достижения вашей цели.И последнее из предложенных решений. Я предлагаю вам опросить сам
LC_COLLATE
файл для получения полной и упорядоченной системной карты символов. Это может показаться нелегким делом, но я добился некоторого успеха со следующим после его компиляции,localedef
как показано ниже:По общему признанию, в настоящее время она несовершенна, но я надеюсь, что она хотя бы продемонстрирует такую возможность.
НА ПЕРВОМ СИНЕСТИ
Это действительно не выглядело так много, но потом я начал замечать
copy
команды по всему списку. Вышеупомянутый файл выглядит, например,copy
в «en_US» , и еще один очень большой файл , которым, похоже, все они в какой-то степени принадлежатiso_14651_t1_common
.Это довольно большое:
Вот вступление к
/usr/share/i18n/locales/POSIX
:...
Вы можете
grep
через это, конечно, но вы можете просто:Вместо. Вы получите что-то вроде этого:
... И БОЛЕЕ
Существует также
luit
терминальноеpty
устройство перевода UTF-8, которое, по-моему, служит посредником для XTerms без поддержки UTF-8. Он обрабатывает много переключателей - таких как запись всех преобразованных байтов в файл или-c
в виде простого|pipe
фильтра.Я никогда не осознавал, что в этом есть что-то особенное - локали, карты персонажей и все такое. Это, очевидно, очень большое дело, но я думаю, что все это происходит за кулисами. По крайней мере, в моей системе есть пара сотен
man 3
связанных результатов для запросов, связанных с локалью.А также есть:
Это будет продолжаться очень долго.
Эти
Xlib
функции обрабатывают все это время -luit
это часть этого пакета.Эти
Tcl_uni...
функции могут оказаться полезными , а также.просто немного
<tab>
доработок иman
поисков, и я многому научился на эту тему.С помощью
localedef
- вы можете скомпилироватьlocales
в своемI18N
каталоге. Вывод фанк, и не очень полезен - совсем не так, какcharmaps
- но вы можете получить необработанный формат, как вы указали выше, как я сделал:Затем
od
вы можете прочитать его - байты и строки:Хотя до победы на конкурсе красоты еще далеко, это полезный результат. И
od
, конечно, настраивается настолько, насколько вы хотите.Я думаю, я тоже забыл об этом:
Я, вероятно, забыл о них, потому что я не мог заставить их работать. Я никогда не использую
Perl
и не знаю, как правильно загрузить модуль. Ноman
страницы выглядят довольно красиво. В любом случае, что-то говорит мне, что вы найдете вызов Perl-модуля, по крайней мере, немного сложнее, чем я. И, опять же, они уже были на моем компьютере - и я никогда даже не использовал Perl. Есть также некоторые,I18N
которые я задумчиво прокручивал, прекрасно зная, что я не заставлю их работать.источник
i18n
), которые могли или не могли быть использованы для создания локали, которую я сейчас использую. Информация о локали, вероятно, поступает из/usr/lib/locale/locale-archive
или/some/dir/LC_CTYPE
, и это часть, относящаяся к моей локали, которая хранится в тех файлах, которые мне нужны.LC_STUFF
из архиваlocaledef
- он тоже это сделает. Думаю, я тоже могу это продемонстрировать. Вы также можете просмотреть это и почти все остальное сstrings
или сod
любым другим . Во всяком случае, я сделал. Но, кстатиcharmaps
, языковой стандарт, которым вы сейчас пользуетесь,localedef
также сообщит об этом. И вот чтоrecode
делает тоже.od,
recode
,uconv
и все остальное. Но это была моя ошибка - дело не вlocaledef
этом, а вrecode
том , что так и будет. Вы должны проверитьinfo recode
- и помимо командыrecode
таблицы, которую я показываю, есть почти то же самое - и она будет обрабатывать вещи таким же образом, я думаю. Он не просто вытаскивает вашу кодировку из воздуха. В любом случае, я возлагал большие надежды на этиperl
модули - вы пробовали их?iswblank(3)
для всех возможных значений символов.По крайней мере, в системах GNU, FreeBSD или Solaris этот метод грубой силы работает:
Хотя для C / POSIX
wchar_t
это непрозрачный тип, который не имеет отношения к Unicode и гарантированно охватывает только все символы, поддерживаемые языковым стандартом системы, на практике в большинстве систем, поддерживающих Unicode, значения соответствуют кодовым точкам Unicode. и определения локали сами основаны на Unicode.Под Unicode подразумевается надмножество всех известных кодировок, поэтому при циклическом обходе всех допустимых кодовых точек в Unicode (от 0 до 0xD7FF и от 0xE000 до 0x10FFFF) должен быть указан как минимум все символы, поддерживаемые данной кодировкой.
Здесь мы используем API стандартного языка системы, чтобы проверить, какие из них имеют заданный тип, и преобразовать его в закодированную форму в кодировке языка. Мы используем
perl
и егоcharnames
модуль только для получения имени из заданной кодовой точки Unicode.В локалях, которые используют кодировки с сохранением состояния, такие как ISO-2022-JP, мы гарантируем, что закодированная форма отображается из исходного состояния по умолчанию.
Я не нашел систему, в которой были установлены языковые стандарты с кодировкой символов с сохранением состояния, но, по крайней мере, в системах GNU, можно сгенерировать некоторые из них, чтобы можно было использовать мошенническую локаль (и, по крайней мере, инструменты GNU не работают должным образом в этих локали). Например, с пользовательской локалью, которая использует ISO-2022-JP с нормальной
ja_JP
локалью, я получаю:Сравнить с:
В ISO-2022-JP
1B 24 42
sequence (\e$B
) переключается из ASCII в состояние, когда символы выражаются в 2 (7-битных) байтах (здесь 21 21 для этого ИДЕОГРАФИЧЕСКОГО ПРОСТРАНСТВА). В то время как в EUCJP это те же байты, но переключение состояний выполняется путем переключения 8-го бита (A1 = 21 | 0x80
), что делает его более не имеющим состояния.Это означает, что в этих кодировках с сохранением состояния есть несколько способов записи данного символа (например, путем вставки нескольких из этих последовательностей переключения состояний ), и показанная последовательность с помощью приведенного выше кода является лишь одним из них (каноническим из начального состояние по умолчанию).
В то время как для обычной локали символы не могут быть за пределами 0..0xD7FF, 0xE000..0x10FFFF, для неконтролируемой локали может быть любой символ в диапазоне, поддерживаемом wchar_t. Например, я мог бы создать локаль, где символы U + DCBA или U + 12345678 (или были бы символами, если бы они были разрешены) являются пробелами . Вот почему вы хотите скомпилировать этот код,
-D SUPPORT_ROGUE_LOCALES
чтобы покрыть их, хотя это означает, что сканирование всего списка занимает гораздо больше времени.Я не мог использовать решение @ mikeserv, так как
recode
использует его собственные преобразования, больше не поддерживается и поддерживает только символы Unicode до 0xFFFF, а GNUtr
по крайней мере не работает с многобайтовыми символами.Я не мог использовать @ ChrisDown's, так как
python
не имеет интерфейсов с классами символов POSIX.Я пробовал Perl, но он является поддельным для кодовых точек между 128 и 255 для многобайтовых локалей, отличных от UTF-8, и не использует системные библиотеки преобразования.
источник
combining
иcombining_level3
(то естьiswctype(i, wctype("combining"))
)