Есть ли способ в Ruby/Rails для выполнения кода, который находится в строке?
Итак, у меня есть база данных различных образцов кода (чтение фрагментов).
Образцы кода создаются пользователями.
Есть ли способ в Rails выполнить его?
Итак, например, у меня есть следующий код в моей базе данных (с id = 123):
return @var.reverse
Есть ли способ для меня выполнить его? Что-то вроде:
@var = 'Hello'
@result = exec(CodeSample.find(123))
Таким образом, результатом будет "olleH"
Ответы
Ответ 1
Вы можете использовать eval
:
code = '@var.reverse'
@var = 'Hello'
@result = eval(code) # => "olleH"
Но будьте очень осторожны в этом; вы даете этому коду полный доступ к вашей системе. Попробуйте eval('exit()')
и посмотрите, что произойдет.
Ответ 2
В ответ eval
(который является правильным) я бы добавил: получите копию Копии книги Киккаса (Programming Ruby или Программирование Ruby 1.9 в зависимости от вашей версии Ruby) и прочитайте главу "Блокировка Ruby в Safe". Эта глава посвящена безопасным уровням Ruby и искаженным объектам, и глава открывается именно вашим прецедентом и почему вам нужно быть параноидальным.
Ответ 3
Существует и другой подход, который вы можете использовать, если у вас очень ограниченный вариант использования или ограничение использования.
Мне пришлось использовать этот подход, чтобы позволить пользователям динамически определять относительные времена, например 3.months.ago
Я использовал регулярное выражение для дезинфекции ввода от таких пользователей
PERMITTED_OPERATIONS = /^\{\%([1-9]\.(day|year|month|hour|minute)(s\.|\.)ago|Time\.now)\%\}$/
def permit?(operation)
return !PERMITTED_OPERATIONS.match(operation.to_s).nil?
end
Вы можете расширить регулярное выражение, чтобы разрешить from_now
, или создать массив регулярных выражений для разрешенных операций и выполнить цикл над ним.
Приветствуем любые комментарии к этому подходу.