The placement new operator enables the programmer to specify the memory in which the object being instantiated will be allocated. A problem may arise when such a pointer is misaligned with the underlying architecture alignment restrictions. On several RISC architectures such as PowerPC or on IA64 (Itanium) or Intel (IA32) CPUs which were configured to fault on unaligned access, access to unaligned objects might cause the program to terminate abnormally.
Noncompliant Code Example
In this non compliant 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 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
The following is a compliant solution on a IA32 system using either GCC or Microsoft's Visual Studio. In this solution the macro ALIGN was added to ensure alignment when compiling with both Microsoft VS compiler and g++ . 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.
#ifdef WIN32 #define ALIGN(X)_declspec(align(X)) #elif __GNUC__ #define ALIGN(X) __attribute__((aligned(X))) #else #define ALIGN(X) #endif 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 (2)
In the following compliant solution a union is used to impose unsigned long's alignment 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); }
Risk Assessment
Accessing a misaligned object may cause the program to terminate abnormally on several systems.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
MEM45-CPP |
low |
probable |
1 |
P2 |
L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Bibliography
[ISO/IEC 14882-2003] 3.7.4.1