我对dcraw进行了一些模糊处理,发现了一个浮点异常。
这有什么危险?plen
它从损坏的文件中读取一些长度并计算foo[i % plen]
. 如果plen == 0
这是标准未定义的,则 gcc 会引发浮点异常。编辑:并且没有捕获异常(这是C)并且程序终止。
我应该关心吗?有没有可能被利用或导致其他坏事的情况?代码的一种可能的正确行为是注意到文件已损坏并且仅存在。这与扔 FPE 然后退出有何不同?
(我很惊讶我没有找到关于这个的问题,因为这对我来说似乎非常基本。)
我对dcraw进行了一些模糊处理,发现了一个浮点异常。
这有什么危险?plen
它从损坏的文件中读取一些长度并计算foo[i % plen]
. 如果plen == 0
这是标准未定义的,则 gcc 会引发浮点异常。编辑:并且没有捕获异常(这是C)并且程序终止。
我应该关心吗?有没有可能被利用或导致其他坏事的情况?代码的一种可能的正确行为是注意到文件已损坏并且仅存在。这与扔 FPE 然后退出有何不同?
(我很惊讶我没有找到关于这个的问题,因为这对我来说似乎非常基本。)
如果
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
我的机器上(英特尔 x86)。if
假定永远不会进入分支并无条件foo
返回 0。没有 FPE,没有崩溃。(不幸的是,我找不到类似的小例子gcc
。)
...并且 gcc 抛出一个浮点异常。
不完全的。如果代码试图除以零,那就是你的 CPU。但是,如上所述,不能保证完全生成这样的代码。
我怀疑 GCC 在这里定义了任何东西(并且在文档中找不到任何表明这一点的东西)。
我应该关心吗?有没有可能被利用或导致其他坏事的情况?代码的一种可能的正确行为是注意到文件已损坏并且仅存在。这与扔 FPE 然后退出有何不同?
你应该关心。如果运气不好,您的程序可能会处理错误的输入文件,见上文。
并出现错误消息“输入文件无效”。在我看来,这比“浮点异常”要好得多。前者告诉我(作为最终用户)出了什么问题,后者只告诉我软件中存在错误(我会这样认为)。
抛出异常以使您能够在发生意外情况后将系统恢复到明确定义的状态。
抛出的异常不会将系统恢复到明确定义的状态。那是你的责任。任何利用都是基于你如何做的,而不是基于抛出的异常本身。
Regarding "Is there any scenario where this could be exploited or
cause other bad things? "
从异常中恢复完全取决于引发异常的上下文。如果某些计算抛出异常,需要其结果才能继续前进,那么最好停止系统。
但是,如果您的异常是针对可以忽略的或可以提供其他默认选项的东西引发的,那么您肯定可以继续前进。
例如:-
假设我正在使用 boost 程序选项阅读 .ini。由于 .ini 文件中缺少一些变量,因此出现了一些异常。在这种情况下,我可以通过为该变量提供一些合适的默认值来从异常中恢复。