grep segfaults когда передается "-r" и "--exclude-dir", а stdin - это канал

690
Jonathan Hartley

Если я передаю данные в grep И передаю флаг "-r" (recurse subdirs) И передаю флаг "--exclude-dir" (например, чтобы пропустить каталоги ".git"), то он segfaults. Если что-то из этого отсутствует, то это нормально.

$ ls | grep -r --exclude-dir=\.git pattern Segmentation fault 

Кто-нибудь еще видит это поведение?

Я использую grep 2.11 (последний), установленный Homebrew для OSX, потому что встроенный в OSX grep настолько стар, что не поддерживает функции, которыми я интенсивно пользуюсь, например, сам «--exclude-dir».

Вы можете удивиться, почему я передаю эти флаги, так как они оба бессмысленны, когда grep фильтрует стандартный ввод (в отличие от поиска файлов), но причина в том, что эти флаги указаны в псевдониме 'grp':

alias grp='grep -r --exclude-dir=\.git' 

потому что я хочу, чтобы они были включены по умолчанию каждый раз, когда я вручную вызываю grp из командной строки. Мой настоящий «grp» содержит гораздо больше флагов, чем этот, но именно они вызывают у меня проблемы сегодня.

Следовательно, эти флаги полезны (и работают нормально), когда я иду:

grp pattern . 

который, я считаю, должен расшириться до:

grep -r --exclude-dir=\.git pattern . 

Но флаги все еще присутствуют, когда я использую grep в режиме «альтернативного огня», где он фильтрует строки в stdin:

ll | grp pattern 

который, я считаю, должен расшириться до:

ll | grep -r --exclude-dir=\.git pattern 

и это то, что segfaults. Удаление либо '-r' или '--exclude-dir', либо канала на stdin, убирает segfault.

Я посмотрел на созданный файл corefile и нашел это:

$ gdb grep /cores/core.31786 GNU gdb 6.3.50-20050815 (Apple version gdb-1515) (Sat Jan 15 08:33:48 UTC 2011) ... This GDB was configured as "x86_64-apple-darwin" ... #0 0x00007fff8897ac00 in strlen () (gdb) bt #0 0x00007fff8897ac00 in strlen () #1 0x0000000100015576 in excluded_file_name (ex=0x1001005a0, f=0x0) at exclude.c:445 #2 0x0000000100012305 in grepdir (dir=0x0, stats=0x100048620) at main.c:1364 #3 0x0000000100014048 in main (argc=11, argv=0x7fff5fbff0b8) at main.c:2216 

Так что это segfaulting в strlen вызывается из 'exclude_file_name'. Это звучит актуально, но я не знаю, что делать с этой информацией.

Эта схема работала нормально с grep из MacPorts (и до этого в Ubuntu), поэтому я решил, что моя проблема может быть вызвана Homebrew. Поэтому я попытался скомпилировать свой собственный grep из источника GNU 2.11, но поведение сохраняется. Я не могу вернуться к MacPorts - мне пришлось переключиться на Homebrew по другим причинам, и, насколько я понимаю, они не очень хорошо играют вместе.

Между прочим, мне не нравится использовать переменную среды GREP_OPTIONS для установки значений по умолчанию, так как она ломает все инструменты, которые я запускаю, которые вызывают grep внутри.

Итак, мои вопросы:

  • Кто-нибудь еще видит такое поведение, или это только у меня?
  • Могу ли я остановить grep от segfaulting? Или просто понять больше о том, почему это segfaulting?
  • Как бы я изменил свой псевдоним, чтобы он удалял '-r' из команды, когда stdin приходит из канала?
2

1 ответ на вопрос

1
l0b0

Похоже, это может быть регрессия, связанная с последней версией :

** Новые возможности

Если файловый операнд не указан и задана опция командной строки -r или эквивалентная, grep теперь выполняет поиск в рабочем каталоге. Ранее grep игнорировал -r и искал стандартный ввод нерекурсивно. -R, найденный в GREP_OPTIONS, не имеет этого нового эффекта.

Другими словами, поведение -rизменилось и, возможно, не было исчерпывающе проверено перед выпуском. Я бы отправил им сообщение об ошибке - это, скорее всего, приведет к исправлению.

Отличная идея. FWIW: https://savannah.gnu.org/bugs/index.php?35915 Jonathan Hartley 12 лет назад 0
Это известная ошибка в последней версии grep, которая будет исправлена ​​в следующей версии. Фиксация фиксации: http://git.savannah.gnu.org/cgit/grep.git/commit/?id=12c957f786b12a4dd116f9c40a715d671d17fa16 Jonathan Hartley 12 лет назад 0