36

Вдохновлен сегодняшней статьей DailyWTF.

Автор утверждает, что файл C:\Program.exe будет выполняться при нажатии на ярлык, например, C:\Program Files\Doom 2\doom2.exe -nomusic .

Предположительно, Windows сначала пытается вызвать C:\Program с аргументами Files\Doom 2/doom2.exe -nomusic .

Если C:\Program.exe , он пытается C:\Program Files\Doom с аргументами 2/doom2.exe -nomusic .

И если нет C:\Program Files\Doom.exe\ , он, наконец, пытается C:\Program Files\Doom 2\doom2.exe -nomusic и завершается успешно.

Это звучит как полная ерунда для меня. Я не могу поверить, что это когда-либо так работало. Комментатор хорошо это формулирует:

Мне трудно поверить, что любая выпущенная версия Windows когда-либо применяла метод проб и ошибок, описанный OP.

Я абсолютно уверен, что в выпущенной версии Windows поведение по умолчанию было безумным. Я испытал это на собственном опыте много, много раз.

Чего я не верю, так это того, что в выпущенной версии Windows было такое умопомрачительное поведение, как описано в статье. Это слишком большой недостаток безопасности, чтобы остаться незамеченным, пока какая-то случайная ежедневная отправка WTF не обнаружит его, по крайней мере, десятилетие спустя, поскольку это должна была быть версия Windows, предшествующая XP.

Отредактируйте для ясности: вот как я сам это проверял.

  1. Нужно скопировать файл notepad.exe в C:\program.exe.
  2. Запустите C:\program files\Internet explorer\iexplore.exe
  3. Блокнот открывается. Это ожидается, потому что он находит что-то под названием C:\program
  4. Переместите progam.exe в C:\program files\Internet.exe
  5. Запустите C:\program files\Internet explorer\iexplore.exe

По мнению автора статьи (и этой статьи от Microsoft), блокнот все равно должен открываться. Но это не так, команда завершается с этим сообщением:

C:\program is not recognized as an internal or external command, operable program or batch file.

Опять же, я не обсуждаю утверждение статьи о том, что C:\program будет вызываться. Я спорю, что Windows рекурсивно пытается каждый каталог, пока не найдет совпадение.

Итак, какая-нибудь версия Windows когда-либо работала таким образом?

2 ответа2

31

Каждая версия Windows, начиная с длинных имен файлов, добавляется таким образом, начиная с Windows 95 и заканчивая Windows 7.

Это поведение задокументировано:

Параметр lpApplicationName может иметь значение NULL. В этом случае имя модуля должно быть первым токеном с пробелами в строке lpCommandLine . Если вы используете длинное имя файла, которое содержит пробел, используйте строки в кавычках, чтобы указать, где заканчивается имя файла и начинаются аргументы; в противном случае имя файла неоднозначно. Например, рассмотрим строку «c:\program files\sub dir\ имя программы». Эта строка может быть интерпретирована несколькими способами. Система пытается интерпретировать возможности в следующем порядке:

c:\program.exe files\sub dir\program name
c:\program files\sub.exe dir\program name
c:\program files\sub dir\program.exe name
c:\program files\sub dir\program name.exe

Что касается того, почему он спрашивает об этом - чтобы он не ломал программы, которые не могут правильно обрабатывать пробелы в именах файлов.

Редактировать Похоже, что команда "Выполнить" не ведет себя так - должна быть добавлена дополнительная логика для обработки именно этого случая. Тем не менее, пытаясь запустить его из любого другого места, в том числе напрямую используя функцию CreateProcess которую большинство приложений будет использовать для запуска команды.

Видят это поведение в действии:

  1. Откройте административную командную строку
  2. Запустите: copy c:\Windows\System32\notepad.exe c:\program.exe
  3. Запустите: c:\Program Files\Internet Explorer\iexplore.exe
  4. Откроется блокнот, сообщающий, что он не может найти Files\Internet Explorer\iexplore.exe
  5. Введите c:\Program Files\Internet Explorer\iexplore.exe в параметре «Выполнить», и IE откроется правильно.

Изменить 2 В случае вашего C:\program files\internet.exe пример; Я считаю, что это мешает интерпретатору командной строки. Он пытается обработать и разбить командную строку на параметры, разделенные пробелами. Таким образом, он принимает C:\program в качестве первого токена и интерпретирует его как имя программы, а остальные как параметры.

Для теста я создал небольшое приложение, которое напрямую вызывает CreateProcess и ведет себя точно так, как описано в документации. Ваш C:\program files\internet.exe пример запуска C:\program files\internet.exe Таким образом, похоже, что поведение зависит от того, как именно выполняется команда - что-то может обрабатывать командную строку перед передачей ее в CreateProcess .

Пример программы:

#include <Windows.h>

void main()
{
    STARTUPINFO si = {0};
    si.cb= sizeof(si);
    PROCESS_INFORMATION pi = {0};

    CreateProcess(NULL, "c:\\program files\\internet explorer\\iexplore.exe",
            NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
}
5

Я просто хочу добавить что-то к предыдущим ответам.

Хотя можно заставить это поведение с помощью усилий, плохого программирования (не RTFM) или не поддающегося проверке идеального шторма, вызванного этой конкретной антивирусной программой, ничто не могло бы вызвать поведение, описанное в статье. Абсолютно ни в коем случае не будет правильно создан ярлык, например, который нацелен на «C:\Program Files\Microsoft\Office\Word.exe», с кавычками, запускает C:\Program.exe. То же самое с Firefox. Черт, в принципе невозможно создать ярлык, который бы не был экранирован должным образом, потому что это сделано разумно.

Если вы создадите ярлык на рабочем столе, указывающий на Firefox, он будет экранирован правильно. Если вы щелкнете правой кнопкой мыши -> Свойства и попытаетесь удалить кавычки, он автоматически вставит их, когда вы нажмете «Применить», даже если C:\Program.exe существует. Когда он анализирует это, я предполагаю, что он либо отдает предпочтение папке, либо рассматривает все перед последним '\' как часть пути. Только если вы вставите два пробела между Program и Files, он будет проанализирован как указывающий на C:\Program.exe с аргументами. Если вы можете отредактировать ярлык в текстовом редакторе (он не является открытым текстом), он может работать.

Как и ярлыки, диалоговое окно «Выполнить» также правильно анализирует строку. Только в относительно низкоуровневой командной консоли он будет некорректно вызывать C:\Program.exe, но не будет пробовать другие различные возможности. То есть он будет неправильно пытаться вызвать «C:\Program.exe», но не будет пытаться вызвать «C:\Program Files\Internet.exe» или что-то еще, даже если такие возможности существуют. Он вернет ошибку, сообщив, что не может найти C:\Program.exe.

И вдобавок ко всему, когда в папке C:\ есть Program.exe, он предупредит вас при запуске и спросит, хотите ли вы его переименовать. Это было проверено для XP, Vista, Windows 7, и теперь я могу проверить Windows 8 (http://goo.gl/eeNCp). Возможно, это было возможно в Windows 9x, но я сомневаюсь в этом.

В итоге, это очевидно, и ни один программист Windows не допустит этой ошибки.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .