C++(真的)安全标准字符串搜索?
Posted
技术标签:
【中文标题】C++(真的)安全标准字符串搜索?【英文标题】:C++ (Really) Safe Standard String Search? 【发布时间】:2009-05-27 15:37:04 【问题描述】:缓冲区溢出问题是众所周知的。因此,我们有幸拥有诸如 wcscat_s() 之类的标准库函数。微软的好心人已经创建了类似的安全字符串函数,例如 StringCbCat()。
但我有一个问题,我需要在 一点内存 中搜索一个字符串。标准库函数:
wcsstr( wchar_t* pMem, wchar_t* pStr )
看起来不错,但是... 有时我的记忆包含垃圾,有时是字符串。当它是垃圾时,我有时会耗尽分配的内存页面,[=访问冲突]。我可以编写自己的函数是的。但我的问题是,是否有任何“标准”函数可以进行安全字符串搜索,例如:
"wcsstr_s( wchar_t* pMem, size_t uiSize, wchar_t* pStr )" ?
感谢
[编辑] 感谢查尔斯贝利对我的问题的完美回答。也感谢其他人的努力。
对于那些怀疑我的情景是否合理的人:是的,当然最好不要在我的记忆中留下垃圾。但我可以想象这种情况可能发生的几种情况。在我的特殊情况下,它是逆向工程,我正在搜索的内存实际上不是“我的内存”,它属于我无法控制的另一个过程。
(另一种假设情况可能是一个棘手的调试情况,需要追踪损坏的内存。)
【问题讨论】:
我很好奇。您有什么用例在字符串中搜索可能是垃圾的子字符串?抱歉,不,我不知道一个标准的宽字符库例程需要一个定界计数。 似乎是一个 C 问题,而不是 C++。如果您想安全,请使用 std::string 或 std:;wstring。 在这种情况下 uiSize 会是什么?从 pMem 开始分配的缓冲区的长度? "从 pMem 开始分配的缓冲区长度"是正确的假设。 【参考方案1】:可能不是您正在寻找的答案,但这里最好的解决方案可能是正确初始化您的字符串和指针。如果你的记忆里有垃圾,何不做点正经事,设置好
yourString[0] = '\0';
如果它真的只是一个任意位的缓冲区,您最好使用memcmp 之类的东西,然后沿着N
字符滑动内存缓冲区的指针(其中N
是您感兴趣的字符数减去您要比较的字符串的长度)。这可能不是最有效的实现,但我应该认为应该是一种相当稳健的方法。
[编辑]你的问题引起了我的兴趣,我做了一些实验。鉴于您似乎正在寻找更多 C 风格的答案,这里有一些我想出的代码 sn-p 来详细说明我的 memcmp 建议:
// SearchingMemoryForStrings.cpp : Defines the entry point for a win32 consol application
// Purpose : Demonstrates a way to search a section of memory for a particular string
//
#include <stdio.h>
#include <string.h>
#define VALUE_NOT_FOUND (-1)
int FindStringInBuffer( const char* pMemBuffer, const size_t& bufferSizeInBytes, const char* pStrToFind )
int stringFound = VALUE_NOT_FOUND; // Return value which will be >= 0 if we find the string we're after
const char* pMemToMatch = NULL; // An offset pointer to part of 'pMemBuffer' which we'll feed to memcmp to find 'pStrToFind'
// Set up some constants we'll use while searching
size_t lenOfStrToFind = strlen( pStrToFind );
size_t lastSearchablePosition = bufferSizeInBytes - lenOfStrToFind;
// Search the memory buffer, shifting one character at a time for 'pStrToFind'
for( size_t i = 0; i <= lastSearchablePosition; i++ )
pMemToMatch = &pMemBuffer[i];
if( memcmp(pMemToMatch, pStrToFind, lenOfStrToFind) == 0 )
// We found the string we're looking for
stringFound = i;
break;
return stringFound;
void ReportResult( int returnVal, const char* stringToFind )
if( returnVal == VALUE_NOT_FOUND )
// Fail!
printf("Error, failed to find '%s' - search function returned %d\n", stringToFind, returnVal );
else
// Win!
printf("Success, found '%s' at index %d\n", stringToFind, returnVal );
void FindAndReport( const char* pMemBuffer, const size_t& bufferSizeInBytes, const char* pStrToFind )
int result = FindStringInBuffer( pMemBuffer, bufferSizeInBytes, pStrToFind );
ReportResult( result, pStrToFind );
int main( int argc, char* argv[] )
const int SIZE_OF_BUFFER = 1024; // Some aribitrary buffer size
char some_memory[SIZE_OF_BUFFER]; // The buffer of randomly assigned memory to look for our string
const char* stringToFind = "This test should pass";
const char* stringYouWontFind = "This test should fail";
FindAndReport( some_memory, SIZE_OF_BUFFER, stringYouWontFind ); // Should fail gracefully
// Set the end of the buffer to the string we're looking for
memcpy( &some_memory[SIZE_OF_BUFFER-strlen(stringToFind)], stringToFind, strlen(stringToFind) );
FindAndReport( some_memory, SIZE_OF_BUFFER, stringToFind ); // Should succeed this time and report an index of 1003
// Try adding at some arbitrary position
memcpy( &some_memory[100], stringToFind, strlen(stringToFind) );
FindAndReport( some_memory, SIZE_OF_BUFFER, stringToFind ); // Should still succeed but report the offset as 100
FindAndReport( some_memory, SIZE_OF_BUFFER, stringYouWontFind ); // Should still fail
return 0;
在 Visual Studio 2008 下编译为 Win32 控制台应用程序的 sn-p。给我以下内容:
Error, failed to find 'This test should fail' - search function returned -1
Success, found 'This test should pass' at index 1003
Success, found 'This test should pass' at index 100
Error, failed to find 'This test should fail' - search function returned -1
FindStringInBuffer
函数是您想要的,如果您需要处理宽字符,则需要进行一些转换,但这至少应该为您提供一些可以继续进行的想法。如果您确实提出了 wchar 版本,我很想看看解决方案是什么样的(我自己没有处理过它们)。
【讨论】:
【参考方案2】:假设您的pStr
是空终止的,并且uiSize
是pMem
处可读内存的wchar_t
的数量:
wchar_t* pSubStr = std::search( pMem, pMem + uiSize, pStr, pStr + std::wcslen( pStr ) );
// Optionally, change to the 'conventional' strstr return value
if( pSubStr == pMem + uiSize)
pSubStr = 0;
【讨论】:
【参考方案3】:唉,我知道仍然没有标准的“安全”字符串库。 BSD 为此提供了 strnstr,但据我所知,它不在 glibc 或 Microsoft 的 libc 中。我不知道有什么“好”的选择,除了你自己的。
作为参考,http://msdn.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx 列出了 Microsoft 安全字符串库,http://msdn.microsoft.com/en-us/library/bb288454.aspx 提供了更详细的信息(带有迁移指南)。
【讨论】:
这里有 safeclib:github.com/rurban/safeclib wcsstr_s 刚刚被添加到那里。 errno_t wcsstr_s(wchar_t *restrict dest, rsize_t dmax, const wchar_t *restrict src, rsize_t slen, wchar_t **restrict substring)以上是关于C++(真的)安全标准字符串搜索?的主要内容,如果未能解决你的问题,请参考以下文章