Integer precision exceeded

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

Описание

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

Риск

Использование размера целого числа в операции с целочисленной точностью может привести к целочисленному переполнению, переносу или неожиданным результатам. Для образца беззнаковое целое число может храниться в памяти в 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 положения налево. The 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
Влияние: Низкое
ИДЕНТИФИКАТОР CWE : 190
Введенный в R2018b