question

Freyu-0399 avatar image
0 Votes"
Freyu-0399 asked Freyu-0399 commented

swprintf_s overrite my heap

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++
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

RLWA32-6355 avatar image
0 Votes"
RLWA32-6355 answered Freyu-0399 commented

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;
 }
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks a lot for your answer. :), I misunderstood the second parameter meaning.

0 Votes 0 ·