【问题标题】:Coverity Static Analysis considers char or numbers as int in CCoverity 静态分析将 char 或 numbers 视为 C 中的 int
【发布时间】:2020-08-05 07:23:09
【问题描述】:

LHS 和 RHS 变量都是 uint8_t 变量,但问题被报告为“从 int 转换为 unsigned char”。我不明白这怎么会是个问题?

同样适用于 8 位数字

两个问题中列出的所有变量都是 uint8_t

问题 1)

CID 147563 (#2 of 2): Coding standard violation (CERT INT31-C)3. cert_violation: 
Casting (uint8_t)apX_compY_bitmask from int to unsigned char without checking its 
value may result in lost or misinterpreted data.

/* AP_X_Flash_Component_Y_Authenticated */
static uint8_t AP_component_require_auth; 

//Local variable:

uint8_t apX_compY_bitmask = 0u, port;

// other operations

AP_component_require_auth |= (uint8_t)apX_compY_bitmask;

问题 2)

CID 148170 (#1 of 1): Coding standard violation (CERT INT31-C)5. cert_violation: 
Casting major_revision >> 3 from int to unsigned char without checking its 
value may result in lost or misinterpreted data.

函数参数:

void sb_rollb_prot_AP_FW_in_use_update(uint8_t img_idx, uint8_t port, uint8_t major_revision, bool primary_image)

//Local Variable
uint8_t x_loc, y_loc;
y_loc = major_revision >> 3;

【问题讨论】:

  • 您阅读过 CERT 规则吗?您不能让静态分析器检查是否违反了您不知道的编码标准,这很危险。 Read the Friendly CERT-C Manual 可在线免费获得。是的,签名 intuint8_t 之间的疯狂隐式转换是危险的,最终会成为细微错误的来源。
  • 我什至尝试将 u 添加为 3 (3u) 问题仍然存在..
  • @Lundin 另外,我没有得到一分,你的意思是说我不能使用 Coverity 来检查 Cert C 规则...???
  • 我是说:上面提到的规则到底是什么你不明白?或者如果你想让别人告诉你你的代码有什么问题,你需要发布代码,包括变量声明。
  • 我想他们担心你的两个例子中出现的implicit type promotionsAP_component_require_auth |= (uint8_t)apX_compY_bitmask; = AP_component_require_auth = AP_component_require_auth | (uint8_t)apX_compY_bitmask; 其中| 的两个操作数都被隐式提升为int。而在major_revision >> 3; 中,操作数major_revision 被隐式提升为int

标签: embedded coding-style static-analysis coverity xc32


【解决方案1】:

要了解导致警告的原因,您必须了解(或至少了解)C 语言有些晦涩、有时令人惊讶的类型提升规则。

C 位和算术运算符对 intunsigned int较大 类型进行操作,因此当呈现较小类型的操作数时,会发生隐式提升:

以这个“实验”为例:

#include <stdint.h>
#include <stdio.h>

int main()
{
    uint8_t a ;
    uint8_t b ;

    printf( "sizeof(a) = %zu\n", sizeof(a) ) ;
    printf( "sizeof(b) = %zu\n", sizeof(b) ) ;
    printf( "sizeof(a | b) = %zu\n", sizeof(a | b) ) ;
    printf( "sizeof((uint8_t)(a | b)) = %zu\n", sizeof((uint8_t)(a | b)) ) ;
    printf( "sizeof(a >> 3) = %zu\n", sizeof(a >> 3) ) ;
    printf( "sizeof((uint8_t)(a >> 3)) = %zu\n", sizeof((uint8_t)(a >> 3)) ) ;


    return 0;
}

输出(int 是 32 位)是:

sizeof(a) = 1
sizeof(b) = 1
sizeof(a | b) = 4
sizeof((uint8_t)(a | b)) = 1
sizeof(a >> 3) = 4
sizeof((uint8_t)(a >> 3)) = 1

所以在第一种情况下:

AP_component_require_auth |= (uint8_t)apX_compY_bitmask;

uint8_t 强制转换没有任何作用,因为它已经是那种类型,并且肯定不会破坏隐式转换。

我不熟悉 CERT-C 或 Coverity,但在我使用过的类似工具中,可以使用隐式转换来断言表达式是故意的:

AP_component_require_auth = (uint_8_t)(AP_component_require_auth | apX_compY_bitmask) ;

y_loc = (uint8_t)(major_revision >> 3) ;

如您所见,使用|= 无法解决此问题,因为您无法在赋值之前强制转换| 表达式的结果。

但是,如果没有令人信服的理由使用较小的类型,通常最好保持类型一致并避免隐式或显式转换并使用 intunsigned 或相等/更大的整数类型。

这两种情况下的问题是将int 大小的类型分配给uint8_t。尽管第一个警告有点令人困惑——可能是由于使用了|=——阻止它呈现隐式转换表达式;如果没有我认为的不必要的演员表,你应该得到同样的错误。我熟悉的静态分析工具,会这样说:

在赋值中隐式转换为更小的类型

在这两种情况下,我认为这更清楚。

Coverity 警告简洁明了;如果您直接查看它正在执行的标准,它会更加明确并提供基本原理、示例和解决方案:https://wiki.sei.cmu.edu/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data

【讨论】:

  • 隐式转换无法解决问题 CID 154581(第 1 个,共 1 个):违反编码标准 (CERT INT31-C)3。 cert_violation:铸造 AP_component_require_auth | apX_compY_bitmask 从 int 到 unsigned char 而不检查其值可能会导致丢失或误解数据。 AP_component_require_auth = (uint8_t)(AP_component_require_auth | apX_compY_bitmask); 我的代码中是否缺少任何设置或其他内容?
  • 我没有建议将 implicit cast 作为解决方案。恰恰相反。你需要一个 explicit 演员表。我从错误中假设这就是你的意思。该工具似乎希望您测试范围,这在这种情况下是不合理的。公平地说,您的问题要求解释而不是解决方案。 y_loc 分配是否也出现类似错误?
  • 如果该工具会让您跳过不必要的障碍,那么也许:AP_component_require_auth = (uint8_t)(0xff &amp; (AP_component_require_auth | apX_compY_bitmask));?如果无法获得让步并使用 Coverity 用来抑制特定行的警告是合理的。我建议的另一个解决方案是确保类型一致 - 使用 uint32_t 而不是 uint8_t
  • 解释应该会导致解决方案,对吧?你是说 Coverity 工具本身有一些错误,因此它显示错误,没有正确分析?我可以使用 uint32_t,但问题是大小。这是针对嵌入式平台的,这样的错误将近204个,每增加3个字节,会导致额外增加600个字节,这对于32KB数据ram系统来说是巨大的
  • @Kanni1303 除非你的编译器很垃圾,否则它将能够更好地优化代码。但是,与 MISRA-C:2012 等其他编码标准中的其他此类规则相比,这个特定的 CERT-C 规则显得有些繁琐,我发现这些规则要精确得多。 CERT 本身甚至参考了不少于 5 条不同的 MISRA 规则来涵盖这个单一的 CERT 规则。
猜你喜欢
  • 1970-01-01
  • 2014-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多