Небольшая проблема с null filehandle в perl
Опубликовано 26.06.2013
Рассмотрим удобную и потому частоиспользуемую конструкцию <> (null filehandle), имитирующую аналогичную фичу из sed и awk, когда один и тот же код может использоваться для чтения из STDIN или из файлов, чьи имена переданы в аргументах командной строки. Такая же конструкция используется в однострочниках с опцией -n:
while(<>){
# do something with line
chomp;
print "got line: [$line]"\n;
}
Проблема в том, что для открытия файлов perl использует встроенный оператор open в форме с двумя аргументами (например, open FH, "$file" где имя файла содержит и режим доступа к нему). Если название файла содержит идентификатор режима доступа, интерпретируемый функцией open ("| cmd", "cmd |" или "> /path/to/file"), то вместо чтения файла выполнится соответствующая команда или файл перезапишется. Так что если приведенный чуть выше код записать в файл под названием getline.pl и выполнить с аргументом "| rm -rf /", то произойдет сами понимаете что.
Выстрелить себе в ногу легко, еще проще этого избежать:
– использовать ключ -T, запрещающий использовать непроверенные данные;
– использовать ключ -i .backup, интерпретирующий все переданные аргументы как файлы;
– преобразовывать @ARGV перед обработкой файлов, как это сделано в ARGV::readonly;
– не использовать конструкцию while(<>) в критичных скриптах;
– иногда перечитывать perlsec.
Такие дела.
