有没有办法以编程方式检查单个C source file
是否有潜在危害?
我知道没有检查会产生100%的准确率 - 但我很感兴趣至少做一些基本检查,如果某些表达式/关键字会引发一个红旗被发现。有关寻找什么的想法?
注意:我要检查的文件尺寸相对较小(最多100行),实现数值分析功能,所有这些功能都在内存中运行。代码中不得使用外部库(math.h除外)。此外,不应使用I / O(函数将使用内存数组运行)。
鉴于上述情况,我是否可以执行编程检查至少尝试检测有害代码?
注意:因为我不期望任何I / O,如果代码执行I / O - 它被认为是有害的。
答案 0 :(得分:8)
是的,有一些程序化方法可以检测出与您有关的条件。
在我看来,理想情况下,您需要一个静态分析工具来验证代码的预处理版本:
通过预处理,您可以摆脱检测宏,可能是错误的宏内容以及实际使用宏的问题。此外,您不希望涉及标准C头中的所有宏定义;因为它们所包含的所有历史残余,它们会伤害你的灵魂。
如果代码仅在标准库中调用自己的函数和可信函数,则不会调用任何令人讨厌的函数。 (注意:它可能通过指针调用某个函数,因此这个检查要么需要函数点分析,要么需要间接函数调用的协议,这对于进行数值分析的代码来说实际上可能是合理的。)
使用指针检查错误内容的目的是,它不会滥用指针来制造令人讨厌的代码并将控制传递给它。第一个意思是“没有强制转换为int的指针”,因为你不知道int的位置: - }
对于who-do-it-call检查,您需要解析代码和名称/类型解析每个符号,然后检查呼叫站点以查看它们的去向。如果你允许指针/函数指针,你需要一个完整的点分析。
标准静态分析工具公司之一(Coverity,Klocwork)可能提供某种限制代码块可能调用的功能的方法。如果这不起作用,你将不得不依赖于我们DMS Software Reengineering Toolkit之类的更通用的分析机制 及其C Front End。 DMS提供可定制的机制来构建任意静态分析器,用于作为前端提供的语言描述。 DMS可以配置为完全执行测试1)包括预处理步骤;它还具有完整的分数和功能点分析器,可用于检查点。
对于2)“不使用恶意指针”,标准静态分析工具公司再次提供一些指针检查。然而,在这里他们有一个更难的问题,因为他们静静地试图推理图灵机。他们的解决方案是错过案例或报告误报。我们的CheckPointer工具是动态分析,也就是说,它会在运行时监视代码,如果有任何误用指针的尝试,CheckPointer会立即报告有问题的位置。哦,是的,CheckPointer禁止从int到指针的强制转换: - }所以CheckPointer不会提供静态诊断“这段代码可以作弊”,但如果它真的试图作弊,你会得到一个诊断。 CheckPointer具有相当高的开销(所有检查都需要花费一些成本),所以你可能希望用它来运行代码一段时间以获得一些不会发生任何不良事件的信念,然后停止使用它。
编辑:另一张海报说关于静态定义缓冲区的缓冲区覆盖,你可以做很多事情。 CheckPointer将进行这些测试等。答案 1 :(得分:3)
如果你想确保它没有调用任何不允许的内容,那么编译一段代码并检查它链接到什么(比如通过nm
)。由于您通过“编程”方法挂断了这一点,只需使用python / perl / bash进行编译,然后扫描目标文件的名称列表。
对于静态定义的缓冲区缓冲区覆盖,你可以做很多事情,但你可以链接到电子围栏类型的内存分配器,以防止动态分配的缓冲区溢出。
您还可以编译并链接有问题的C文件,该驱动程序会在valgrind下运行时为其提供典型数据,这有助于检测不良或恶意编写的代码。
但是,最后,你总是会遇到“这个例程终止”的问题,这个问题因为不可判断而闻名。解决这个问题的一个实际方法是编译你的程序并在一段合理的时间之后从一个驱动程序运行它alarm
- 。
编辑:显示使用nm
的示例:
创建一个定义函数foo
的C片段,该函数调用fopen
:
#include <stdio.h>
foo() {
FILE *fp = fopen("/etc/passwd", "r");
}
使用-c
进行编译,然后查看生成的目标文件:
$ gcc -c foo.c
$ nm foo.o
0000000000000000 T foo
U fopen
在这里,您将看到foo.o
目标文件中有两个符号。一个是foo
定义的,我们写的子程序的名称。还有一个是未定义的,fopen
,当目标文件与其他C文件和必要的库链接在一起时,它将链接到它的定义。使用此方法,您可以立即看到编译对象是否引用了自己定义之外的任何内容,并且根据您的规则,可以认为是“不好”。
答案 2 :(得分:0)
您可以对“坏”函数调用(如网络IO或程序集块)进行一些明显的检查。除此之外,我想不出你只能用C文件做什么。
考虑到C的本质,你只需要编译甚至开始。宏等对C代码进行静态分析非常困难。