Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatically truncate and null terminate a string buffer in a buffer overflow

I have following code, which can load text from all child windows of a specified parent window. It works fine, but sometimes, there are some parent windows (such as opened Notepad with a very long C++ source file) those have large amount of text and cause a buffer overflow.

BOOL CALLBACK EnumChildProc(__in HWND hWnd, __in LPARAM lParam) {

    LRESULT TEXT_LENGTH = NULL;
    WCHAR szText[32767];
    LPWSTR szWindowText;
    UINT nBuffer = NULL, nText = NULL;

    szWindowText = reinterpret_cast<LPWSTR>(lParam); szText[0] = L'\0';
    nBuffer = (UINT)wcslen(szWindowText);
    TEXT_LENGTH = SendMessage(hWnd, WM_GETTEXTLENGTH, NULL, NULL);

    if (TEXT_LENGTH > NULL)
    {
        SendMessage(hWnd, WM_GETTEXT, (WPARAM)32767, reinterpret_cast<LPARAM>(&szText));
        szText[TEXT_LENGTH] = L'\n'; szText[TEXT_LENGTH + 1] = L'\0';

        while ((nBuffer < 32766) && (szText[nText] != L'\0'))
        { szWindowText[nBuffer++] = szText[nText++]; }

        szWindowText[nBuffer] = L'\0';
    }
    return TRUE;
}

The line SendMessage(hWnd, WM_GETTEXT, (WPARAM)32767, reinterpret_cast<LPARAM>(&szText)); sometimes causes a buffer overflow and my application crashes.

I know how to detect this overflow like if (TEXT_LENGTH > 32767), but I cannot dynamically increase the size of the buffer szText.

As the question title mentions, I don't want to increase its size, I just want to truncate and null terminate return text to maximum buffer size of 32767 (if TEXT_LENGTH is over 32767) and assign it to szWindowText to be used for other purposes.

Any help is greatly appreciated.

like image 535
Blueeyes789 Avatar asked Oct 18 '22 07:10

Blueeyes789


1 Answers

A few things:

  1. It's better to dynamically allocate the buffer to TEXT_LENGTH. (+1 for '\0')
  2. Drop the & operator of szText in WM_GETTEXT, you just need the address contained, not the address of the pointer
  3. When you explicitly use char's, use SendMessageA, otherwise visual studio defaults to wchar_t with SendMessageW. SendMessage is a macro which expands to wchar_t or char depending on your project settings. Or use TCHAR type with SendMessage which expands to the correct type also.

DWORD l = SendMessage(hWnd, WM_GETTEXTLENGTH, NULL, NULL);

if (l > 0){
   TCHAR *szText = new TCHAR[l + 1];
   SendMessage(hWnd, WM_GETTEXT, (WPARAM)l + 1, reinterpret_cast<LPARAM>(szText));

  // use szText

   delete[] szText;
}
like image 137
Serve Laurijssen Avatar answered Nov 11 '22 15:11

Serve Laurijssen