Integer precision exceeded

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

Описание

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

Риск

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

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

Фиксация

Не используйте размер целого числа вместо его точности. Чтобы определить целочисленную точность, реализуйте стандартную программу расчета точности или используйте встроенную функцию, такую как __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++
Значение по умолчанию: 'off'
Синтаксис командной строки: INT_PRECISION_EXCEEDED
Удар: низко
ID CWE: 190

Введенный в R2018b