VC++ 2010 and memcpy

A year ago, I wrote a short post about us banning memcpy in the SDL for new code. Well, I’m happy to announce that in VC++ 2010, we have made it much easier to remove potentially insecure calls to memcpy and replace them with more secure calls to memcpy_s; it’s automagic, just like we do did for other banned functions!

 

As I said in a previous post, I am a huge fan of adding defenses to code automatically, and making such changes as easy as possible for software engineers, and this auto-migration is a great example.

 

In short, if your code has a call to memcpy, and the compiler can determine the destination buffer size at compile time, the compiler will replace the call to memcpy with a call to memcpy_s.

 

For example, if you compile the code below with:

 

cl /D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY=1 foo.cpp

 

 

#include <memory.h>

 

 

int main() {

 

    int src[100];
const size_t src_size =  _countof(src) * sizeof(int);

 

    memset(src, 12, src_size);

 

    const size_t dst_size_int = _countof(src);
int dst[dst_size_int];

 

    memcpy(dst, src, src_size);

 

    return 0;

 

}

 

You’ll see that the calls to memcpy are replaced with memcpy_s courtesy of this code in memory.h:

 

#if defined(__cplusplus) && _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY

 

extern “C++” {

 

#ifndef _CRT_ENABLE_IF_DEFINED

 

  #define _CRT_ENABLE_IF_DEFINED

 

    template<bool _Enable, typename _Ty>

 

    struct _CrtEnableIf;

 

    template<typename _Ty>

 

    struct _CrtEnableIf<true, _Ty>

 

    {

 

        typedef _Ty _Type;

 

    };

 

#endif

 

    template <size_t _Size, typename _DstType>

 

    inline

 

    typename _CrtEnableIf<(_Size > 1), void *>::_Type __cdecl memcpy(_DstType (&_Dst)[_Size], _In_opt_bytecount_(_SrcSize) const void *_Src, _In_ size_t _SrcSize) _CRT_SECURE_CPP_NOTHROW

 

    {

 

        return memcpy_s(_Dst, _Size * sizeof(_DstType), _Src, _SrcSize) == 0 ? _Dst : 0;

 

    }

 

}

 

#endif

 

Note that for this to work, you must define a preprocessor variable:

 

_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY = 1

 

This is another great example of why migrating your C++ code to Visual C++ 2010 can help improve the security of the code with virtually no engineering effort.

(Big thanks to the C++ folks over in the Developer Division for getting this work done in time for VC++ 2010)

- Michael

About the Author
Michael Howard

Principal Security Program Manager

Michael Howard is a principal security program manager on the Trustworthy Computing (TwC) Security team at Microsoft, where he is responsible for managing secure design, programming, and testing techniques across the company. Michael is an architect of the Security Development Read more »