Main Content

Bitwise operation on negative value

Undefined behavior for bitwise operations on negative values

Description

This defect occurs when bitwise operators (>>, ^, |, ~, but, not, &) are used on signed integer variables with negative values.

Risk

If the value of the signed integer is negative, bitwise operation results can be unexpected because:

  • Bitwise operations on negative values can produce compiler-specific results.

  • Unexpected calculations can lead to additional vulnerabilities, such as buffer overflow.

Fix

When performing bitwise operations, use unsigned integers to avoid unexpected results.

Extend Checker

A default Bug Finder analysis might not raise this defect when the input values are unknown and only a subset of inputs cause an issue. To check for defects caused by specific system input values, run a stricter Bug Finder analysis. See Extend Bug Finder Checkers to Find Defects from Specific System Input Values.

Examples

expand all

#include <stdio.h>
#include <stdarg.h>

static void demo_sprintf(const char *format, ...)
{
    int rc;
    va_list ap;
    char buf[sizeof("256")];

    va_start(ap, format);
    rc = vsprintf(buf, format, ap);
    if (rc == -1 || rc >= sizeof(buf)) {
        /* Handle error */
    }
    va_end(ap);
}

void bug_bitwiseneg()
{
    int stringify = 0x80000000;
    demo_sprintf("%u", stringify >> 24);
}

In this example, the statement demo_sprintf("%u", stringify >> 24) stops the program unexpectedly. You expect the result of stringify >> 24 to be 0x80. However, the actual result is 0xffffff80 because stringify is signed and negative. The sign bit is also shifted.

Correction — Add unsigned Keyword

By adding the unsigned keyword, stringify is not negative and the right-shift operation gives the expected result of 0x80.

#include <stdio.h>
#include <stdarg.h>

static void demo_sprintf(const char *format, ...)
{
    int rc;
    va_list ap;
    char buf[sizeof("256")];

    va_start(ap, format);
    rc = vsprintf(buf, format, ap);
    if (rc == -1 || rc >= sizeof(buf)) {
        /* Handle error */
    }
    va_end(ap);
}

void corrected_bitwiseneg()
{
    unsigned int stringify = 0x80000000;
    demo_sprintf("%u", stringify >> 24);
}

Result Information

Group: Numerical
Language: C | C++
Default: Off
Command-Line Syntax: BITWISE_NEG
Impact: Medium

Version History

Introduced in R2016b