The placement new operator enables the programmer to specify the memory in which an object being constructed will be located. A problem may arise if a pointer to this memory is misaligned with the platform's underlying architecture alignment restrictions. On several RISC architectures, such as PowerPC or IA64 (Itanium), access to misaligned objects might cause the program to terminate abnormally. This can also occur on IA32 CPUs which have been configured to fault on misaligned access.
Noncompliant Code Example
In this noncompliant code, a struct of type A
is allocated on the memory region of s.B
. The problem is that A
has a member of type unsigned long
which, on IA32 systems, is required to be aligned to 4. However, B
is an array of unsigned chars inside S
and is not aligned to 4. After the call to operator new
, the pointer a
is pointing to an unaligned memory address. Writing val
into a->i
can cause the program to terminate abnormally.
struct A { unsigned long i; }; struct S { unsigned char x; unsigned char B[sizeof(A)]; } s; int main() { A *a = new(&s.B[0]) A; unsigned long val = 0xaabbccdd; a->i = val; return 0; }
Compliant Solution (Union)
In the following compliant solution, a union is used to impose the alignment of unsigned long on the array B.
struct A { unsigned long i; }; union AlignedUnion { unsigned char B[sizeof(A)]; private: unsigned long _align_; } algn; int main() { A *a = new(&algn.B[0]) A; unsigned long val = 0xaabbccdd; a->i = val; return (0); }
Compliant Solution (G++)
The following is a compliant solution on a IA32 system using g++. In this solution, the ALIGN
macro was added to ensure alignment when compiling with g++. In this case, it is used on B
to make it aligned to 4, which is the alignment restriction for unsigned long
.
#define ALIGN(X) __attribute__((aligned(X))) struct A { unsigned long i; }; struct S { unsigned char x; ALIGN(4) unsigned char B[sizeof(A)]; } s; int main() { A *a = new(&s.B[0]) A; unsigned long val = 0xaabbccdd; a->i = val; return 0; }
Compliant Solution (MSVC)
The following is a compliant solution on a IA32 system using Microsoft Visual Studio. In this solution, the ALIGN
macro was added to ensure alignment when compiling with Microsoft VS. The ALIGN()
macro calls either declspec(align())
or attribute_((aligned()))
to enforce alignment on a particular variable. In this case, it is used on B
to make it aligned to 4, which is the alignment restriction for unsigned long
.
#define ALIGN(X) _declspec(align(X)) struct A { unsigned long i; }; struct S { unsigned char x; ALIGN(4) unsigned char B[sizeof(A)]; } s; int main() { A *a = new(&s.B[0]) A; unsigned long val = 0xaabbccdd; a->i = val; return 0; }
Risk Assessment
Providing improperly-aligned pointers to placement new can result in undefined behavior, including abnormal termination.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
MEM45-CPP | low | probable | low | P6 | L2 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Bibliography
[ISO/IEC 14882-2003] section 3.7.4.1