Main Content

CERT C++: OOP57-CPP

Prefer special member functions and overloaded operators to C Standard Library functions

Description

Rule Definition

Prefer special member functions and overloaded operators to C Standard Library functions.1

Polyspace Implementation

The rule checker checks for Bytewise operations on nontrivial class object.

Examples

expand all

Issue

Bytewise operations on nontrivial class object occurs when you use C Standard library functions to perform bytewise operation on non-trivial or non-standard layout class type objects. For definitions of trivial and standard layout classes, see the C++ Standard, [class], paragraphs 6 and 7 respectively.

The checker raises a defect you initialize or copy non-trivial class type objects using these functions:

  • std::memset

  • std::memcpy

  • std::strcpy

  • std::memmove

Or when you compare non-standard layout class type objects using these functions:

  • std::memcmp

  • std::strcmp

Bytewise operations on nontrivial class object raises no defect if the bytewise operation is performed through an alias. For example no defect is raised in the bytewise comparison and copy operations in this code. The bytewise operations use dptr and sptr, the aliases of non-trivial or non-standard layout class objects d and 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)); 
      // ...
   }
}

Risk

Performing bytewise comparison operations by using C Standard library functions on non-trivial or non-standard layout class type object might result in unexpected values due to implementation details. The object representation depends on the implementation details, such as the order of private and public members, or the use of virtual function pointer tables to represent the object.

Performing bytewise setting operations by using C Standard library functions on non-trivial or non-standard layout class type object can change the implementation details. The operation might result in abnormal program behavior or a code execution vulnerability. For instance, if the address of a member function is overwritten, the call to this function invokes an unexpected function.

Fix

To perform bytewise operations non-trivial or non-standard layout class type object, use these C++ special member functions instead of C Standard library functions.

C Standard Library FunctionsC++ Member Functions

std::memset

Class constructor

std::memcpy

std::strcpy

std::memmove

Class copy constructor

Class move constructor

Copy assignment operator

Move assignment operator

std::memcmp

std::strcmp

operator<()

operator>()

operator==()

operator!=()

Example - Using memset with non-trivial class object
#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)); //Noncompliant
    std::cout << c.f(100) << std::endl;
}

In this example, func() uses std::memset to reinitialize non-trivial class object c after it is first initialized with its default constructor. This bytewise operation might not properly initialize the value representation of c.

Correction — Define Function Template That Uses std::swap

One possible correction is to define a function template clear() that uses std::swap to perform a swap operation. The call to clear()properly reinitializes object c by swapping the contents of c and default initialized object 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;
}

Check Information

Group: Rule 09. Object Oriented Programming (OOP)

Version History

Introduced in R2019b


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.