Perplexed Owl Random Ponderings

Benjamin ‘Benilda’ Key:

May 4, 2020

Be careful when you use the wide character versions of the Security-Enhanced Versions of CRT Functions

You need to be careful when you use the wide character versions of the Security-Enhanced Versions of CRT Functions; if you are not careful you may introduce a bug that will always result in a crash in debug builds of your application and may cause intermittent crashes in release builds.

This seemingly innocent block of code will always crash you application in debug builds. It may or may not crash your application in release builds.

WCHAR buffer[1024]{};
wcscpy_s(buffer, sizeof(buffer), source);

The crash occurs because the common_tcscpy_s function, which is called by the wcscpy_s function, contains the following line of code.

_FILL_STRING(destination, size_in_elements, size_in_elements - available + 1);

In debug builds, this preprocessor macro uses the memset function to fill the destination after the terminating null character with the _SECURECRT_FILL_BUFFER_PATTERN. The issue is that the _FILL_STRING assumes that the size_in_elements is the number of characters, not bytes. However, when the wcscpy_s function is called in the Example Code Block, the number of bytes is specified since the sizeof operator returns the size of buffer in bytes.

The result of this discrepancy is that when memset is called, it will write twice as many bytes as it should since it will write "((_Count) - (_Offset))) * sizeof(*(_String)))" bytes.

This will result in a stack memory overrun which will result in a crash.

The _FILL_STRING macro does nothing in release builds. However, if the size of the destination is large enough you will still have a stack memory overrun.

There are template versions of these functions that do not require you to specify the size of the buffer; they use template magic to calculate it for you at compile time. If at all possible, you should use these template versions if at all possible.