Перейти к содержанию

И на старуху бывает проруха

Сегодня решил поделиться отрицательным опытом. Код, приведенный в статье лучше не использовать.

У меня возникла необходимость распарсить файл типа:

xxx yy "zz zz zz zz"

Видно, что однословные поля разделены пробелом, а многословные заключены в кавычки. Распарсить такой файл на awk можно, но не быстро. Нужно писать код.

А на bash - вроде просто:

set -- xxx yy "zz zz zz zz"
echo $# $1 $2 $3

# 3 xxx yy zz zz zz zz

Проверил — вроде работает. Классно, пишу цикл, проверяю на файле — не работает. Упрощаю код до минимума.

REC='xxx yy "zz zz zz zz"'
set -- $REC
echo $# $1 $2 $3

# 6 xxx yy "zz

Очевидно, разбились по пробелам. Перепробовал кавычки — не выходит. Не придумал ничего лучшего, как использовать конструкцию:

REC='xxx yy "zz zz zz zz"'
eval "set -- $REC"
echo $# $1 $2 $3

# 3 xxx yy zz zz zz zz

Все работает как надо.

После этого я решил распарсить реальный лог apache.

Все работало прекрасно, но на определенной строчке все зависало на несколько секунд, а потом продолжалось. Начал разбираться, и когда понял, что происходит — чуть не поседел.

Там была инъекция:

$(ping${IFS}-c${IFS}6${IFS}aa.bb.cc.dd)

Переменная IFS использовалась вместо пробела. Короче, команда выглядела так:

ping -c 6 aa.bb.cc.dd

Ничего страшного. Просто пинг 6 раз на адрес. И этот пинг ИСПОЛНЯЕТСЯ, вызывая задержку. Но команда могла быть и другой. Спасибо дядям за доброту.

Проблема возникла из-за того, что оператор eval разворачивал не только мою переменную, а все переменные, в том числе и из лога, попутно выполняя команды.

В общем, если я раньше считал оператор eval — бесполезным, то теперь я считаю его вредным.

Вот такой опыт.

ㅤЧитать первым в Телеграм

Комментарии