«Taint» в Перле
Спасибо провидению, в своё время мне удалось несколько лет попрограммировать на Перле. Язык (заслуженно) ругают, но там есть много интересных вещей, которые не грех бы перенести и в другие языки.
Например, хорошей вещью, на мой взгляд, является «taint» («загрязнение») — это специальная метка на переменной, что в ней лежат недоверенные данные, смешивание доверенных и недоверенных данных приводит к «загрязнению» результата. Недоверенными данными является весь ввод — то, что пришло со входного потока, прочитано из файлов и так далее, доверенными — то, что произвела сама программа. Например:
my $a = "hello"; # доверенные данные
my $b = <>; # «загрязённые» (строка, прочитанная из входного потока)
$a .= $b; # данные в переменной $a стали «грязными»«Грязные» данные (если включен соответствующий режим), при попадании в операции, где они могут представлять угрозу для безопасности (например, пользовательский ввод напрямую попадает в функцию языка для удаления файла), генерируют специальное сообщение.
Вот, например, что будет если я добавлю в конец предыдущего кода вызов unlink (эта функция удаляет файл в Перле) с переменной «a», в качестве аргумента:
Insecure dependency in unlink while running with -T switch at sample.pl line 6, <> line 1Причём выполнение программы прервётся в этом месте.
«Грязные» данные можно отчистить, например, пропустив их через регулярное выражение (предполагается, что в этом случае вы проверяете их на корректность и выбираете только то, что безопасно для вашей программы), за подробностями отсылаю в документацию, она простая и понятная, даже если вы плохо знаете английский.
Было бы полезно иметь такой же механизм в ПХП — это помогло бы свести многие уязвимости к нулю, например, внедрение скриптов в код ХТМЛ
Справедливости ради, «taint» есть не только в Перле, насколько я знаю, этот же механизм используется в Руби и одно время был реализован в ДжаваСкрипте.
Комментарии 47
Для подобных вещей, кстати,
У всех «грязных» переменных используется спецпрефикс. Присвоение грязной к чистой видно на кодревью.
PS: а устранять
PPS: ctrl+enter не работает ;)
Можно «запачкать» расширяемые значения специальным вызовом, если это необходимо (вообще, данные должны автоматически «пачкаться»).
Разве она для этого была придумана? Вот уж вряд ли :) Спецпрефикс — это такой же «ручной» способ, как и всё остальное.
Не спорю.
Я знаю, лениво чинить :)
А чем она тут поможет?
Комментарий для Евгения Степанищева:
Ну как это чем? Сделайте «грязные» данные отдельным типом и компилятор не позволит передать «грязные» данные в методы, которым нужны данные «чистые». Напишите функцию (любую, а не только регэксп), преобразующую «грязный» тип в «чистый». А перегрузка операторов позволит вам взять в свои руки полный контроль над взаимодействием «грязных» данных с «чистыми».
Естественно, есть поддержка ручной работы с загрязнением/очисткой данных — http://www.parser.ru/docs/lang/opuntainttaint.htm
Ах да, совсем забыл про него. Язык настолько ужасен своим синтаксисом, что из памяти совершенно пропал.
Комментарий для roman.yankovsky.me:
Это просто чуть больше автоматизации, чем «ручной» способ и всё. Данные не «загрязняться» автоматически, если к чистым присоединить «грязные», для разных типов данных (числа, строки) нужны разные «грязные» типы. В общем, не изящно и не спасает от ошибок.
Комментарий для Евгения Степанищева:
Это просто частная не расширяемая попытка реализовать в языке с динамической типизацией то, что статическая типизация позволяет «из коробки» :)
Это было так до изобретения дженериков. Если говорить о современных мейнстримных языках, то тип нужен ровно один.Что-то вроде «class Taint», в котором будет спрятана вся логика и который можно будет использовать и с числами, и со строками, и с чем угодно.
Комментарий для roman.yankovsky.me:
Статическая типизация это не позволяет сделать, ни «из коробки», ни ещёкак-то. Заводить отдельные типы для «грязных» данных — совсем не выход. Это позволяет только пометить данные, но не позволяет автоматически «загрязнять» чистые типы.
помогут-то? Мне было бы интересно, если бы вы рассказали.
как-то помогут (у меня маленький опыт их использования), я правда не вижу, почему способ с дженериками лучше, чем способ с taint. И уж тем более не понимаю о каких «мучениях» идёт речь. Способ Перла в разы проще и к ошибкам не ведёт, не говоря уже о том, что ему не меньше десятка лет и у него большая практика использования.
Как тут дженерики
Пусть даже
Комментарий для Евгения Степанищева:
А не надо их автоматически «загрязнять». Это вы в коде должны указать, где «чистые» данные, а где «грязные». Статическая типизация хороша как раз тем, что позволяет убедиться в корректности работы с типами на этапе компиляции, а не когда у вас на продакшене unlink упадет.
Я говорю лишь о том, что ради частного случая обработки данных пришлось добавлять в язык новую сущность. Что будем делать, если регэкспа не достаточно для контроля «чистоты»? Внутри такого дженерика можно держать совершенно произвольную процедуру валидации. А вот что мне сможет предложить перловый taint? Вызывать дополнительную проверку для уже «очищенных» данных?
Комментарий для roman.yankovsky.me:
Как это, интересно? Предположим, у меня есть путь, я его присваиваю переменной, это чистые данных, я в них уверен, к пути надочто-то добавить (конкатенировать две строки), что чистыми данными не является. Результат должен быть грязным.
Как будто в этом естьчто-то новое. В Си# есть Nullable, например.
Нет. Проверять данные как вздумается, если мы считаем, что отчистили их добела, помечать их как чистые. Всё как обычно.
Применение регулярки к данным само по себе их не очищает. Вот пример из документации:
http://pastebin.com/jWws7mHj
Давайте, чтоб тут много слов не разводить, попробуем сделать так. Вы мне дадите
Так давайте с малого начнём. Пример в статье:
http://pastebin.com/Mii3hNks
Диагностирую статическую типизацию головного мозга. Это просто классика: человек, привыкший к статической типизации, любую методологию из динамической воспринимает как некое извращение, потому что в статической делается иначе. И тут бесполезночто-либо доказывать — стена непонимания и неприятия.
Шрифты выглядят плохо. Но возможно у меня под Windows неправильный DjVu Sans.
Комментарий для dionys.moikrug.ru:
А откуда он у тебя под виндой и зачем?
Комментарий для Леша:
Потому что буква «С» так и читается — «Эс», зачем повторяться?
Комментарий для Евгения Степанищева:
У меня есть софт, портированный с Linux. Вероятно,какой-нибудь дистрибутив притащил шрифт с собой.
Комментарий для Евгения Степанищева:
А буква «К» читается «Ка». Иными словами, слово либо является аббревиатурой с начала и до конца, либо с начала и до конца не является.
Должно быть, надо думать так: «Текст вашего комментария, не ЭйчТиМЭл.» Это вполне безумно,по-моему.
Ой, это уже 300 раз обсудили и обсосали у меня в комментариях. Ещё раз не интересно.
Комментарий для dionys.moikrug.ru:
Ну блин, не знаю что и делать. На винде уродский дежавю, на линуксе — Требушет. Винды, конечно, больше, чем Линуксов, придётся пожертвовать, по всей видимости.
А Segoe UI есть?
У меня Vista, в ней Segoe UI предустановлен. А почему не указать первым Segoe UI, а потом уже DejaVu?
Это выглядит дико, поэтому вопрос возникнет еще триста раз, гарантия 100%.
Потому и спросил — есть или нету. Поставил Сегое первым.
Комментарий для Леша:
Да пусть возникает, это ещё не значит что я должен каждый раз на него отвечать.
Другое дело — документация. Там нельзя ничего русифицировать.
Ну даже потому, что ХТМЛ выглядит как XTML. Если читать бегло, то уже возможна ошибка в понимании.
ЭсКуЭл, ЭсКуЭль, СКуЭл, СКуЛ, Сиквэл. А потом попробуй найти поиском по тексту упоминания.
А навязывать только один правильный? Ради чего? Чтобы не переключать кодировку?
Все это вносит неразбериху.
Сто раз это уже обсуждалось. Я не хочу повторяться. Но вкратце напишу.
На русском надо писать
Надо убирать из сознания ту херню, которая нам навязал поток нерусифицированной жратвы и шмоток, хлынувшей
Извините, что отнял время. Наверное я пропустил эти обсуждения.
Вашу позицию понимаю, но у каждого своя правда.
Жду же с нетерпением!
(саргазм)
И ведь понимаешь, что так и будет, но всё равно надеешься на чудо. А вдруг?
В Django есть
https://code.djangoproject.com/wiki/AutoEscaping
По ссылке, которую я дал, описана реализация маркировки «загрязненности» данных с помощью множественного наследования в python. Я не специалист по движкам шаблонов, но мне такое не попадалось…
class escaped:
pass
class escapedstr(str, escaped):
pass
class escapedunicode(unicode, escaped):
pass
def markescaped(s):
if isinstance(s, escaped):
return s
if isinstance(s, str):
return escapedstr(s)
if isinstance(s, unicode):
return escapedunicode(s)
raise ValueError, «'s' must be str or unicode»
А, вон оно что. В «Твиге» (пхпешный движок) всё попроще: всё считается «грязным», чтобы вывести «как есть», надо использовать фильтр «raw».
Как написано в том же тексте про Django, проблема с «все считается грязным» заключается в том, что есть шанс