Bytewise operations on nontrivial class object

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

Описание

Этот дефект происходит, когда вы используете Стандартные библиотечные функции C, чтобы выполнить bytewise операцию на нетривиальных или нестандартных текстовых объектах класса макета. Для определений тривиальных и стандартных классов макета см. Стандарт C++, [класс], абзацы 6 и 7 соответственно.

Средство проверки повышает дефект, когда вы инициализируете или копируете нетривиальные объекты типа класса с помощью этих функций:

  • std::memset

  • std::memcpy

  • std::strcpy

  • std::memmove

Или когда вы сравниваете нестандартные текстовые объекты класса макета с помощью этих функций:

  • std::memcmp

  • std::strcmp

Средство проверки не повышает дефекта, если bytewise операция выполняется через псевдоним. Например, никакой дефект не повышен в bytewise сравнении и операциях копии в этом коде. bytewise операции используют dptr и sptr, псевдонимы нетривиального или нестандартного класса макета возражают d и s.

void func(NonTrivialNonStdLayout *d, const NonTrivialNonStdLayout *s)
{
   void* dptr = (void*)d; 
   const void* sptr = (void*)s;
   // ...
   // ...
   // ...
   if (!std::memcmp(dptr, sptr, sizeof(NonTrivialNonStdLayout))) {  
     (void)std::memcpy(dptr, sptr, sizeof(NonTrivialNonStdLayout)); 
      // ...
   }
}

Риск

Выполнение bytewise операции сравнения при помощи Стандартных библиотечных функций C на нетривиальном или нестандартном текстовом объекте класса макета может привести к неожиданным значениям из-за деталей реализации. Объектное представление зависит от деталей реализации, таких как порядок частных и общедоступных членов или использование таблиц указателя виртуальной функции, чтобы представлять объект.

Выполнение bytewise установка операций при помощи Стандартных библиотечных функций C на нетривиальном или нестандартном текстовом объекте класса макета может изменить детали реализации. Операция может привести к аварийному поведению программы или уязвимости выполнения кода. Например, если адрес функции членства перезаписывается, вызов этой функции вызывает неожиданную функцию.

Фиксация

Чтобы выполнить bytewise операции нетривиальный или нестандартный текстовый объект класса макета, используйте их C++ специальные функции членства вместо Стандартных библиотечных функций C.

C стандартные библиотечные функцииФункции членства C++

std::memset

Конструктор класса

std::memcpy

std::strcpy

std::memmove

Конструктор копии класса

Конструктор перемещения класса

Копирование оператора присваивания

Перемещение оператора присваивания

std::memcmp

std::strcmp

operator<()

operator>()

operator==()

operator!=()

Примеры

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

#include <cstring>
#include <iostream>
#include <utility>

class nonTrivialClass
{
    int scalingFactor;
    int otherData;
public:
    nonTrivialClass() : scalingFactor(1) {}
    void set_other_data(int i);
    int f(int i)
    {
        return i / scalingFactor;
    }
    // ...
};

void func()
{
    nonTrivialClass c;
    // ... Code that mutates c ...
    std::memset(&c, 0, sizeof(nonTrivialClass));
    std::cout << c.f(100) << std::endl;
}

В этом примере, func() использование std::memset повторно инициализировать нетривиальный объект класса c после того, как это сначала инициализируется своим конструктором по умолчанию. Эта bytewise операция не может правильно инициализировать представление значения c.

Коррекция — задает шаблон функции, который использует std::swap

Одна возможная коррекция должна задать шаблон функции clear() это использует std::swap выполнять операцию подкачки. Вызов clear()правильно повторно инициализирует объект c путем свопинга содержимого c и значение по умолчанию инициализировало объект empty.

 #include <cstring>
#include <iostream>
#include <utility>

class nonTrivialClass
{
    int scalingFactor;
    int otherData;
public:
    nonTrivialClass() : scalingFactor(1) {}
    void set_other_data(int i);
    int f(int i)
    {
        return i / scalingFactor;
    }
    // ...
};

template <typename T>
T& clear(T& o)
{
    using std::swap;
    T empty;
    swap(o, empty);
    return o;
}

void func()
{
    nonTrivialClass c;
    // ... Code that mutates c ...

    clear(c);
    std::cout << c.f(100) << std::endl;
}

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

Группа: объектно-ориентированный
Язык: C++
Значение по умолчанию: 'off'
Синтаксис командной строки: MEMOP_ON_NONTRIVIAL_OBJ
Удар: носитель

Введенный в R2019b