检测应用程序执行逻辑错误的工具

检测应用程序执行逻辑错误的工具

我想检测应用程序执行逻辑中的错误。例如:

  • 忘记调用free()返回的地址malloc()
  • 没有关闭返回的文件句柄open()
  • 无效标志传递给open()
  • 传递给的文件句柄无效poll()
  • write()调用未打开写入的 fd
  • 将无效标志传递给open()例如 open("/etc/fstab", 4)
  • 调用close()无效的 fd
  • ...

我想还有数百个。

也许该工具可以类似于ftrace或运行strace,但包含错误调用的内核日志也足够了。

答案1

忘记调用free()返回的地址malloc()

好吧,mallocfree不是内核调用!什么malloc()(这是一个 libc 库函数,普通用户进程代码!)

  1. 在内存池中查找是否有请求大小的可用块
  2. 如果是,则将其标记为已使用并将其返回给程序,如果不是,则调用sbrk(或等效地,匿名内存的分配很常见)向内核请求一定数量的新虚拟内存页,将它们添加到池中,然后满足程序的要求。

free只是获取之前通过 ; 返回的 s 块内存malloc;如果是,则将其标记为内存池中未使用的。 (如果没有,会发生未定义的行为,但大多数 libc 将在此时中止。)大多数实现free甚至不会尝试将内存返回给操作系统!

现在,如果您想要内存清理,有一些工具(valgrindgcc -fsanitize等)可以监视这些freemalloc调用,甚至可以跟踪 ed 内存块的地址是否malloc仍然“保存”在程序中的某个位置,或者是否在例如当函数结束时,保存该地址的指针将不再存在,因此没有人会记得内存已分配。那将是一个真正的错误;只是不立即释放内存,或者将释放推迟到程序结束根本不是问题。重点malloc是您获得的内存可能具有无限的生命周期! (提示:如果您担心这些事情,并且您这样做是正确的,请不要编写 C。使用允许正确跟踪对象生命周期的语言编写。这将是 Rust 或 C++ 等语言,但后者除非有人将 C++ 视为 C 的扩展。我有一些大型程序,在我的 C++ 代码中从未使用过,new甚至更糟。malloc智能指针可以解决你肩膀上的很多陷阱,即使是在 C++ 中,这也非常重要。允许您可以进行手动内存控制,但在现代变体中,通过提供零成本对象生命周期跟踪也非常鼓励您不要这样做。 )

没有关闭返回的文件句柄open()

那不是问题!与内存相比,将文件保持打开状态直到程序结束是完全可以接受的,甚至是明智的。例如,如果您立即放弃文件锁定,则它们将不起作用。并且控制接口需要保持打开状态,直到程序关闭。

再说一遍,如果您担心在程序的控制流中,您可能会打开数千个文件并忘记关闭它们,请不要使用 C 语言编写,而是使用文件句柄具有生命周期并可以关闭文件句柄的语言编写。不再需要时的底层文件描述符。

只是:“有一个文件已打开,尚未关闭”根本不是问题,尤其不是在 POSIX 系统上,并发文件访问是正常的,并且在许多方面甚至是明确定义的。

无效标志传递给open()

除了返回错误代码之外,你怎么知道这一点?

我的意思是,库检查文件是否可以以“写入+追加”模式打开是很正常的,但如果不能打开也不是问题。

如果您想观察系统调用的任何时间,获取其参数以及它“返回”到用户空间的内容,那么ptrace系统调用就是您的朋友,例如流行strace程序所使用的那样。其他选项包括编写 eBPF 探针或 uprobes,它们可用于非常高效甚至“智能过滤”此类事件的日志记录。

传递给的文件句柄无效poll()

与之前的问题相同,这可能只是您的程序检查文件句柄是否可以被轮询;并非所有(伪)文件系统都是如此。

此外,poll如果需要的话,实际上也是至少由 glibc 提供的包装函数(符号)的名称,并且“无效”可能与系统调用的“无效”不同poll

答案2

其中第一个,未能释放由 分配的内存块malloc(),并不一定涉及内核 — 内存分配由 C 库处理。瓦尔格林德的内存检查可以检测到这些。

要跟踪内核返回的错误,您可以使用以下命令运行程序strace -Z(自strace5.2 起可用):这只会跟踪返回错误的系统调用。您仍然需要对结果进行后处理以查找例如等EBADFDEINVAL

请注意,未能调用free()orclose()并不一定是错误;无论如何,当程序退出时,这些资源都会被释放,因此在某些情况下,不显式放弃资源是完全可以接受的。

答案3

有各种静态代码分析工具可用于查找此类常见的编码错误。我不能说它是否涵盖了您的所有场景,但 SonarQube 就是这样一种支持 C 语言的工具:https://www.sonarqube.org/features/multi-languages/c

C 语言有数百条 SonarQube 规则:https://rules.sonarsource.com/c

SonarQube - C - 应释放动态分配的内存

如果静态代码分析不够,您可能需要动态分析来检查正在运行的程序:https://en.wikipedia.org/wiki/Dynamic_program_analysis

相关内容