在缓冲区溢出时自动截断和 null 终止字符串缓冲区

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

我有以下代码,可以从指定的 parent window 的所有 child windows 加载文本。它工作正常,但有时,有一些 parent windows(例如用很长的 C++ 源文件打开记事本)那些有大量文本并导致缓冲区溢出。

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'[=10=]';
    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'[=10=]';

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

        szWindowText[nBuffer] = L'[=10=]';
    }
    return TRUE;
}

SendMessage(hWnd, WM_GETTEXT, (WPARAM)32767, reinterpret_cast<LPARAM>(&szText)); 行有时会导致缓冲区溢出并且我的应用程序崩溃。

我知道如何像 if (TEXT_LENGTH > 32767) 一样检测这种溢出,但我无法动态增加缓冲区的大小 szText

正如问题标题提到的,我不想增加它的大小,我只想截断和空终止 return 文本到 32767 的最大缓冲区大小(如果 TEXT_LENGTH结束了32767),分配给szWindowText作他用。

非常感谢任何帮助。

几件事:

  1. 最好将缓冲区动态分配给TEXT_LENGTH。 (对于“\0”+1)
  2. 去掉WM_GETTEXT中szText的&运算符,只需要包含的地址,不需要指针的地址
  3. 当您显式使用 char 时,使用 SendMessageA,否则 visual studio 默认为 wchar_t 和 SendMessageW。 SendMessage 是一个宏,根据您的项目设置扩展为 wchar_t 或字符。或者将 TCHAR 类型与 SendMessage 一起使用,它也可以扩展为正确的类型。

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;
}

基本上你需要为 \n 腾出空间,无论你为什么要插入它,方法是在 WM_GETTEXT 中使用 sizeof szText-1 而不是 32767打电话。

注意如果您必须使用 Simonyi 表示法,请不要在不适用的地方使用它。 szText 没有任何以 null 结尾的内容,您仅将其用于 WM_GETTEXT.

的结果

SendMessage(hWnd, WM_GETTEXT, (WPARAM)32767, reinterpret_cast<LPARAM>(&szText)); 永远不会导致缓冲区溢出,因为提供了正确大小的缓冲区。实际上根本不需要这个临时缓冲区。

您真正的问题是您在不知道目标缓冲区大小的情况下将字符附加到作为 lParam 提供的指针中。您应该提供目标缓冲区大小。