# V1046. Unsafe usage of the 'bool' and integer types together in the operation '&='.

Анализатор обнаружил небезопасное использование типа 'bool' и целочисленного типа вместе в операции побитового И. Проблема в том, что побитовое И вернет 'false' для четных чисел, так как младший разряд всегда равен нулю. Если же привести вручную численный тип к 'bool', то всё будет в порядке.

Рассмотрим синтетический пример:

    int foo(bool a)
    {
      return a ? 0 : 2;
    }
    ....
    bool var = ....;
    var &= foo(false);

Независимо от начального значения переменной 'var', после выполнения операции '&=' эта переменная будет иметь значение 'false'. Допустим, функция 'foo' вернёт значение 2. Тогда операция 'var & 2' всегда даёт в результате 0, так как возможные значения 'var' это только 0 или 1.

Этот код следует исправить так:

    var &= foo(false) != 0;

или же можно изменить и возвращаемое функцией значение:

    int foo(bool a)
    {
      return a ? 0 : 1;
    }

Если, например, функция будет возвращать только значения из диапазона [0;1], то всё в порядке, так как мы можем привести их без потерь к bool.

Пример ошибки, найденной с помощью этой диагностики в реальном проекте:

    template<class FuncIterator>
    bool SetFunctionList( FuncIterator begin, FuncIterator end) {
      bool ret = true;
      for (FuncIterator itr = begin; itr != end; ++itr) {
        const ROOT::Math::IMultiGenFunction *f = *itr;
        ret &= AddFunction(*f);
      }
      return ret;
    }

    int AddFunction(const ROOT::Math::IMultiGenFunction & func) {
      ROOT::Math::IMultiGenFunction *f = func.Clone();
      if (!f) return 0;
      fFunctions.push_back(f);
      return fFunctions.size();
    }

Предполагалось, что функция 'SetFunctionList' проверяет валидность переданных ей итераторов и возвращает 'false', если хоть один из них невалидный, иначе 'true'. Но программист допустил ошибку при работе с оператором '&='. Правый аргумент – функция, которая возвращает целое число в диапазоне от 0 до SIZE_MAX. При возвращении чётных чисел из функции 'AddFunction', переменная 'ret' будет обнуляться, хотя должна это делать только для невалидных итераторов.

Исправленная функция 'SetFunctionList', где результат функции 'AddFunction' предварительно приводится к типу 'bool':

    template<class FuncIterator>
    bool SetFunctionList( FuncIterator begin, FuncIterator end) {
      bool ret = true;
      for (FuncIterator itr = begin; itr != end; ++itr) {
        const ROOT::Math::IMultiGenFunction *f = *itr;
        ret &= (bool)AddFunction(*f);
      }
      return ret;
    }

Данная диагностика классифицируется как:

CWE-682 CERT-INT31-C

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V1046.