先上代码。
#define KEYVALUE_MAX_SIZE 512
HRESULT HvGetNonGreedyMatchBetweenBeginLabelAndEndLabel(const CHAR* szBeginLabel,const CHAR* szEndLabel,const CHAR* pszRetMsg, INT nRetMsgLen, CHAR* szJieQuReslut, INT nReslutLen )
{
if ( NULL == szBeginLabel || NULL == szEndLabel || NULL == pszRetMsg || NULL == szJieQuReslut)
{
WrightLogEx("testIP" , "HvGetNonGreedyMatchBetweenBeginLabelAndEndLabel point is NULL");
return E_FAIL;
}
memset(szJieQuReslut, 0, nReslutLen);
const char* pBegin = strstr( pszRetMsg , szBeginLabel );
if (pBegin!=NULL)
{
pBegin+=strlen(szBeginLabel);
}
else
{
WrightLogEx("testIP" , "HvGetNonGreedyMatchBetweenBeginLabelAndEndLabel can not find begin Label");
return E_FAIL;
}
const char* pEnd=strstr(pBegin, szEndLabel);
if ( NULL != pEnd )
{
if (pEnd - pBegin >= nReslutLen)
{
WrightLogEx("testIP" , "HvGetNonGreedyMatchBetweenBeginLabelAndEndLabel can not find end Label");
return E_FAIL;
}
memcpy( szJieQuReslut ,pBegin , pEnd-pBegin );
return S_OK;
}
return E_FAIL;
}
//无限循环的for循环。
for (int i = 0; i < g_XmlCmdAppendInfoMap[iCmdIndex].iParamNum; i++)
{
char szBeginLabel[128];
char szEndLabel[128];
char szResult[128]={0};
sprintf(szBeginLabel,"%s=[", *(&(g_XmlCmdAppendInfoMap[iCmdIndex].szParamName1) + i) );
strcpy(szEndLabel, "]");
if( S_OK == HvGetNonGreedyMatchBetweenBeginLabelAndEndLabel(szBeginLabel, szEndLabel, pszRetMsg, strlen(pszRetMsg), szResult, KEYVALUE_MAX_SIZE))
{
pElementRet->SetAttribute(
*(&(g_XmlCmdAppendInfoMap[iCmdIndex].szParamName1) + i),//这里有个地址偏移访问,让属性位置想后移动
szResult);
}
else
{
pElementRet->SetAttribute(
*(&(g_XmlCmdAppendInfoMap[iCmdIndex].szParamName1) + i),//这里有个地址偏移访问,让属性位置想后移动
"");
}
}
why
今天为了扩充xml私有协议的字符串大小,把KEYVALUE_MAX_SIZE 宏由128改成512。
然后发现程序陷入一个函数里,永远没有返回的样子。
然后多次按alt + ctrl + break,一直断在一个for循环里面。然后跟进去单步调试,发现循环迭代子i,每次循环都是0,就一直在循环体出不来了。
然后围观上下文,发现蹊跷的地方在:
<pre name="code" class="cpp">HvGetNonGreedyMatchBetweenBeginLabelAndEndLabel函数的
memset(szJieQuReslut, 0, nReslutLen);,第一个可能越界的地方
<pre name="code" class="cpp">memcpy( szJieQuReslut ,pBegin , pEnd-pBegin );第二个可能越界的地方。
尼玛,把szResult缓冲区越界清0了。
注意下不安全的赋值。
另外私有协议传长的字符串,不应该走xml路线,然后又用固定长度的buf解析。最好直接走二进制。