Статический анализ покрытия рассматривает char или числа как int в C
Обе переменные 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;
1 ответ
Чтобы понять, что вызвало предупреждение, вы должны понимать (или, по крайней мере, осознавать) несколько загадочные, а иногда и неожиданные правила продвижения типов в языке C.
Поразрядные и арифметические операторы C работают с int
или unsigned 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
cast не имеет смысла, поскольку он уже является этим типом, и уж точно не отменяет неявное преобразование.
Я не знаком с CERT-C или Coverity, но в аналогичных инструментах, которые я использовал, неявное приведение может использоваться, чтобы утверждать, что выражение является преднамеренным:
AP_component_require_auth = (uint_8_t)(AP_component_require_auth | apX_compY_bitmask) ;
y_loc = (uint8_t)(major_revision >> 3) ;
Как видите, решить эту проблему с помощью |=
потому что вы не можете затем применить результат |
выражение перед присваиванием.
Однако часто лучше поддерживать соглашение о типах и избегать явных или неявных преобразований и использовать int
, unsigned
или целочисленный тип равного / большего размера, если нет веских причин использовать меньший тип.
В обоих случаях проблема заключается в присвоении int
размер шрифта в uint8_t
. Хотя первое предупреждение несколько сбивает с толку - вероятно, из-за использования|=
- предотвращение формы представления неявно приведенного выражения; я думаю, вы должны получить ту же ошибку без ненужного приведения. Инструмент статического анализа, с которым я знаком, мог бы сказать что-то вроде:
неявное преобразование в меньший тип при присваивании
в обоих случаях, что, на мой взгляд, намного яснее.
Предупреждение Coverity краткое и минимальное; если вы перейдете непосредственно к стандарту, который он применяет, он будет более явным и дает обоснование, примеры и решения: https://wiki.sei.cmu.edu/confluence/display/c/INT31-C.+Ensure+that+ целочисленные + преобразования + не + приводят + к + потерянным + или + неверно интерпретированным + данным