# V582. Consider reviewing the source code that uses the container.

Анализатор обнаружил потенциальную ошибку при работе с контейнером фиксированного размера. Эту диагностику нам предложил реализовать один из наших пользователей. Вот как он сформулировал задачу.

Для работы с массивами константного размера мы используем следующий шаблонный класс:

    template<class T_, int numElements > class idArray
    {
    public:
      int Num() const { return numElements; };
      .....
      inline const T_ & operator[]( int index ) const {
        idassert( index >= 0 );
        idassert( index < numElements );
        return ptr[index];
      };
      inline T_ & operator[]( int index ) {
        idassert( index >= 0 );
        idassert( index < numElements );
        return ptr[index];
      };
    private:
      T_ ptr[numElements];
    };

Класс позволяет обнаружить ошибки выхода за пределы массива при запуске DEBUG версии. При этом производительность RELESE версии не снижается. Пример некорректного кода:

    idArray<int, 1024> newArray;
    newArray[-1] = 0;
    newArray[1024] = 0;

Ошибки будут обнаружены при запуске отладочной версии. Однако хочется иметь возможность обнаруживать подобные ошибки с помощью статического анализа ещё на этапе компиляции.

Для выявления подобных ошибочных ситуаций и предназначена диагностика V582. Если в программе используется класс, реализующий функциональность контейнера фиксированного размера, то анализатор пытается проверить, что индекс не выходит за его границу. Пример диагностики:

    idArray<float, 16> ArrA;
    idArray<float, 8> ArrB;
    for (size_t i = 0; i != 16; i++)
      ArrA[i] = 1.0f;
    for (size_t i = 0; i != 16; i++)
      ArrB[i] = 1.0f;

Здесь анализатор выдаст предупреждение:

V582 Consider reviewing the source code which operates the 'ArrB' container. The value of the index belongs to the range: [0..15].

Ошибка в том, что оба цикла обрабатывают 16 элементов, хотя второй массив содержит только 8 элементов. Корректный вариант:

    for (size_t i = 0; i != 16; i++)
      ArrA[i] = 1.0f;
    for (size_t i = 0; i != 8; i++)
      ArrB[i] = 1.0f;

Следует отметить, что передача слишком больших или маленьких индексов не всегда означает ошибку в программе. Например, оператор [] может быть реализован следующим образом:

    inline T_ & operator[]( int index ) {
      if (index < 0) index = 0;
      if (index >= numElements) index = numElements - 1;
      return ptr[index];
    };

Если вы используете подобные классы и получаете много ложных срабатываний, то очевидно вам следует отключить диагностику V582.

Примечание. Анализатор не обладает искусственным интеллектом и поэтому его возможности поиска дефектов при работе с контейнерами ограничены. Мы работаем над усовершенствованием алгоритмов, поэтому если вы заметили явные ложные срабатывания или наоборот ситуации, в которых анализатор не выдал предупреждение, просим написать нам и прислать соответствующий пример кода.

Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки переполнения буфера (записи или чтения за пределами выделенной для буфера памяти).

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

CWE-119 CWE-125 CWE-787 CERT-ARR30-C