IAR CSTAT 分析中的 UNION 类型双关错误

hob*_*bik 5 c static-analysis iar

我在 example.h 文件中有一个这样的类型结构:

typedef union{
uint16_t valNum;
struct{
uint8_t valNumH;
uint8_t valNumL;
};
} valueExp;
Run Code Online (Sandbox Code Playgroud)

我在 example.c 文件中使用这个结构:

uint16_t myFunction(uint16_t tempData){
uint8_t myData[8];
ValueExp mainValue;
mainValue.valNum=tempData;
myData[5]=mainValue.valNumH;

}
Run Code Online (Sandbox Code Playgroud)

当我分析 IAR-CSTAT 分析此函数时,出现此错误:

Union mainValue is written as valNum then read as another field - UNION-type punning
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个消息?

sha*_*eek 4

使用 C 中的静态代码分析器将在特定编译器实现的顶部呈现编码标准(“安全”C 语言子集)。当嵌入式应用程序有安全认证负担时,它有助于防止不安全的构造以及未定义的行为。使用它会导致 C 语言规范提供的可能性范围与源于需求的更严格规则之间的权衡。

\n

根据 IAR C-STAT 文档,这UNION-type-punning是一项涵盖多个标准规则的交叉检查,默认情况下处于启用状态。例如CERT EXP39-C的解释:

\n
\n

如果用于读取联合对象内容的成员与最后用于在对象中存储值的成员不同,则该值的对象表示形式的适当部分将被重新解释为新类型中的对象表示形式: 6.2.6 中描述(有时称为 \xe2\x80\x9ctype 双关语\xe2\x80\x9d 的过程)。这可能是一个陷阱表示。

\n
\n

由所提供的代码片段生成的完整警告消息如下所示:

\n
"main.c",18 Severity-Medium[UNION-type-punning]:Union \'mainValue\' is written as \'valNum\', then read as another field.\n    "main.c",17: ! - Write to union field: mainValue.valNum = tempData\n    "main.c",18: ! - Read from union field: mainValue.valNumH\n
Run Code Online (Sandbox Code Playgroud)\n

需要myFunction()8 位访问。可以按以下方式重写以符合规则UNION-type-punning

\n
uint16_t myFunction(uint16_t tempData) {\n  uint8_t myData[8];\n  valueExp mainValue;\n  mainValue.valNumH=((tempData & 0xFF00U) >> 8);\n  mainValue.valNumL=(tempData & 0x00FFU);\n  myData[5]=mainValue.valNumH;\n/* .... */\n
Run Code Online (Sandbox Code Playgroud)\n

一种解决方法是禁止对受影响的行进行此检查,其中valNumH读取myFunction()

\n
uint16_t myFunction(uint16_t tempData) {\n  uint8_t myData[8];\n  valueExp mainValue;\n  mainValue.valNum=tempData;\n#pragma cstat_suppress="UNION-type-punning"\n  myData[5]=mainValue.valNumH;\n/* ... */\n
Run Code Online (Sandbox Code Playgroud)\n

  • 通过联合进行类型双关**不是**未定义行为,也**不是**“通过不兼容类型的指针访问变量”。根据(草案)C11 标准的脚注 95](https://port70.net/~nsz/c/c11/n1570.html#note95):“如果用于读取联合对象内容的成员不是与最后用于在对象中存储值的成员相同,该值的对象表示形式的适当部分被重新解释为新类型中的对象表示形式,如 6.2.6 中所述” (2认同)