Skip to main content

使用Axivion分析多语言软件项目

回顾:C# P/Invoke 和 Rust FFI  存在安全性隐患 

在本系列的上一篇文章(多语言软件项目中的陷阱)中,我们介绍了在软件项目中,使用 P/Invoke 或 Rust 的 FFI 等技术与 C API 函数交互时可能存在的陷阱和缺陷来源。

例如,函数签名或类型声明的不匹配可能导致以下问题:

  • 崩溃:应用程序或设备停止工作,无法继续使用。
  • 数据丢失:数值被截断或误解,导致错误结果。

这次,我们将分析一个软件模块中的示例错误,该模块使用 P/Invoke 从 C# 调用 C 函数。同样的一般方法和潜在问题适用于 Rust 的 FFI,也适用于 C 语言之外的其他目标语言。

背景铺垫:示例代码

我们有一个由 C# 编写的控制单元和带有 C 语言编写的通信接口的嵌入式设备组成的系统。

使用的 C 语言接口如下:

// exports.h
#pragma pack(push, 1)

typedef struct
{
short id;

int flags;
double value;
} HWCommand;
#pragma pack(pop)

 

extern "C" __declspec(dllexport) void SendCommand(HWCommand cmd);

 

// exports.cpp
extern "C" __declspec(dllexport) void SendCommand(HWCommand cmd)
{
// just print the values
printf("Received Command - id: %d, flags: %d, value: %f", cmd.id, cmd.flags, cmd.value);
}

 

它由一个结构定义 HWCommand 和一个函数 SendCommand 组成,前者由 id、flags 和 value 组成,后者用于向设备发送 HWCommand 实例。在我们的例子中,命令只是打印在控制台上以供展示。SendCommand 函数被标记为__declspec(dllexport),因此可以从其他库中使用。

使用 C 接口的 C# 代码如下:

// Program.cs
SendCommand(new HWCommand() { id = 1, flags = 1, value = 3.14 });

[DllImport("UnmanagedLibrary.dll", EntryPoint = "SendCommand")]
static extern void SendCommand(HWCommand cmd);

public struct HWCommand
{
public short id;
public int flags;
public double value;
}

在这里,我们再次看到了 HWCommand 结构定义,它与 C# 中定义的对应结构相匹配。此外,我们还看到了 SendCommand 的定义,它使用 DllImportAttribute 从我们的非托管库中导入了导出的函数。

请注意,C# 编译器不会也无法验证这些声明是否匹配,或者是否存在具有给定名称的函数。

在运行上述代码时,我们预期产生以下输出结果:

Received Command - id: 1, flags:1, value:3.140000

现在,让我们运行代码,看看我们的预期是否与实际程序执行一致:

Received Command - id: 1, flags:65536, 值: 0.000000

遗憾的是,这些都不是预期值。数据没有正确传输到 "设备 "端,功能无法得到保障!因此,迅速发现这些问题至关重要。然而,正如上一篇博客所述,由于编译器只能独立处理两种语言,因此无法发现潜在的问题。那么如何才能在开发过程的早期发现这些错误,而无需建立复杂的硬件测试环境或编写和运行任何单元测试或集成测试呢?

Axivion 静态代码分析前来救援!

静态代码分析(如 Axivion 所执行的分析)是发现问题的另一个实用工具。

为 C# 和 C/C++ 代码设置 Axivion 项目的构建配置,并在分析中运行/启用 C#-CheckPInvoke 规则 ,就可以在 Axivion 控制面板中查看分析结果:

分析发现了签名不匹配问题,现在我们可以在控制面板中直接查看源代码,进一步探究问题所在:

从右侧面板中可以看到,错误信息提供了有关问题的详细信息。它指出 C/C++ 中定义的结构的大小和对齐方式与 C# 代码中的定义不一致,这就解释了我们在执行代码时看到的错误值。

结论

总之,Axivion 可以帮助查找、理解和修复不同编程语言边界上的错误。否则,这些问题通常很难被发现,因为这些问题无法通过单独考虑参与语言的工具来正确检测。在我们最新的 7.11 版发布中,Axivion 能够同时且一致地分析整体软件系统及其跨语言架构。这既包括 Axivion 架构验证等精细的广度检查,也涵盖对语言间接口的技术深度分析。我们正在努力将 Axivion 对软件项目中各语言相关模块的信息更多地带入跨语言边界,为所涉多语言项目提供全面兼顾架构与语言特性的质量与安全检查。

了解更多

如需进一步了解我们的架构验证和静态代码分析工具请访问我们的网站。您还可以通过互动导览探索 Axivion 静态代码分析工具的实际运作方式

如果您有任何疑问或希望安排演示,请联系我们

了解最新产品新闻和活动:订阅新闻通讯