CERT C: правило EXP46-C

Не используйте побитовый оператор с подобным булевской переменной операндом

Описание

Управляйте определением

Не используйте побитовый оператор с подобным булевской переменной операндом. [1]

Примеры

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

Описание

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

  • Булев операнд имеет представление прерывания. Размер булева типа в памяти является по крайней мере одним адресуемым модулем (размер 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, если вы используете версию 4.9 gcc с флагом -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);
} 

Проверяйте информацию

Группа: правило 03. Выражения (EXP)

Введенный в R2019a


[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ-МЕЛЛОН И/ИЛИ ЕГО ИНСТИТУТА ПРОГРАММНОЙ ИНЖЕНЕРИИ СОДЕРЖАЛ, ЗДЕСЬ ПРЕДОСТАВЛЯЕТСЯ НА ОСНОВЕ "ASIS". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

Это программное обеспечение и сопоставленная документация не были рассмотрены, ни являются подтвержденным Университетом Карнеги-Меллон или его Институтом программной инженерии.