You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

The non-placement new expression is specified to invoke an allocation function to allocate storage for an object of the specified type.  When successful, the allocation function, in turn, is required to return a pointer to storage with alignment suitable for any object with a fundamental alignment requirement.  Although the global operator new, the default allocation function invoked by the new expression, is specified by the C++ standard [ISO/IEC 14882-2014] to allocate sufficient storage suitably aligned to represent any object of the specified size, since the expected alignment isn't part of the function's interface, the most a program can safely assume is that the storage is aligned for an object with a fundamental alignment.  In particular, it is unsafe to use the storage for an object of a type with a stricter alignment requirement – an over-aligned type.

Avoid using the new expression to construct objects of over-aligned types.  Doing so may result in an object being constructed at a misaligned location, which has undefined behavior and typically results in abnormal termination when the object is accessed.

Noncompliant Code Example

In the following noncompliant code example, the new expression is used to construct an object of the user-defined type Vector with alignment that exceeds the fundamental alignment of most implementations (typically 16 bytes).  Objects of such over-aligned types are typically required by SIMD vectorization instructions which often trap when passed unsuitably aligned arguments.

struct alignas (32) Vector { char elems [32]; };

Vector* f() {
  Vector *pv = new Vector ();
  return pv;
}

Compliant Solution (aligned_alloc)

In this compliant solution, an overloaded operator new function is defined to obtain appropriately aligned storage by calling the C11 function aligned_alloc.  Programs that make use of the array form of the new expression must define the corresponding member array operator new[] and operator delete[].  Programs targeting C++ implementations that do not provide the C11 aligned_alloc function must define the member operator new to adjust the alignment of the storage obtained by the allocation function of their choice, either the default global operator new or malloc.

#include <new>
#include <stdlib.h>

struct alignas (32) Vector {
  char elems [32];
  static void* operator new (size_t);
  static void operator delete (void *p) {
    free (p);
  }
};

void* Vector::operator new (size_t nbytes) {
  if (void *p = aligned_alloc (32, nbytes))
    return p;
  throw std::bad_alloc ();
}

Vector* f() {
  Vector *pv = new Vector ();
  return pv;
}

Risk Assessment

Using improperly aligned pointers results in undefined behavior, typically leading to abnormal termination.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MEM55-CPP

Medium

Unlikely

Low

P6

L2

Automated Detection

Tool

Version

Checker

Description

    

Related Vulnerabilities

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

Related Guidelines

Bibliography

[N3396] Dynamic memory allocation for over-aligned data, WG14 proposal, Clark Nelson

[ISO/IEC 14882-2014]

Subclause 3.7.4, "Dynamic Storage Duration"
Subclause 5.3.4, "New"
Subclause 18.6.1, "Storage allocation and deallocation"

 


  • No labels