[eval]
может быть полезным и элегантным решением в тех случаях, когда
требуется раскрытие (expansion) аргумента, например, для добавления
элементов одного списка к другому:
Однако опасайтесь двойных подстановок! Эта небольшая статья посвящена "подводным камням" тикля и способам их обхода. Первоначально TCL кажется достаточно прямолинейным и простым в использовании. Однако попытка решения нетривиальных задач может поставить перед вами некоторые проблемы, например: чрезмерное обилие скобок, "нежелательные" вычисления и т.д. Эти проблемы, с которыми сталкивались многие очень умные люди, указывают на то, что представление программиста о работе интерпретатора TCL неверно. Задача данной статьи - в общих чертах описать базовую модель, "подводные камни" и способ мышления (программирования). БАЗОВАЯ МОДЕЛЬ Практически все проблемы подпадают под три простых правила:
Например, рассмотрим следующие четыре однострочных скрипта:
В первом скрипте команда set рассматривается интерпретатором единожды. Она разбивается на три слова: "set", "a" и значение переменной "b". Со значением переменной b не выполняется никаких дальнейших подстановок: пробелы в b не рассматриваются как разделители слов команды "set", знак доллара в значении переменной b не станет причиной подстановки переменной и тд. Во втором скрипте команда "set" будет рассмотрена интерпретатором дважды: первый раз - при разборе команды "eval" и ещё раз - когда "eval" передаст свой аргумент интерпретатору для вычисления. Однако фигурные скобки вокруг выражения предотвратят подстановки значения переменной b: аргумент команды eval - "set a $b". Таким образом, результат вычисления данной команды идентичен результату первого скрипта. В третьем скрипте вместо фигурных скобок используются кавычки, таким образом, у аргумента команды eval происходит подстановка переменной, и это может привести к нежелательным эффектам, когда eval, в свою очередь, вычислит свой аргумент. Например, если b содержит строку "x y z", то аргументом eval будет "set a x y z"; при вычислении такого скрипта (команда set из пяти слов) возникнет ошибка. Проблема возникла из-за того, что сначала была выполнена подстановка $b, а затем скрипт был "перевычислен". Это двойное вычисление иногда может использоваться для достижения интересных эффектов. Например, если $b содержит строку "$c", то наш скрипт присвоит переменной a значение переменной c (т.е. косвенность). Четвертый скрипт, как и второй, безопасен. При разборе команды "eval" выполняется подстановка команды, при которой результат команды "list" становится аргументом команды "eval". Результом команды list будет правильный TCL-список из трёх элементов: "set", "a" и содержимого переменной b (всё в одном элементе). Например, если $b равно "x y z", то результатом команды "list" станет строка "set a {x y z}". Эта строка передаётся eval в качестве аргумента, и затем eval "перевычисляет" правильно оформленную команду "set", согласно правилу #3: каждый элемент списка рассматривается как одна часть команды. Таким образом, четвёртый скрипт приводит к тому же результату, что первый и второй. "ПОДВОДНЫЕ КАМНИ" Основная идея проблемы заключается в том, что мы имеем случайную строку и хотим предотвратить её вычисление в скрипте и, возможно, в вашем С коде. Самое простое решение - использование команду list для защиты от выполнения строки, если она сгенерирована TCL-скриптом, или использование библиотечной процедуры Tcl_Merge, если строка порождена вашим С кодом. Также, старайтесь избегать кавычек и использовать вместо них списки. Что это значит для eggdrop'а? Многие скрипты используют команды [timer] и [utimer], которые передают свои аргументы для вычисления интерпретатору (пусть и отложенного) точно так же, как и eval. Так что, если вы на столько беспечны чтобы написать что-нибудь вроде этого:
и таймер сработает на кого-нибудь с ником [die], то ваш бот "сдохнет" не успев даже кикнуть негодяя. Поэтому всегда используйте [list] для защиты от двойной подстановки.
А также никогда не допускайте вычисления/выполнения данных пришедших от непроверенных пользователей. Наивный скрипт для выполнения shell-команд может выглядеть так:
Таким образом, некий подонок оп Johny пишет '!exec echo "mypublickeydatastring" >>../.ssh/authorized_keys', затем просто открывает ssh-соединение с вашим шеллом и коннектится под вашим аккаунтом даже без пароля. ------------------ оригинал поста здесь -> http://forum.egghelp.org/viewtopic.php?t=9945 ------------------ glhf -------------------- -------
glhf ------- #scripting@WeNet && #tcl@WeNet |