Подтвердить что ты не робот

Может ли поведение undefined стирать жесткий диск?

От "Эффективного С++ 3-го издания от Scott Meyers":

Чтобы подчеркнуть, что результаты поведения undefined не предсказуемы и могут быть очень неприятными, опытные программисты на C++ часто говорят, что программы с поведением undefined могут стереть ваш жесткий диск.

В каких обстоятельствах это может произойти?

Например, может ли доступ и запись в местоположения из поврежденной памяти массива, которая не принадлежит этой программе или потоку С++?

4b9b3361

Ответ 1

Может ли это? Конечно. Фактически, случилось со мной.

Я написал код для удаления временного каталога. Это связано с созданием команды recursive delete <temp directory>\*.*. Из-за ошибки поле <temp directory> не всегда заполнялось. Наш код файловой системы с радостью выполнил команду recursive delete \*.*.

Мои коллеги заметили, как исчезли значки на рабочем столе. Выпустили две машины.

Ответ 2

Если учесть, что UB доступен не только для кода пользовательского режима, но и для системного программиста. Другими словами, если вы пишете драйверный код с UB (или другими ошибками!) В нем, вы можете записать его в кусок памяти, который позже будет записан как "корень всей структуры данных диска",

У меня действительно была ошибка в драйвере, над которым я работал, что вызвало повреждение диска, потому что драйвер использовал устаревшие указатели (использование указателя после бесплатного). Если вы были UNLUCKY, неиспользуемая память оказалась блоком, принадлежащим файловой системе, поэтому он записывал на диск случайный мусор. К счастью, было не сложно определить, в чем проблема, и мне только нужно было переформатировать диск один раз на моей тестовой системе (при работе с драйверами обычно используются два компьютера, один для сборки кода и один для тестирования код на тестовой машине, как правило, имеет минимальный набор установки и часто часто переформатируется и реконфигурируется относительно часто).

Я не думаю, что упоминание Скотта обязательно означает такую ​​ситуацию, но вполне возможно, что если у вас есть достаточно дикий код, это может привести к почти чему-либо. Включая поиск дыр в системе безопасности (см. Все успешные удары по удалению стека). Вы, вероятно, должны быть ОЧЕНЬ не повезло достичь этого, но люди также выигрывают эти мега-лотереи время от времени, поэтому, если вы можете достичь чего-то, что имеет один шанс в несколько миллионов раз в неделю или раз в месяц, то компьютер, который может выполнять операции много миллионов раз в секунду, может достичь гораздо менее вероятных вещей...

Ответ 3

Из стандарта С++ 11 (фактически из проекта N3337), в разделе 1.3 Термины и определения [intro.defs] (emphasis):

undefined поведение
поведение, для которого этот международный стандарт налагает никаких требований
[Примечание: поведение Undefined можно ожидать, если в этом Международном стандарте отсутствует явное определение поведение или когда программа использует ошибочную конструкцию или ошибочные данные. Допустимое поведение Undefinedварьируется от полного игнорирования ситуации с непредсказуемыми результатами, вести себя во время перевода или выполнение программы в документированном виде, характерном для окружающей среды (с выдачей или без диагностическое сообщение), до завершения перевода или выполнения (с выдачей диагностического сообщения). Многие ошибочные программные конструкции не порождают поведение Undefined; они должны быть диагностированы. - конечная нота]

Из "нет требований" + "непредсказуемых результатов" мы можем заключить, что (теоретически) все может случиться.

Теперь "разумный" компилятор не намеренно испускает код для стирания жесткого диска, например, деления на 0, но это может произойти, если вы возились с файловой системой или, как вы сказали, в случае повреждения памяти (отредактируйте: см. комментарий MSalters о своем собственном ответе).

Пункт здесь: всегда будьте осторожны, чтобы никогда никогда не вызывать поведение Undefined. "Здесь будут драконы".

(На практике может быть трудно быть уверенным в том, что ваша программа четко определена. Там есть какой-то совет. Знайте язык хорошо и держитесь подальше от пыльных углов. Если фрагмент кода кажется подозрительным или слишком сложным, попробуйте переписывайте его, чтобы сделать его проще и понятнее. Всегда компилируйте с самым высоким уровнем предупреждений и не игнорируйте их. Существуют также флаги компилятора, такие как -fcatch-undefined-behavior, и такие инструменты, как lint, которые могут помочь. И, конечно, но немного опоздал.)

Ответ 4

Нарушение памяти может теоретически привести к тому, что ваша программа выполнит неправильный код. Если вам очень повезло, это может быть код, который удаляет материал на вашем жестком диске. Я подозреваю, что вряд ли удастся зайти так далеко, если вы сами не занимаетесь дисковыми операциями низкого уровня.

Я считаю, что смысл заявления заключается в том, что вы должны воспринимать поведение undefined крайне серьезно и делать все возможное для защиты от него (т.е. защитного программирования). Я видел слишком много плохих программистов, наивно полагающихся на поведение undefined, предполагая, что он будет работать одинаково все время. На практике это не предсказуемо, и иногда результат может быть катастрофическим.

Ответ 5

Простым примером может быть то, что вы повредите номер блока, который вы пишете, или имя файла, которое вы собираетесь удалить.

Ответ 6

Да.

Рассмотрим приложение, которое обрабатывает внешний вход (например, компонент веб-приложения) и имеет переполнение буфера, что является довольно распространенным типом поведения undefined.

Злоумышленник замечает это и намеренно создает ввод, который удаляет все данные. (Большинство злоумышленников на самом деле этого не делают: то, что они хотят сделать, это получить ваши данные или разместить контент на вашем сайте, но иногда некоторые хотят стереть ваши файлы.)

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

Урок, который следует избегать, заключается в том, что поведение undefined - это не только вещи, которые могут произойти. Мало того, что вы не ожидаете, что вы не ожидаете (некоторые компиляторы очень хороши в выборе странных оптимизаций, которые являются правильными, когда переменная не изменяется дважды между точками последовательности и делает что-то очень удивительное в противном случае), но могут случиться, что математически крайне маловероятны, потому что кто-то сознательно избегал их пути, чтобы заставить их произойти.

Ответ 7

В Linux любая операция действительна, когда вы являетесь пользователем root. Даже уничтожая вашу корневую файловую систему. rm -rf /

Каждый сегмент кода (с ошибками) успешно выполняется, когда вы root. Предполагается, что все UB предназначены для разрешений sudo.

Ответ 8

[Этот ответ приходит на четыре года. Кто его прочтет? Мы увидим.]

Er, без обид, но некоторые из других ответов ошибочны или, во всяком случае, вводят в заблуждение, по моему опыту.

Стандарт С++ не ограничивает поведение undefined. Однако операционная система обычно ограничивает его. Причина: поведение undefined относительно С++.

... всегда будьте осторожны, чтобы никогда не ссылаться на поведение undefined.

Глупости. Опыт опровергает это предположение. Программисты на C++ часто непреднамеренно вызывают поведение undefined во время тестирования. Иногда я делаю это нарочно, просто чтобы посмотреть, что произойдет.

Теперь я понимаю, что кто-то думает, что я щеголяю безрассудством здесь, но на самом деле, ваш ноутбук вряд ли поймает огонь с undefined, чем определено поведение. undefined поведение в С++ испускает код сборки с определенным поведением. Подумай об этом. Поведение сборки остается определенным. Это просто, что стандарт С++ больше не понимает механику.

Иногда вы хотите спровоцировать поведение undefined, чтобы увидеть, что происходит в стеке.

Если вы находитесь в среде, в которой можно написать определенную С++-программу, которая загорается на вашем ноутбуке, тогда вам нужно быть осторожным в любом случае; но главная проблема в этом случае - отсутствие защиты от аппаратного и/или ядра.

В сумме, не позволяйте стандарту С++ путать вас. Он просто информирует вас о том, каковы его собственные пределы компетенции.