exponenta event banner

Побитовая операция при отрицательном значении

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

Описание

Этот дефект возникает при побитовых операторах (>>, ^, |, ~, 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++
По умолчанию: Откл.
Синтаксис командной строки: BITWISE_NEG
Воздействие: среднее
CWE ID: 682, 758
Представлен в R2016b