Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

When f() is called with the designer argument, the formal parameter in f() is sliced and information is lost. When the Manager object is object e is printed, Employee::print() is called instead of Manager::print(), resulting in the following output:

...

Using the same class definitions as the noncompliant code example, this compliant solution modifies the definition of f() to require raw pointers to the object, removing the slicing problem:.

Code Block
bgColor#ccccff
langcpp
// ... restRemainder of code unchanged ...
 
void f(const Employee *e) {
  if (e) {
    std::cout << *e;
  }
}

int main() {
  Employee coder("Joe Smith");
  Employee typist("Bill Jones");
  Manager designer("Jane Doe", typist);
  
  f(&coder);
  f(&typist);
  f(&designer);
}

This compliant solution also complies with EXP34-C. Do not dereference null pointers in the implementation of f(). With this definition, the the program correctly outputs :the following.

Code Block
Employee: Joe Smith
Employee: Bill Jones
Manager: Jane Doe
Assistant: 
	Employee: Bill Jones

...

An improved compliant solution, which does not require guarding against null pointers within f(), uses references instead of pointers:.

Code Block
bgColor#ccccff
langcpp
// ... restRemainder of code unchanged ...
 
void f(const Employee &e) {
  std::cout << e;
}

int main() {
  Employee coder("Joe Smith");
  Employee typist("Bill Jones");
  Manager designer("Jane Doe", typist);
  
  f(coder);
  f(typist);
  f(designer);
}

...

Both previous compliant solutions depend on consumers of the Employee and Manager types to be declared in a compliant manner with the expected usage of the class hierarchy. This compliant solution ensures that consumers are unable to accidentally slice objects by removing the objects' ability to copy-initialize an object that derives from Noncopyable. If copy-initialization is attempted, as in the original definition of f(), the program is ill-formed and a diagnostic will be emitted. However, such a solution also restricts the Manager object from attempting to copy-initialize its Employee object, which subtly changes the semantics of the class hierarchy.

...

Code Block
bgColor#ccccff
langcpp
#include <iostream>
#include <string>

class Noncopyable {
  Noncopyable(const Noncopyable &) = delete;
  void operator=(const Noncopyable &) = delete;
  
protected:
  Noncopyable() = default;
};

class Employee : Noncopyable {
  // Remainder of the definition is unchanged.
  std::string name;
  
protected:
  virtual void print(std::ostream &os) const {
    os << "Employee: " << get_name() << std::endl;      
  }
  
public:
  Employee(const std::string &name) : name(name) {}
  const std::string &get_name() const { return name; }
  friend std::ostream &operator<<(std::ostream &os, const Employee &e) {
    e.print(os);
    return os;
  }
};
 
class Manager : public Employee {
  const Employee &assistant; // Note: ThisThe definition of Employee has been modified.

  // remainingRemainder of the definition is unchanged.
protected:
  void print(std::ostream &os) const override {
    os << "Manager: " << get_name() << std::endl;
    os << "Assistant: " << std::endl << "\t" << get_assistant() << std::endl;      
  }
  
public:
  Manager(const std::string &name, const Employee &assistant) : Employee(name), assistant(assistant) {}
  const Employee &get_assistant() const { return assistant; }
};
 
// If f() were declared as accepting an Employee, the program would be
// ill-formed because Employee cannot be copy-initialized.
void f(const Employee &e) {
  std::cout << e;
}

int main() {
  Employee coder("Joe Smith");
  Employee typist("Bill Jones");
  Manager designer("Jane Doe", typist);
  
  f(coder);
  f(typist);
  f(designer);
}

...

This noncompliant code example uses the same class definitions of Employee and Manager as in the previous examples noncompliant code example and attempts to store Employee objects in a std::vector. However, because std::vector requires a homogeneous list of elements, slicing occurs.

Code Block
bgColor#FFCCCC
langcpp
// In addition to the #includes from the previous example#include <iostream>
#include <string>
#include <vector>
 
void f(const std::vector<Employee> &v) {
  for (const auto &e : v) {
    std::cout << e;
  }
}

int main() {
  Employee typist("Joe Smith");
  std::vector<Employee> v{typist, Employee("Bill Jones"), Manager("Jane Doe", typist)};
  f(v);
}

Compliant Solution

This compliant solution stores uses a vector of std::unique_ptr smart pointers in the std::vector, which  objects, which eliminates the slicing problem:.

Code Block
bgColor#ccccff
langcpp
// In addition to the #includes from the previous example#include <iostream>
#include <memory>
#include <memory><string>
#include <vector>

void f(const std::vector<std::unique_ptr<Employee>> &v) {
  for (const auto &e : v) {
    std::cout << *e;
  }
}

int main() {
  std::vector<std::unique_ptr<Employee>> v;
  
  v.emplace_back(new Employee("Joe Smith"));
  v.emplace_back(new Employee("Bill Jones"));
  v.emplace_back(new Manager("Jane Doe", *v.front()));
  
  f(v);
}

...

Slicing results in information loss, which could lead to abnormal program execution or denial-of-service attacks.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

OOP51-CPP

Low

Probable

Medium

P4

L3

Automated Detection

Tool

Version

Checker

Description

CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

LANG.CAST.OBJSLICE

Object Slicing

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C++3072
Parasoft C/C++test
9.5OOP-02, JSF-117_a 

 PRQA QA-C++

  Include PagePRQA QA-C++_VPRQA QA-C++_V

3072, 3073

Include Page
Parasoft_V
Parasoft_V

CERT_CPP-OOP51-a

Avoid slicing function arguments / return value

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C++: OOP51-CPPChecks for object slicing (rule partially covered)
PVS-Studio

Include Page
PVS-Studio_V
PVS-Studio_V

V1054
 

Related Vulnerabilities

Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

Bibliography

[Dewhurst
02
2002]Gotcha #38, "Slicing"
[ISO/IEC 14882-2014]Subclause 12.8, "Copying and Moving Class Objects"
[Sutter
00
2000]Item 40, "Object Lifetimes—Part I"

...


...

Image Modified Image Modified Image Modified