Now that RSA is over and things are somewhat back to normal, we can get back to the business of talking about Visual Studio features as they relate to the SDL. Here we present the fourth installment of the series by Thomas Garnier of the Security Science team talking about Visual Studio and proper C++ class initialization…
In previous posts we introduced the /sdl compiler switch and described our approach when designing and implementing additional security features in Visual Studio 2011.
This post describes another feature enabled by the /sdl compiler switch: in specific cases it will initialize all member pointers of a class. This feature addresses a common mistake made by developers when creating C++ classes.
Creating C++ classes requires the developer to handle the class initialization correctly. A classic mistake is forgetting or failing to initialize a member pointer that will be used or freed in the destructor.
This code assumes that the allocation will succeed and initialize the p variable. An attacker might influence the size or state of the process forcing a particular failure path to be taken. In this example it would free an uninitialized pointer which can lead to code execution.
We have seen different approaches to make this initialization process easier. For example, a developer might use a custom operator “new” to allocate and initialize memory. However the custom operator is not called if the variable is declared locally, as a member of another class (not being a pointer) or if the class is inherited.
Ensuring a class is always properly initialized can be a challenge, especially for large and complex code bases.
Automated initialization of class member pointers
In reviewing MSRC cases involving uninitialized class members, we noted that uninitialized pointers are the most common issue that could lead to code execution.
The following examples highlight how the compiler generates class creation code into assembly and how the /sdl compiler switch can change the generated code to initialize class pointers avoiding the common mistake described earlier.
Creating an object for the previous example via the following code:
Generates this assembly by default (without /sdl) on x86:
With the /sdl compiler switch enabled, when creating a class the Visual Studio 11 Developer Preview compiler will generate a new function called A::__autoclassinit(). This function is responsible for the initialization of class member pointers. It will also call the compiler-generated class initialization functions of any base classes or member variable of a class type. For our example the A::__autoclassinit() function is called before the call to the constructor:
In this example the A::__autoclassinit() function would initialize the variable p, call B::__autoclassinit() for the variable o and not touch n:
The compiler-generated class initialization function is called as long as:
- The object is not allocated as part of an array (for example “new A[x]”)
- The class is not managed or imported
To be initialized by the compiler-generated class initialization function, a member has to respect the following rules:
- The member is a pointer
Automated initialization of class member pointers demonstrates the capabilities offered by the compiler to mitigate complex security problems.
We hope you will find this functionality of the /sdl compiler switch useful and encourage you to try it. You can find more information about the Security Development Lifecycle (SDL), including articles, tools and more on this website.
Thomas Garnier, MSEC Security Science.