ПрограммированиеBackend разработчик

Какая разница между использованием eval BLOCK и eval STRING в Perl, каковы особенности обработки ошибок и безопасности у каждого из вариантов?

Проходите собеседования с ИИ помощником Hintsage

Ответ

В Perl существует два синтаксиса конструкции eval:

  1. eval BLOCK — выполняет блок кода как защищенный блок, перехватывая фатальные ошибки времени выполнения (runtime exceptions). Использует существующий скоуп переменных и не требует компиляции кода во время выполнения.
  2. eval STRING — компилирует и выполняет строку как Perl-код во время выполнения. Может исполнять динамически сгенерированный код и используется для создания динамических подпрограмм, однако опасен с точки зрения безопасности (может исполнить произвольный, потенциально опасный код, особенно если строка формируется из внешних данных).

Особенности обработки ошибок:

  • В обоих случаях фатальная ошибка перехватывается, и в глобальной переменной $@ содержится текст ошибки (если ошибка была), иначе $@ пустой.
  • eval BLOCK быстрее, безопаснее и предпочтительнее, когда не требуется выполнять динамический код.
  • eval STRING удобен для динамического создания кода, но дополнительно компилирует строку, что медленнее и потенциально опаснее.
# Пример использования eval BLOCK my $result = eval { die "Error!" unless 1 + 1 == 2; return "OK"; }; if ($@) { warn "Error caught: $@"; } # Пример использования eval STRING my $code = '$x = 1 + 2; $x;'; my $res = eval $code; if ($@) { warn "Eval string error: $@"; }

Вопрос с подвохом

Если внутрь eval STR рассовать динамически подставляемые переменные без должного экранирования, могут ли возникнуть дополнительные риски?

Да, если подставляемая строка формируется из переменных, особенно полученных извне (например, из ввода пользователя), возникает угроза security/injection. Всегда нужно использовать экранирование или не использовать eval STRING для чужих данных.

my $user_code = 'system("rm -rf /");'; eval $user_code; # ОЧЕНЬ ОПАСНО!

Примеры реальных ошибок из-за незнания тонкостей темы


История

В аудиторском скрипте для проверки параметров виртуальных машин использовался eval STRING, в который "по ошибке" попадали данные, прочитанные из внешнего файла конфигураций. Однажды файл был подменен, что привело к исполнению кода злоумышленника и компрометации сервера.


История

Разработчик обернул потенциально аварийную часть кода в eval BLOCK, ожидая, что он "захватит" не только runtime-ошибки, но и compile-time (например, синтаксические ошибки). Но синтаксическая ошибка (например, опечатка в имени переменной) не перехватывается eval BLOCK — она вызвала аварийное завершение процесса.


История

При десериализации сложных структур данных через eval STRING после Dumper-дампа, забыли убедиться, что строка содержит только допустимый Perl-код — пользователь с помощью input injection добавил исполняемый код, что привело к выполнению вредоносных команд на сервере.