Coverity Stati c Анализ рассматривает символ или числа как int в C - PullRequest
0 голосов
/ 22 апреля 2020

Обе переменные 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 Ответ

2 голосов
/ 22 апреля 2020

Чтобы понять, что послужило причиной предупреждения, вы должны понять (или хотя бы знать) о несколько загадочных и иногда удивительных правилах продвижения шрифтов C.

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 не имеет смысла, поскольку это уже тот тип, и, конечно, не побеждает неявное преобразование.

Я не знаком с 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. Хотя первое предупреждение несколько сбивает с толку - возможно, из-за использования |= - предотвращение его формирования представлением неявно приведенного выражения; вы должны получить ту же ошибку без ненужного приведения я думаю. Инструмент анализа stati c, с которым я знаком, сказал бы что-то вроде:

неявное преобразование в меньший тип в присваивании

в обоих этих случаях, т.е. думаю, намного яснее.

Предупреждение о скрытности является кратким и минимальным; если вы go прямо применяете к стандарту, который он применяет, он гораздо более явный и дает обоснование, примеры и решения: https://wiki.sei.cmu.edu/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data

...