swprintf_s overrite my heap

ffaith 116 Reputation points
2022-05-02T11:36:28.47+00:00

Hi all,

I wrote a simple program as following:

//-------------------------------------------------------
TCHAR* userName{};
int len = lstrlen(L"administrator") * 2 + 2;
userName = (TCHAR*)malloc(len);
if (userName) {
swprintf_s(userName, len, L"%ls", L"administrator");
free(userName);
}
//------------------------------------------------------
With Debug version, after swprintf_s, the 13 bytes after userName is override as "FE". And when free(userName), VS report heap corrupted as following:
//------------------------------------------------------
0x000001362D16DC40 61 00 64 00 6d 00 69 00 a.d.m.i.
0x000001362D16DC48 6e 00 69 00 73 00 74 00 n.i.s.t.
0x000001362D16DC50 72 00 61 00 74 00 6f 00 r.a.t.o.
0x000001362D16DC58 72 00 00 00 fe fe fe fe r...þþþþ
0x000001362D16DC60 fe fe fe fe fe fe fe fe þþþþþþþþ
0x000001362D16DC68 fe fe fe fe fe fe fe fe þþþþþþþþ
0x000001362D16DC70 fe fe fe fe fe fe fe fe þþþþþþþþ
//------------------------------------------------------

And the program can run correctly without heap corruption.

The code the fill the pattern as following. I understand that we need secure fill. However, this behavior just break the heap.

//------------------------------------------------------
static int __cdecl common_vsprintf_s(
unsigned __int64 const options,
_Out_writes_z_(buffer_count) Character* const buffer,
size_t const buffer_count,
Character const* const format,
_locale_t const locale,
va_list const arglist
) throw()
{
_VALIDATE_RETURN(format != nullptr, EINVAL, -1);
_VALIDATE_RETURN(buffer != nullptr && buffer_count > 0, EINVAL, -1);

int const result = common_vsprintf<format_validation_base>(options, buffer, buffer_count, format, locale, arglist);
if (result < 0)
{
    buffer[0] = 0;
    _SECURECRT__FILL_STRING(buffer, buffer_count, 1);
}

if (result == -2)
{
    _VALIDATE_RETURN(("Buffer too small", 0), ERANGE, -1);
}
else if (result >= 0)
{
    **_SECURECRT__FILL_STRING(buffer, buffer_count, result + 1);**
}

return result;

}
//------------------------------------------------------

PS. My environment is Windows 10 + VS2019, and Version of SDK is 10.0.19041.0.

I appreciate your explanation.

C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,538 questions
0 comments No comments
{count} votes

Accepted answer
  1. RLWA32 40,651 Reputation points
    2022-05-02T12:15:59.547+00:00

    Your posted code does not properly account for the length of a wide string when building for UNICODE.

    Following example properly handles either UNICODE or non-UNICODE builds.

    #define WIN32_LEAN_AND_MEAN
    #include <Windows.h>
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <tchar.h>
    
    int main()
    {
        TCHAR* userName{};
        int len = (lstrlen(_T("administrator"))+ 1) * sizeof(TCHAR);
        userName = (TCHAR*)malloc(len);
        if (userName) {
            _stprintf_s(userName, len / sizeof(TCHAR) , _T("%s"), _T("administrator"));
            free(userName);
        }
    
        return 0;
    }
    

0 additional answers

Sort by: Most helpful