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