Bitwise operation on negative value

Неопределенное поведение для битовых операций на отрицательных величинах

Описание

Битовая операция на отрицательной величине обнаруживает побитовые операторы (>>, ^, |, ~, but, not, &) используемый на переменных целого числа со знаком с отрицательными величинами.

Риск

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

  • Битовые операции на отрицательных величинах специфичны для компилятора.

  • Неожиданные вычисления могут привести к дополнительным уязвимостям, таким как переполнение буфера.

Фиксация

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

Примеры

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

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

В этом примере, операторе demo_sprintf("%u", stringify >> 24) неожиданно останавливает программу. Вы ожидаете результат stringify >> 24 быть 0x80. Однако фактическим результатом является 0xffffff80 потому что stringify подписывается и отрицателен. Знаковый бит также смещен.

Коррекция — добавляет unsigned Ключевое слово

Путем добавления unsigned ключевое слово, stringify не отрицательно, и операция сдвига вправо дает ожидаемый результат 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);
}

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

Группа: числовой
Язык: C | C++
Значение по умолчанию: 'off'
Синтаксис командной строки: BITWISE_NEG
Удар: носитель
ID CWE: 682, 758

Введенный в R2017b