exponenta event banner

Превышена целочисленная точность

Операция с целочисленным размером вместо точности может привести к неопределенному поведению

Описание

Этот дефект возникает, когда целочисленное выражение использует размер целого числа в операции, превышающей целочисленную точность. На некоторых архитектурах размер целого числа в памяти может включать в себя биты знака и заполнения. На этих архитектурах размер целого больше, чем точность, которая является всего лишь количеством битов, которые представляют значение целого числа.

Риск

Использование размера целого числа в операции с целочисленной точностью может привести к переполнению целого числа, обтеканию или неожиданным результатам. Например, целое число без знака может храниться в памяти в 64 битах, но использует только 48 бит для представления его значения. Операция сдвига влево 56 бит для этого целого числа является неопределенным поведением.

Предположение, что размер целого числа равен его точности, также может привести к проблемам переносимости программ между различными архитектурами.

Зафиксировать

Не используйте размер целого числа вместо его точности. Чтобы определить целочисленную точность, выполните процедуру вычисления точности или используйте функцию builtin, такую как __builtin_popcount().

Примеры

развернуть все

#include <limits.h>

unsigned int func(unsigned int exp)
{
    if (exp >= sizeof(unsigned int) * CHAR_BIT) {
        /* Handle error */
    }
    return 1U << exp;
}

В этом примере функция использует операцию сдвига влево, чтобы вернуть значение 2, возведенное в степень exp. Операция сдвигает биты 1U около exp позиции слева. if оператор гарантирует, что операция не сдвигает биты на несколько позиций exp больше, чем размер unsigned int. Однако, если unsigned int содержит биты заполнения, значение, возвращаемое sizeof() превышает точность unsigned int. В результате некоторые значения exp может быть слишком большим, а операция смены может иметь неопределенное поведение.

Коррекция - реализация функции для вычисления точности unsigned int

Одной из возможных корректировок является реализация функции. popcount() которая вычисляет точность unsigned int путем подсчета количества установленных битов.

#include <stddef.h>
#include <stdint.h>
#include <limits.h>

size_t popcount(uintmax_t);
#define PRECISION(umax_value) popcount(umax_value)


unsigned int func(unsigned int exp)
{
    if (exp >= PRECISION(UINT_MAX)) {
        /* Handle error */
    }
    return 1 << exp;
}




size_t popcount(uintmax_t num)
{
    size_t precision = 0;
    while (num != 0) {
        if (num % 2 == 1) {
            precision++;
        }
        num >>= 1;
    }
    return precision;
} 

Информация о результатах

Группа: Числовые
Язык: C | C++
По умолчанию: Откл.
Синтаксис командной строки: INT_PRECISION_EXCEEDED
Воздействие: Низкий
ИДЕНТИФИКАТОР CWE : 190
Представлен в R2018b