<?xml version="1.0" encoding="UTF-8" ?>

<bugzilla version="5.2"
          urlbase="https://bugzilla.altlinux.org/"
          
          maintainer="jenya@basealt.ru"
>

    <bug>
          <bug_id>61099</bug_id>
          
          <creation_ts>2026-10-16 13:56:03 +0300</creation_ts>
          <short_desc>gio bash completion: «unexpected end of file» и потеря введённой строки при TAB-дополнении слова в кавычках</short_desc>
          <delta_ts>2026-10-16 13:56:03 +0300</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>4</classification_id>
          <classification>Development</classification>
          <product>Sisyphus</product>
          <component>glib2</component>
          <version>unstable</version>
          <rep_platform>x86_64</rep_platform>
          <op_sys>Linux</op_sys>
          <bug_status>NEW</bug_status>
          <resolution></resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P5</priority>
          <bug_severity>normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Artem Varaksa">varaksaaa</reporter>
          <assigned_to name="Yuri N. Sedunov">aris</assigned_to>
          <cc>aris</cc>
          
          <qa_contact>qa-sisyphus</qa_contact>

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>302616</commentid>
    <comment_count>0</comment_count>
    <who name="Artem Varaksa">varaksaaa</who>
    <bug_when>2026-10-16 13:56:03 +0300</bug_when>
    <thetext>**Версия:** p11: glib2 2.84.4-alt1 (libgio 2.84.4-alt1), bash5 5.2.37-alt1
Исходники: https://ftp.altlinux.org/pub/distributions/ALTLinux/p11/branch/x86_64/SRPMS.classic/glib2-2.84.4-alt1.src.rpm
Sisyphus: glib2 2.90.1-alt1 (libgio 2.90.1-alt1), bash5 5.2.37-alt2

## Суть

При выполнении TAB-дополнения расположения в командах `gio` (move, copy, cat, list и т. д.) в том случае, если дописываемое слово содержит кавычку (`&quot;` или `&apos;`), в терминал выводится ошибка синтаксиса bash, варианты завершения не показываются, а введённая пользователем строка теряется (оболочка возвращается к пустому промпту, команду приходится вводить заново).

Сообщение в терминале (bash 5.2):

    bash: неожиданный конец файла во время поиска «&quot;»

(для одиночной кавычки: `во время поиска «&apos;»`; в bash 4.4, например ветки p10, при том же сбое выводится дополнительная строка: `bash: синтаксическая ошибка: неожиданный конец файла`).

Обнаружено при вводе FTP-URI в кавычках:

    $ gio move &quot;ftp://&lt;SERVER_IP&gt;:7777/home/test/rn&lt;TAB&gt;
    bash: неожиданный конец файла во время поиска «&quot;»
    bash: синтаксическая ошибка: неожиданный конец файла

Однако ситуация воспроизводится с произвольным словом в кавычках, без FTP-сервера, без монтирований и без бэкендов gvfs: сбой происходит внутри функции завершения, до каких-либо обращений `gio list`.

## Воспроизведение

1. Интерактивный терминал (bash с загруженным bash-completion, например терминал в сессии рабочего стола).
2. Ввести команду без нажатия Enter (сервер из примера не обязан существовать, монтирование не требуется):

       $ gio move &quot;ftp://&lt;SERVER_IP&gt;:7777/home/test/rn

3. Нажать TAB.

Более простой вариант без URI:

       $ gio move &quot;/home/test/
+ TAB — тот же результат.

## Фактический результат

1. В терминал выводится ошибка bash: `неожиданный конец файла во время поиска «&quot;»` (для `&apos;` — `«&apos;»`; в bash 4.4 плюс `синтаксическая ошибка: неожиданный конец файла`).
2. Варианты завершения не показываются.
3. Введённая пользователем строка очищается: последующий ввод и Enter исполняются как самостоятельная команда (проверено: после ошибки введённый один символ исполняется как отдельная команда, т. е. буфер строки пуст).

Тот же результат и при кавычке, закрытой в конце слова (`gio move &quot;ftp://.../rn&quot;` + TAB) — по той же причине, см. «Где».

## Ожидаемый результат

Варианты завершения из указанного расположения (список имён) либо, при отсутствии подходящих имён, отсутствие видимой реакции; введённая строка сохраняется, ошибки в терминал не выводится.

## Где

`/usr/share/bash-completion/completions/gio` — сценарий bash-завершения утилиты `gio`, поставляется подпакетом `libgio` исходного пакета `glib2` (файл `glib/gio/completion/gio` в дереве исходников). Строки 67–69 (нумерация по 2.84.4):

    # Workaround to unescape dir name (e.g. &quot;\ &quot; -&gt; &quot; &quot;)
    local -a tmp=&quot;( ${dir} )&quot;
    local unescaped_dir=&quot;${tmp[0]}&quot;

Этот «workaround» разымыливает имя каталога (например, `\ ` -&gt; ` `), опираясь на давнее поведение встроенных команд bash `local`/`declare`/`typeset`: значение, присваиваемое переменной-массиву, оболочка повторно разбирает как составное присваивание `NAME=(...)` со снятием кавычек (синтаксис составного присваивания описан в справочнике bash, раздел «Arrays»). Для «чистого» `dir` (без кавычек в значении) трюк работает: `local -a tmp=&quot;( /home/test/my\ dir )&quot;` даёт `tmp[0]` = `my dir` с обычным пробелом.

Однако `dir` строится из дописываемого слова (строки 44–54 сценария) и сохраняет введённые пользователем кавычки: при кавычке, закрытой в конце слова, она отрезается вместе с basename, при недописанном слове кавычка и так не закрыта. В обоих случаях значение, попадающее на повторный разбор, содержит неспаренную кавычку, например:

    ( &quot;ftp://&lt;SERVER_IP&gt;:7777/home/test/ )

Далее:

1. bash выводит ошибку `неожиданный конец файла во время поиска «&quot;»` (при выполнении вне интерактивной оболочки сообщение имеет префикс с именем файла и контекстом, например `/usr/share/bash-completion/completions/gio: array assign: строка 1:`);
2. текущая команда прерывается — функция `__gio_location` завершается сразу после этой строки, последующие строки не исполняются;
3. `COMPREPLY` остаётся пустым, поэтому варианты не показываются;
4. в интерактивной оболочке введённая пользователем строка теряется.

Другие сценарии завершения GLib, поставляемые тем же пакетом (`gapplication`, `gdbus`, `gresource`, `gsettings`), такой конструкции не содержат.

## Доказательства (проверено на p11, bash 5.2.37-alt1)

- Интерактивно (pty, `bash -i` с загруженным bash-completion): по описанному сценарию на первый TAB выводится приведённая ошибка; одинаково для `&quot;` и `&apos;`, для слова, оканчивающегося `/`, и для слова с закрытой кавычкой. Буфер введённой строки после этого пуст.
- Контроль без кавычек в слове (`gio move /h` + TAB): дополнение работает (строка дополнена до `/home/`), ошибки нет, строка сохранена.
- Та же конструкция вне механизма завершения:

      $ bash -c &apos;declare -a t=&quot;( \&quot;x )&quot;; echo ok&apos;
      bash: array assign: строка 1: неожиданный конец файла во время поиска «&quot;»

  (`ok` не выводится, rc=1) — подтверждено, что прерывается именно повторный разбор значения присваивания массива, т. е. строка 68 сценария.
- Повторные попытки завершения повторяют ошибку, `COMPREPLY` каждый раз пуст.
- В bash 4.4.23 (p10) поведение то же, при том же сбое выводится обе строки сообщения (это объясняет вторую строку в первичном отчёте); в bash 5.2.37 — одна. Различие лишь в форме вывода ошибки, механизм один и тот же — давнее стабильное поведение встроенных команд bash, не регрессия bash.

## Апстрим

Сценарий — апстримный код (Copyright 2018 Red Hat, https://gitlab.gnome.org/GNOME/glib). Строка «Workaround to unescape dir name» присутствует в сценарии с момента его появления (glib 2.58.0, 2018; первоначально `declare -a`, затем `local -a` — конструкция та же) и сохранена без изменений в актуальном источнике 2.90.1. Апстримные улучшения bash-завершения утилит GLib в 2.81.0 (!3989, !4012, !4013) эту строку не затрагивали; в дереве packages/srpms/g/glib2.git файл идентичен во ветках p11 и sisyphus, ALT-патчи его не меняли.

## Затронутость

- p11 glib2 2.84.4-alt1: **затронут** (воспроизведено на тестовой системе, bash5 5.2.37-alt1)
- Sisyphus glib2 2.90.1-alt1: **затронут** (уровень исходников: `glib/gio/completion/gio` идентичен p11, строки 67–69 на месте)

Баг предсуществующий (сценарий от 2018 года), не является регрессией ни какого-либо релиза glib2, ни bash, ни gvfs: сбой происходит до обращения к `gio list` и воспроизводится без монтирований, серверов и бэкендов gvfs.

## Проверка затронутости

Без терминала достаточно убедиться, что установленный `/usr/share/bash-completion/completions/gio` содержит строку

    local -a tmp=&quot;( ${dir} )&quot;

и что повторный разбор bash срабатывает:

    bash -c &apos;declare -a t=&quot;( \&quot;x )&quot;; echo ok&apos;
    # bash: array assign: строка 1: неожиданный конец файла во время поиска «&quot;»
    # (ok не выводится)

## Просьба

Исправить сценарий завершения `gio` в исходном пакете glib2 так, чтобы дописываемое слово, способное содержать неспаренные кавычки, не попадало на повторный разбор. Например, применять описанный трюк только при отсутствии кавычек в `dir`, а в остальных случаях ограничиться безопасным преобразованием:

    if [[ $dir == *[\&apos;\&quot;]* ]]; then
        unescaped_dir=${dir//\\ / }
    else
        local -a tmp=&quot;( ${dir} )&quot;
        unescaped_dir=&quot;${tmp[0]}&quot;
    fi

(точная формулировка — на усмотрение мейнтейнера). При возможности — передать исправление в апстрим (https://gitlab.gnome.org/GNOME/glib).</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>