Каковы опасности исключений с плавающей запятой при неверном вводе?

Я выполнил нечеткость на dcraw и обнаружил исключение с плавающей запятой.

Чем это чревато? Он считывает некоторую длину plen из поврежденного файла и вычисляет foo[i % plen]. Если plen == 0, то это undefined по стандарту, и gcc выдает исключение с плавающей запятой. РЕДАКТИРОВАТЬ: И исключение не перехватывается (это C), и программа завершается.

Должно ли меня это волновать? Есть ли какой-нибудь сценарий, в котором это можно было бы использовать в своих интересах или привести к другим плохим последствиям? Одним из возможных правильных действий кода было бы заметить, что файл поврежден и просто существует. Чем это отличается от запуска FPE с последующим выходом?

(Я удивлен, что не нашел вопроса по этому поводу, потому что это кажется мне очень простым.)


person Unapiedra    schedule 14.11.2014    source источник


Ответы (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 с последующим выходом?

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

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

person mafso    schedule 14.11.2014

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

Выброшенные исключения не восстанавливают систему в четко определенное состояние. Это ваша ответственность. Любая эксплуатация происходит на основе того, как вы это делаете, а не на основе самого выброшенного исключения.

person Oswald    schedule 14.11.2014
comment
Я хотел спросить (см. редактирование), чтобы я не ловил исключение. Так как же система/машина может находиться в плохо определенном состоянии, которое можно использовать? Или можно представить себе какие-либо другие государства, которые в той или иной мере плохи? - person Unapiedra; 14.11.2014

Regarding "Is there any scenario where this could be exploited or 
cause other bad things? "

Восстановление после исключения полностью зависит от контекста, в котором возникло исключение. Если исключение было вызвано какими-то вычислениями, результат которых нужен для продвижения вперед, то лучше остановить систему.

Однако, если ваше исключение выдается для чего-то, что можно игнорировать ИЛИ для чего могут быть предоставлены другие параметры по умолчанию, вы, безусловно, можете уйти от этого.

Например: -

Допустим, я читаю .ini, используя параметры программы повышения. Из-за отсутствия некоторых переменных в файле .ini было некоторое исключение. в этом случае я могу восстановиться после исключения, предоставив этой переменной подходящее значение по умолчанию.

person ravi    schedule 14.11.2014
comment
Одно из возможных правильных действий кода — заметить, что файл поврежден и просто существует. Чем это отличается от запуска FPE с последующим выходом? Поскольку это вызвано поврежденным файлом, мы можем предположить, что разумное восстановление невозможно и нежелательно. Так что, FPE хуже, чем поймать и выйти? (Помимо предоставления более описательного сообщения) - person Unapiedra; 14.11.2014
comment
Что ж, если исключение возникает и никогда не перехватывается, оно завершит вашу программу, не сообщив пользователю, что пошло не так. Итак, лучше перехватить это исключение, а затем отобразить какое-нибудь осмысленное сообщение. - person ravi; 14.11.2014
comment
Спасибо! То есть никакой опасности нет, только удобство для пользователя? - person Unapiedra; 14.11.2014