Main Content

Integer precision exceeded

Operation using integer size instead of precision can cause undefined behavior

Description

This defect occurs when an integer expression uses the integer size in an operation that exceeds the integer precision. On some architectures, the size of an integer in memory can include sign and padding bits. On these architectures, the integer size is larger than the precision which is just the number of bits that represent the value of the integer.

Risk

Using the size of an integer in an operation on the integer precision can result in integer overflow, wrap around, or unexpected results. For instance, an unsigned integer can be stored in memory in 64 bits, but uses only 48 bits to represent its value. A 56 bits left-shift operation on this integer is undefined behavior.

Assuming that the size of an integer is equal to its precision can also result in program portability issues between different architectures.

Fix

Do not use the size of an integer instead of its precision. To determine the integer precision, implement a precision computation routine or use a builtin function such as __builtin_popcount().

Examples

expand all

#include <limits.h>

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

In this example, the function uses a left shift operation to return the value of 2 raised to the power of exp. The operation shifts the bits of 1U by exp positions to the left. The if statement ensures that the operation does not shift the bits by a number of positions exp greater than the size of an unsigned int. However, if unsigned int contains padding bits, the value returned by sizeof() is larger than the precision of unsigned int. As a result, some values of exp might be too large, and the shift operation might be undefined behavior.

Correction — Implement Function to Compute Precision of unsigned int

One possible correction is to implement a function popcount() that computes the precision of unsigned int by counting the number of set bits.

#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;
} 

Result Information

Group: Numerical
Language: C | C++
Default: Off
Command-Line Syntax: INT_PRECISION_EXCEEDED
Impact: Low

Version History

Introduced in R2018b