Список символов Unicode, которые должны быть отфильтрованы на выходе?

Недавно я столкнулся с ошибкой из-за качества данных при поддержке браузера, и я ищу безопасное правило для применения экранирования строки без двойного размера, если это не требуется.

Последовательность байтов UTF-8 "E2-80-A8" (U+2028, РАЗДЕЛИТЕЛЬ СТРОК), вполне допустимый символ в базе данных Unicode. Однако эта последовательность представляет собой разделитель строк (да, кроме "0A").

И что плохо, многие браузеры (включая Chrome, Firefox и Safari; другие я не тестировал) не смогли обработать обратный вызов JSONP, содержащий строку, содержащую этот символ Unicode. JSONP был включен в не-Unicode HTML, который я не контролировал.

Браузеры просто сообщали об ошибке INVALID CODE/syntax в таком JavaScript, который выглядит допустимым в инструментах отладки и во всех текстовых редакторах. Я предполагаю, что он может попытаться преобразовать «E2-80-A8» в BIG-5 и нарушить синтаксис JS.

Вышеприведенное является лишь примером того, как Unicode может неожиданно сломать вашу систему. Насколько мне известно, некоторые хакеры могут использовать RTL и другие управляющие символы себе во благо. И в спецификации Unicode много «кавычек», «пробелов», «символов» и «элементов управления».

ВОПРОС:

Существует ли список символов Unicode, которые каждый программист должен знать о скрытых функциях (и ошибках), которые мы могли бы не хотеть, чтобы они были эффективными в нашем приложении. (например, Windows отключает RTL в имени файла).

РЕДАКТИРОВАТЬ:

Я не прошу ни JSON, ни JavaScript. Я прошу общую передовую практику передачи Unicode во всех программах.


person Dennis C    schedule 11.05.2012    source источник
comment
Поскольку JSON является общим форматом сериализации для Unicode, ничего фильтровать не нужно, иначе вы нарушите взаимодействие. Когда браузеры неправильно интерпретируют JSON, кодировка которого явно является UTF-8, как другую кодировку, вина лежит на браузерах; и они должны быть исправлены. Gimping JSON не является решением.   -  person daxim    schedule 21.05.2012


Ответы (4)


Существует база данных свойств символов и отчет с ее описанием, БАЗА ДАННЫХ СИМВОЛОВ UNICODE, которая дает хорошая идея о том, как браузеры «должны» обрабатывать кодовую точку. Я люблю это слово «должен». Самым безопасным будет белый список, вы, вероятно, можете использовать L|M|N|S, Letter или Mark, Number или Symbol.

Взгляните на проект ICU для библиотеки.

person jthill    schedule 20.05.2012

Это ломает javascript, потому что в строках не может быть новых строк:

var myString = "

";

//SyntaxError: Unexpected token ILLEGAL

Теперь последовательность UTF-8 "E2-80-A8" декодируется в кодовую точку Юникода U+2028, который обрабатывается аналогично новой строке в javascript:

 var myString = "
";

//Syntax Error

Однако безопасно писать

var myString = "\u2028";
//you can now log myString in console and get real representation of this character

это то, что будет иметь правильно закодированный JSON. Я бы посмотрел на правильное кодирование JSON вместо того, чтобы хранить черный список небезопасных символов. (это U + 2028 и U + 2029 AFAIK).

В PHP:

echo json_encode( chr(0xe2). chr(0x80).chr(0xA8 ) );
//"\u2028"
person Esailija    schedule 11.05.2012
comment
JSON — это только пример. Есть кодировка XML, текст HTML, атрибут HTML, SQL, кодировка URI, имя файла, адрес электронной почты, доменное имя и т. д. В приведенном выше примере УЖЕ используется метод кодирования, предоставленный фреймворком; и в котором явно есть ошибка. Использование API не гарантирует, что escape-символ всегда будет правильным, и вам, возможно, придется делать это самостоятельно, когда он сломается. - person Dennis C; 12.05.2012
comment
Более конкретно, JSONP был сгенерирован Spring MVC API. - person Dennis C; 12.05.2012
comment
@DennisCheung JSONP выполняется как код javascript, а остальные — просто данные, я не понимаю, как они имеют к этому какое-то отношение. Описанная вами проблема применима только к JSONP. - person Esailija; 12.05.2012
comment
Любопытная дыра в том, что U+2028/2029 допустимы в JSON, несмотря на то, что они недействительны в JavaScript (и, следовательно, в JSONP). Хороший кодировщик JSON должен избегать их для совместимости, но на самом деле это делают очень немногие. - person bobince; 14.05.2012
comment
Поэтому и прошу не JS, а Unicode. Бьюсь об заклад, есть дюжина из них, которые должны обрабатываться теми, кто пишет эти escape/encode API для всех мест. - person Dennis C; 15.05.2012
comment
Javascript МОЖЕТ иметь новые строки в сценарии: var s="\n"; Проблема, о которой вы упоминаете, является только синтаксической проблемой. - person dda; 10.12.2016

Посмотрите на таблицы Unicode. Есть список непечатаемых символов. Это те, которые могут стать потенциальными нарушителями спокойствия. У вашего друга U+2028 много друзей: http://www.unicode.org/charts/PDF/U2000.pdf И это касается не только диапазона 2000 года.

Вы можете либо уничтожить их всех, либо разделить их на разные категории (символы SEP, такие как U + 2028, становятся \n или правильно экранируются) и т. д.

ХТН

person dda    schedule 19.05.2012

AZ, az и 0-9 обычно безопасны. За пределами этих 62 символов вы столкнетесь с проблемами в какой-то системе. Другого ответа вам никто не может дать.

Например, вы упоминаете доменные имена. Единственный способ обработки доменных имен Unicode — следовать RFC 3454 и RFC 5890-5893 и обрабатывать данные таким и только таким образом. Имена файлов в большинстве файловых систем Unix представляют собой произвольные строки байтов, которые не включают / или \0. Функциональная обработка имени файла в Unix как строки Unicode без нарушения чего-либо сама по себе является вопросом. Обратите внимание, что имена файлов Windows не являются безопасными от A до Z; такие вещи, как NUL и PRN, являются зарезервированными именами. У каждого домена есть свои маленькие проблемы и причуды, и простого резюме не будет достаточно для всех.

person prosfilaes    schedule 18.05.2012
comment
Это не имеет смысла для меня. Если бы мы могли использовать только A-Z0-9, то зачем UTF-8? Это похоже на возвращение к 7-битной сети BBS, и вы должны использовать Base64 для всего. У Unicode слишком много разработанных функций, которые мы должны изучить и понять, а не игнорировать. - person Dennis C; 19.05.2012
comment
Я не говорю, что не используйте Unicode. Я говорю, что вы спрашивали о системе доменных имен; вам нужно взглянуть на эти RFC 3454 и 5890-5893. Вы спросили об именах файлов; Имена файлов POSIX представляют собой произвольную строку байтов, не содержащую \0 или \x2F. Имена файлов Windows нечувствительны к регистру UTF-16 и требуют исключения набора зарезервированных имен ASCII. Формальные ответы на то, что может идти в них, не имеют ничего общего. - person prosfilaes; 21.05.2012
comment
Имя файла Windows является хорошим примером. RTL действителен в спецификации имени файла (его использовал вирус), но на самом деле он должен быть заблокирован. Вы не можете прочитать это из спецификации/RFC. Даже тому, кто написал RFC, нужно знать Unicode, прежде чем он сможет поместить эти опасные символы в список исключений. - person Dennis C; 21.05.2012
comment
RTL должен быть допустимым в именах файлов для поддержки арабского языка и иврита. Если вы говорите о символе RLO, RFC 3454 упоминает RLO. RLO не является опасным символом в произвольном случае; это может привести к изменению порядка текста в некоторых обстоятельствах, что может привести к путанице. Вы не хотите фильтровать его из произвольного текста, и в большинстве случаев, даже в именах файлов, его блокировка проблематична; вам нужно принять имена файлов, которые находятся на диске. И это только один небольшой домен; ты хочешь знать все. - person prosfilaes; 21.05.2012
comment
unicode.org/reports/tr36 — это список соображений безопасности в Unicode. Как видите, это намного сложнее, чем список символов, и сильно зависит от поставленной вами задачи. - person prosfilaes; 17.06.2012
comment
@prosfilase у тебя лучший ответ - person Dennis C; 18.06.2012