Каковы опасности исключений с плавающей запятой при неверном вводе?
Я запустил нечеткий вывод на dcraw и нашел исключение с плавающей точкой.
Каковы опасности этого? Читает немного plen
из поврежденного файла и вычисляет foo[i % plen]
, Если plen == 0
тогда это не определено стандартом и gcc выдает исключение с плавающей запятой. РЕДАКТИРОВАТЬ: И исключение не перехватывается (это C) и программа завершается.
Должен ли я заботиться? Есть ли сценарий, где это может быть использовано или вызвать другие плохие вещи? Одним из возможных правильных действий кода было бы заметить, что файл поврежден и просто существует. Чем это отличается от броска FPE и затем выхода?
(Я удивлен, что не нашел вопрос по этому вопросу, потому что это кажется мне очень простым.)
3 ответа
Если
plen == 0
тогда это не определено стандартом...
Именно так. Это означает, что компилятор может предположить, что этого не происходит. Этот код, например
int foo(int m, int n) {
if(n == 0) return m % n;
return 0;
}
составлен в
foo: # @foo
xorl %eax, %eax
ret
от clang -std=c99 -S -O2
на моей машине (Intel x86). if
предполагается, что ветвь никогда не будет введена и foo
возвращает 0 безоговорочно. Без FPE, без сбоев. (Я не смог найти похожий маленький пример с gcc
, к несчастью.)
... и gcc создает исключение с плавающей запятой.
Не совсем. Это ваш процессор, если код пытается разделить на ноль. Но, как сказано выше, нет никакой гарантии, что такой код будет сгенерирован вообще.
Я сомневаюсь, что GCC что-то здесь определяет (и не смог найти ничего, указывающего на это в документации).
Должен ли я заботиться? Есть ли сценарий, где это может быть использовано или вызвать другие плохие вещи? Одним из возможных правильных действий кода было бы заметить, что файл поврежден и просто существует. Чем это отличается от броска FPE и затем выхода?
Вы должны заботиться. В случае неудачи ваша программа может продолжить работу с неверным входным файлом, см. Выше.
И сообщение об ошибке "Неверный входной файл". на мой взгляд, гораздо приятнее, чем просто "исключение с плавающей точкой". Первый говорит мне (как конечному пользователю), что не так, а второй говорит мне, что в программном обеспечении есть ошибка (я бы посчитал ее такой).
Исключения выдают, чтобы вы могли восстановить систему в четко определенное состояние после непредвиденных событий.
Брошенные исключения не восстанавливают систему до четко определенного состояния. Это ваша ответственность. Любая эксплуатация происходит на основе того, как вы это делаете, а не на основе самого брошенного исключения.
Regarding "Is there any scenario where this could be exploited or
cause other bad things? "
Восстановление после исключения полностью зависит от контекста, в котором было сгенерировано исключение. Если в результате некоторых вычислений возникло исключение, результат которого необходим для продвижения вперед, лучше остановить систему.
Однако, если ваше исключение выдается для чего-то, что может быть проигнорировано ИЛИ для которого могут быть предоставлены другие параметры по умолчанию, тогда вы, безусловно, можете перейти от этого.
Например:
Допустим, я читаю.ini, используя параметры программы повышения. Из-за некоторых пропущенных переменных в файле.ini возникло исключение. в этом случае я могу восстановиться после исключения, указав для этой переменной подходящее значение по умолчанию.