Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Added another NCCE/CS pair

...

A special instance of this guidance involves non-C++ code compiled by a different compiler, such as C standard library implementations that are exposed via the C++ standard library. C standard library functions are exposed with C++ signatures, and the type system frequently assists in ensuring that types match appropriately. This disallows passing a pointer to a C++ object to a function expecting a char * without additional work to suppress the type mismatch. However, some C standard library functions accept a void *, for which any C++ pointer type will suffice. Passing a pointer to a nonstandard-layout type in this situation results in unspecified indeterminate behavior, as it depends on the behavior of the other language as well as the layout of the given object.

...

Code Block
bgColor#ccccff
langcpp
struct S {
  int i, j, k;
 
  // ...

  virtual void f();
  void clear() { i = j = k = 0; }
};

void f() {
  S *s = new S;
  // ...
  s->clear();
  // ...
  s->f();
}

Noncompliant Code Example

In this noncompliant code example, a pointer to an object of nonstandard-layout type is passed to a function that has a "Fortran" language linkage. Language linkages other than "C" and "C++" are conditionally-supported with implementation-defined semantics [ISO/IEC 14882-2014]. If the implementation does not support this language linkage, the code is ill-formed. Assuming that the language linkage is supported, any operations performed on the object passed may result in indeterminate behavior, which could have security implications.

Code Block
bgColor#FFCCCC
langcpp
struct B {
  int i, j;
};
 
struct D : B {
  float f;
};
 
void f(D *d) {
  extern "Fortran" void func(void *);
  func(d);
}

Compliant Solution

In this compliant solution, the nonstandard-layout type object is serialized into a local standard-layout type object, that is then passed to the Fortran function:

Code Block
bgColor#ccccff
langcpp
struct B {
  int i, j;
};

struct D : B {
  float f;
};

void f(D *d) {
  struct {
    int i, j;
    float f;
  } temp;
 
  temp.i = d->i;
  temp.j = d->j;
  temp.f = d->f;

  extern "Fortran" void func(void *);
  func(&temp);
}

Risk Assessment

The effects of passing objects of nonstandard-layout type across execution boundaries depends on what operations are performed on the object within the callee as well as what subsequent operations are performed on the object from the caller, and can range from correct or benign behavior to undefined behavior.

...

[ISO/IEC 14882-2014]Clause 9, "Classes"
7.5, "Linkage Specifications" 

 

...