Possible invalid operation on boolean operand

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

Описание

Этот дефект происходит, когда вы используете булев операнд в арифметике, реляционной, или битовой операции и:

  • Булев операнд имеет представление прерывания. Размер булева типа в памяти является по крайней мере одним адресуемым модулем (размер char). Булев тип требует, чтобы только один бит представлял значение true (1) или false (0). Представление булева операнда в памяти содержит дополнительные биты. Представление памяти может привести к значениям, которые не являются true или false, представление прерывания.

  • Результат операции может превысить точность булева операнда.

Например, в этом фрагменте кода:

bool_v >> 2

  • Если значение bool_v true (1) или false (0), поразрядный сдвиг превышает однобитную точность bool_v и всегда результаты в 0.

  • Если bool_v имеет представление прерывания, результатом операции является произвольное значение.

Возможная недопустимая операция на булевом операнде не повышает дефекта когда:

  • Операция не приводит к переполнению точности. Например, поразрядный & или | операции с 0x01 или 0x00.

  • Булев операнд не может иметь представления прерывания. Например, константное выражение, которое приводит к 0 или 1, или сравнение, оцененное к true или false.

Риск

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

Фиксация

Постарайтесь не выполнять операции на булевых операндах кроме этих операций:

  • Операция Assignment (=).

  • Операции равенства (== или !=).

  • Логические операции, ||, или !).

Примеры

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

#include <stdio.h>
#include <stdbool.h>

#define BOOL _Bool

int arr[2] = {1, 2};

int func(BOOL b)
{
    return arr[b];
}

int main(void)
{
    BOOL b;
    char* ptr = (char*)&b;
    *ptr = 64;
    return func(b);
}

В этом примере, булев операнд b используется в качестве индекса массива в func для массива с двумя элементами. В зависимости от компилятора и оптимизации отмечает вас использование, значение b не может быть 0 или 1. Например, в Linux® Debian 8, если вы используете gcc версия 4.9 с флагом -O0 оптимизации, значение b 64, который вызывает переполнение буфера.

Коррекция — использует только последнее значение значимого бита булева операнда

Одна возможная коррекция должна использовать переменную b0 из типа unsigned int получить только значение последнего значимого бита булева операнда. Значение этого бита находится в области значений [0..1], даже если булев операнд имеет представление прерывания.

#include <stdio.h>
#include <stdbool.h>

#define BOOL _Bool

int arr[2] = {1, 2};

int func(BOOL b)
{
    unsigned int b0 = (unsigned int)b;
    b0 &= 0x1;
    return arr[b0];
}

int main(void)
{
    BOOL b;
    char* ptr = (char*)&b;
    *ptr = 64;
    return func(b);
} 

Обратите внимание на то, что представление прерывания часто является результатом более ранней проблемы в коде, таком как:

  • Неинициализированная переменная типа bool.

  • Побочный эффект, который изменяет любую часть bool текстового объекта с помощью lvalue выражения.

  • Чтение bool члена от объединения вводит с последней хранимой суммой другого типа.

По сути, это - лучшая практика уважать булеву семантику даже в Коде С++.

#include <iostream>

template <typename T>
bool less_or_equal(const T& x, const T& y)
{
    std::cout << "INTEGER VERSION" << '\n';
    return x <= y;
}
bool b1 = true, b2 = false;
int i1 = 2, i2 = 3;

int main()
{
    std::cout << std::boolalpha;
    std::cout << "less_or_equal(" << b1 << ',' << b2 << ") = " << less_or_equal<bool>(b1, b2) << '\n';
    std::cout << "less_or_equal(" << i1 << ',' << i2 << ") = " << less_or_equal<int>(11, 12) << '\n';
    return 0;
}

В этом примере, шаблон функции less_or_equal оценивает, меньше чем или равна ли переменная x y. Когда вы передаете булевы типы этой функции, <= операция может привести к произвольному значению, если представление памяти операндов, включая их дополнительные биты, ни 1, ни 0.

Коррекция — специализирует шаблон функции для булевых типов

Одна возможная коррекция должна специализировать шаблон функции для булевых типов. Специализированный шаблон функции использует логическое (||) операция, чтобы сравнить булевы операнды.

#include <iostream>

template <typename T>
bool less_or_equal(const T& x, const T& y)
{
    std::cout << "INTEGER VERSION" << '\n';
    return x <= y;
}

template<>
bool less_or_equal<bool>(const bool& x, const bool& y)
{
    std::cout << "BOOLEAN VERSION" << '\n';
    return !x || y;
}

bool b1 = true, b2 = false;
int i1 = 2, i2 = 3;

int main()
{
    std::cout << std::boolalpha;
    std::cout << "less_or_equal(" << b1 << ',' << b2 << ") = " << less_or_equal<bool>(b1, b2) << '\n';
    std::cout << "less_or_equal(" << i1 << ',' << i2 << ") = " << less_or_equal<int>(11, 12) << '\n';
    return 0;
}

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

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

Введенный в R2018b