通过静态分析检测缺少 if/else 语句
我试图捕获 if 语句中缺少的未处理的 expressiong 条件。
第一个示例
if (a < 5) {
// Do something
} else {
// handled else condition
}
第二个示例
if (a < 5) {
// Do something
} else if (a >= 5){
// handled else if condition
}
这两个示例是正确的,并且处理了所有可能性。
但我正在尝试解决类似的条件
if ((a < 5) && b > 10) {
// Do something
} else if ((a >= 5) && (b > 10)){
// handled else condition
} else if((a < 5) && (b <= 10)) {
// handled else condition
}
,但这种条件并不能处理所有可能性,并且缺少条件,
} else if ((a >= 5) && (b <= 10)) {
// missing condition which is not handled
}
我正在尝试通过静态分析和使用源代码的抽象语法树来查找此类漏洞。有没有任何算法、方法或任何论文研究这样的问题?
I'm trying to catch missing unhandled conditions of expressiong inside if statements.
First Example
if (a < 5) {
// Do something
} else {
// handled else condition
}
Second Example
if (a < 5) {
// Do something
} else if (a >= 5){
// handled else if condition
}
this two examples are correct and all possibilities are handled.
But I'm trying to cathc the conditions like
if ((a < 5) && b > 10) {
// Do something
} else if ((a >= 5) && (b > 10)){
// handled else condition
} else if((a < 5) && (b <= 10)) {
// handled else condition
}
But this condition does not handle all possibilities and there is a missing condition of
} else if ((a >= 5) && (b <= 10)) {
// missing condition which is not handled
}
I'm trying to find these kind of vulnerability by static analysis and using Abstract Syntax Tree of source codes. Is there any algorithm, approach or any paper which is studied on problem like that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您有类似的代码
并且希望确保处理所有可能性,那么您必须证明公式
A 或 B 或 C
的计算结果始终为true
。如果您所做的只是检查范围,那么我会将此公式转换为联合范式。经过此转换后,您将得到以下形式的公式
,其中每个原子命题的形式为
(x < c)
,(x ≤ c)
,(x > c)
或(x ≥ c)
,其中x
是变量,c
是常量。这些命题可以通过使用以下转换进行组合:(x < c1)
与(x > c2)
一起转换为true
如果(c1 > c2)
(x < c1)
与(x ≥ c2)
一起转换为true
if(c1 ≥ c2)
(x ≤ c1)
与(x > c2)
一起转换为true
if(c1 ≥ c2)
(x ≤ c1)
与(x ≥ c2)
一起转换为true
if(c1 ≥ c2)
现在看看子句
(F1 or F2 or ...)
。一旦您能够执行其中一个转换,整个子句就有效,您可以开始检查下一个子句。如果所有子句都有效,则处理所有可能性。
通用解决方案(其中 if 语句中的条件可以是任何内容)并不是那么简单。例如,如果您想检查
if(f(x) || g(x))
,则可能是f()
或g()
有副作用,或者执行非常复杂的计算。If you have code like
and you want to make sure that all possibilities are handled, then you have to prove that the formula
A or B or C
always evaluates totrue
. If all you do is check for ranges, then I would transform this formula to a conjunctive normal form.After this transformation you have a formula of the form
where each atomic proposition is of the form
(x < c)
,(x ≤ c)
,(x > c)
or(x ≥ c)
, wherex
is a variable andc
is a constant. These propositions can be combined by using the following transformations:(x < c1)
together with(x > c2)
transforms totrue
if(c1 > c2)
(x < c1)
together with(x ≥ c2)
transforms totrue
if(c1 ≥ c2)
(x ≤ c1)
together with(x > c2)
transforms totrue
if(c1 ≥ c2)
(x ≤ c1)
together with(x ≥ c2)
transforms totrue
if(c1 ≥ c2)
Now look at the clause
(F1 or F2 or ...)
. As soon as you are able to perform one of these transformations, then the entire clause is valid, and you can begin checking the next clause.If all clauses are valid, then all possibilities are handled.
A generic solution (where the conditions in the if statements can be anything) is not as trivial. For instance, if you want to check
if(f(x) || g(x))
, it is possible thatf()
org()
have side effects, or perform very complex calculations.如果您希望将问题简化为更普遍的问题,可以将代码转换
为:
合理的编译器会为转换后的版本发出与原始版本相同的代码,现在您可以使用静态分析或测试生成来验证
assert
是否成立,这与验证最后的else
永远不会被采用,这正是您感兴趣的属性。如果上述代码是Java(断言可以是JML注释),C(断言可以是ACSL注释),则存在工具) 或 C#(断言可以是 Spec# 注释)。 Elian Ebbing 的算法很好,但我建议另一种选择,让用作这些工具后端的自动定理证明器来完成这项工作,而无需重新实现确定给定逻辑命题是否为同义反复的轮子。现有的轮子很可能比您所能得到的更好。
C 语言示例,使用 Frama-C 和 Jessie:
断言未验证,表明 Jessie 无法验证最后一个案例是否无法访问。添加
} else if ((a >= 5) && (b <= 10)) {
,断言得到验证。If you wish to reduce your problem to a more general problem, you can transform the code
into:
A reasonable compiler would emit the same code for the transformed version as for the original version, and now you can use static analysis or test generation to verify that the
assert
holds, which is the same as verifying that the lastelse
is never taken, which is exactly the property you are interested in.Tools exist if the above code is Java (the assert can be a JML annotation), C (the assert can be an ACSL annotation), or C# (the assert can be a Spec# annotation). Elian Ebbing's algorithm is fine, but the alternative I suggest it to let the automated theorem provers used as back-end for these tools do the job without re-implementing the wheel that determines if a given logical proposition is a tautology. Chances are that the existing wheels are doing a better job than you'll ever be able to get.
Example in C, using Frama-C and Jessie:
The assertion is not verified, indicating that Jessie wasn't able to verify that the last case was unreachable. Adding
} else if ((a >= 5) && (b <= 10)) {
, the assertion is verified.