在用CString的时候,一直用TrimRight去掉空格,及右侧的字符,字符串,用着挺方便,一直没多考过真正含义,结果终于有一天莫名的出错了。
写一个检查程序时,想保留IAT中的API名称,但不要Ex,ExA ,这些扩展的名称,因为从API函数的含义上这些都是一个意思。
所以有如下程序,
void parse_iat_api_name(char *iat_api_name)
{
CString strAPI = iat_api_name;
strAPI.TrimRight("ExA");
strAPI.TrimRight("ExW");
}
乍一看代码没问题,跑了一些测试样本也没问题,但当iat_api_name = “OpenMutexA” ,有这类特点的Api 时问题来了,经过转换,strAPI变成了OpenMute, 那个‘x’ 被干掉了,按我以前的理解是,这个函数,大小写敏感的匹配右段,然后干掉右侧能匹配的字符串,可惜结果不是,下面是MFC中的实现,
void CString::TrimRight(LPCTSTR lpszTargetList)
{
// find beginning of trailing matches
// by starting at beginning (DBCS aware)
CopyBeforeWrite();
LPTSTR lpsz = m_pchData;
LPTSTR lpszLast = NULL;
while (*lpsz != '\0')
{
if (_tcschr(lpszTargetList, *lpsz) != NULL) --- 当”OpenMutexA“递减到仅剩"xA"时,被”ExA“匹配到,
{ --- 出了问题
if (lpszLast == NULL)
lpszLast = lpsz;
}
else
lpszLast = NULL;
lpsz = _tcsinc(lpsz); ----》 _tcsinc 相当于让lpsz 做指针加1的操作,不断从左侧递减要
处理的“OpenMutexA”
}
if (lpszLast != NULL)
{
// truncate at left-most matching character
*lpszLast = '\0';
GetData()->nDataLength = lpszLast - m_pchData;
}
}
所以该函数并不是全字匹配右端函数,我理解上有误。
---------------------------------------------------------------------------------------------------------
下面给出安全的去掉右端的字符串的代码
想要去除的右侧后缀,添加ptrimstring 到表即可
bool trim_r_string(char *string,CString &str)
{
if(!string)
return fasle;
CString str = string;
const char *ptrimstring[] =
{
"ExA",
"ExW",
"Ex",
"A",
"W",
0
}; // 这里要注意,一定要从字符多到字符少的这个顺序.
int str_size = str.GetLength();
for(int i = 0; ptrimstring[i];i++)
{
int len = strlen(ptrimstring[i]);
if(len >= str_size)
continue;
char *pex = (LPSTR)(LPCTSTR)str;
pex += (str_size - len);
if(pex && 0 == strncmp(pex,ptrimstring[i],len))
{
strAPI = strAPI.Left(str_size - len);
break;
}
}
return true;
}
写一个检查程序时,想保留IAT中的API名称,但不要Ex,ExA ,这些扩展的名称,因为从API函数的含义上这些都是一个意思。
所以有如下程序,
void parse_iat_api_name(char *iat_api_name)
{
CString strAPI = iat_api_name;
strAPI.TrimRight("ExA");
strAPI.TrimRight("ExW");
}
乍一看代码没问题,跑了一些测试样本也没问题,但当iat_api_name = “OpenMutexA” ,有这类特点的Api 时问题来了,经过转换,strAPI变成了OpenMute, 那个‘x’ 被干掉了,按我以前的理解是,这个函数,大小写敏感的匹配右段,然后干掉右侧能匹配的字符串,可惜结果不是,下面是MFC中的实现,
void CString::TrimRight(LPCTSTR lpszTargetList)
{
// find beginning of trailing matches
// by starting at beginning (DBCS aware)
CopyBeforeWrite();
LPTSTR lpsz = m_pchData;
LPTSTR lpszLast = NULL;
while (*lpsz != '\0')
{
if (_tcschr(lpszTargetList, *lpsz) != NULL) --- 当”OpenMutexA“递减到仅剩"xA"时,被”ExA“匹配到,
{ --- 出了问题
if (lpszLast == NULL)
lpszLast = lpsz;
}
else
lpszLast = NULL;
lpsz = _tcsinc(lpsz); ----》 _tcsinc 相当于让lpsz 做指针加1的操作,不断从左侧递减要
处理的“OpenMutexA”
}
if (lpszLast != NULL)
{
// truncate at left-most matching character
*lpszLast = '\0';
GetData()->nDataLength = lpszLast - m_pchData;
}
}
所以该函数并不是全字匹配右端函数,我理解上有误。
---------------------------------------------------------------------------------------------------------
下面给出安全的去掉右端的字符串的代码
想要去除的右侧后缀,添加ptrimstring 到表即可
bool trim_r_string(char *string,CString &str)
{
if(!string)
return fasle;
CString str = string;
const char *ptrimstring[] =
{
"ExA",
"ExW",
"Ex",
"A",
"W",
0
}; // 这里要注意,一定要从字符多到字符少的这个顺序.
int str_size = str.GetLength();
for(int i = 0; ptrimstring[i];i++)
{
int len = strlen(ptrimstring[i]);
if(len >= str_size)
continue;
char *pex = (LPSTR)(LPCTSTR)str;
pex += (str_size - len);
if(pex && 0 == strncmp(pex,ptrimstring[i],len))
{
strAPI = strAPI.Left(str_size - len);
break;
}
}
return true;
}