有害的C源文件检查?

有没有办法以编程方式检查单个C source file是否有潜在危害?

知道没有检查会产生100%的准确性 – 但至少有兴趣做一些基本的检查,如果找到一些表达式/关键字会引起一个红旗。 有什么想法的想法?

注意:我要检查的文件大小相当小(最多几行),实现了所有在内存中运行的数值分析function。 代码中不得使用外部库(math.h除外)。 此外,不应使用I / O(函数将与内存数组一起运行)。

鉴于上述情况,我是否可以做一些程序性检查,至少尝试检测有害代码?

注意:因为我不期望任何I / O,如果代码执行I / O – 它被认为是有害的

如果你想确保它没有调用任何不允许的东西,那么编译一段代码并检查它链接到什么(比如通过nm )。 由于您通过“编程”方法挂断了这一点,只需使用python / perl / bash进行编译,然后扫描目标文件的名称列表。

关于静态定义的缓冲区的缓冲区覆盖,你可以做很多事情,但你可以链接到电栅栏类型的内存分配器,以防止动态分配的缓冲区溢出。

您还可以编译并链接有问题的C文件,该驱动程序在valgrind下运行时可以为其提供典型数据,这有助于检测不良或恶意编写的代码。

然而,最后,你总是会遇到“这个例程终止”的问题,这个问题以不可判定而闻名。 解决这个问题的一个实际方法是编译程序并从一个驱动程序运行它,该驱动程序会在一段合理的时间后alarm

编辑 :显示使用nm示例:

创建一个定义函数foo的C片段,调用fopen

 #include  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文件和必要的库链接在一起时,它将与其定义相关联。 使用此方法,您可以立即看到编译对象是否引用了自己定义之外的任何内容,并且根据您的规则,可以认为是“不好”。

是的,有一些程序化的方法来检测与您有关的条件。

在我看来,理想情况下,您需要一个静态分析工具来validation代码的预处理版本:

  1. 不调用任何函数,除了它定义的函数和标准库中的非I / O函数,
  2. 不用指针做任何不好的事情。

通过预处理,您可以摆脱检测宏,可能是错误的宏内容以及实际使用宏的问题。 此外,您不希望涉及标准C头中的所有宏定义; 因为它们所包含的所有历史残骸,它们会伤害你的灵魂。

如果代码只在标准库中调用自己的函数和可信函数,那么它就不会调用任何令人讨厌的函数。 (注意:它可能通过指针调用某个函数,因此这个检查要么需要函数点分析,要么需要间接函数调用的协议,这对于进行数值分析的代码来说实际上可能是合理的)。

使用指针检查错误内容的目的是,它不会滥用指针来制造令人讨厌的代码并将控制传递给它。 第一个意思是“没有强制转换为int的指针”,因为你不知道int的位置: – }

对于who-do-it-call检查,您需要解析代码并命名/类型解析每个符号,然后检查呼叫站点以查看它们的去向。 如果你允许指针/函数指针,你需要一个完整的分析点。

其中一个标准静态分析器工具公司(Coverity,Klocwork)可能提供某种限制代码块可能调用的函数的方法。 如果这不起作用,您将不得不依赖于更通用的分析机制,例如我们的DMS软件再造工具包及其C前端 。 DMS提供可定制的机制来构建任意静态分析器,用于作为前端提供给它的语言描述。 DMS可以配置为完全执行测试1)包括预处理步骤; 它还具有完整的分数和function点,可用于分数检查。

对于2)“不使用恶意指针”,标准静态分析工具公司再次提供一些指针检查。 然而,在这里他们有一个更难的问题,因为他们静静地试图推理图灵机。 他们的解决方案是错过案例或报告误报。 我们的CheckPointer工具是一个动态分析,也就是说,它在运行时监视代码,如果有任何滥用指针的尝试,CheckPointer将立即报告有问题的位置。 哦,是的,CheckPointer禁止从int到指针的强制转换: – }因此CheckPointer不会提供静态诊断“此代码可以作弊”,但如果它实际上试图作弊,您将获得诊断。 CheckPointer具有相当高的开销(所有检查都需要花费一些成本),所以你可能希望用它来运行代码一段时间以获得一些不会发生任何不良事件的信念,然后停止使用它。

编辑:另一张海报说,关于静态定义缓冲区的缓冲区覆盖,你可以做很多事情 。 CheckPointer将执行这些测试等。

您可以对“坏”函数调用(如网络IO或汇编块)进行一些明显的检查。 除此之外,我想不出你只能用C文件做什么。

鉴于C的本质,你只需要编译甚至开始。 宏等对C代码进行静态分析非常困难。