前一段时间遇到了一个非常有意思的问题,在控件的页面上显示了非法的字符串
接下来大家就一步步根据上次的定位思路来看下这个问题。
首先,找到这块控件的代码
class CItem
{
****
std::string input;
****
}
发现这个控件里有一个默认构造的string对象,由此可以大胆猜测,有没有可能是string的静态变量地址被篡改了。
然后,我们运行core来看下string的字符串地址。
(gdb) thread apply all bt
发现线程里没有页面的信息,所有只能从别的地方入手。由标准库的string实现我们知道,默认构造生成的字符串地址,均指向同一个全局静态变量。Cpage页面继承自Citem,而Citem中有一个string的成员,所有我们查找包含page页面的线程。查看Cpage的string成员地址即可找到Citem类的string成员地址
class CPage : public CItem
{
***
std::string m_title;
***
}
上面有一个string成员,分别打印他们的值
并且查看符号表可知,m_title是默认构造生成的string
pm_title
{static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
_M_p = 0x3ddc9b8 <_ZNSs4_Rep20_S_empty_rep_storageE@@GLIBCXX_3.4+24> "*******}}
(gdb) info symbol _ZNSs4_Rep20_S_empty_rep_storageE
std::string::_Rep::_S_empty_rep_storage in section .bss of /usr/lib64/libstdc++.so.6
所以我们知道肯定是string的静态变量内容被覆盖了。现在有2个思路,一个是静态变量地址越界,还有一种是静态变量的内容被其他默认构造生成的字符串篡改。
先看第一种思路
(gdb) x /32xg 0x3ddc9b8 - 8*16
0x3ddc938: 0x0000000000000000 0x0000000000000000
0x3ddc948 0x00000030144ee1b0 0x00000030142bd4e0
0x3ddc958: 0x00000030142bd500 0x00000030142bd430
0x3ddc968: 0x00000030142bd830 0x00000030142bd210
0x3ddc978: 0x00000030142bd840 0x00000030142bd440
0x3ddc988: 0x0000000000000000 0x0000000000000000
0x3ddc998: 0x0000000000000000 0x0000000000000000
0x3ddc9a8 : 0x0000000000000000 0x0000000000000000
0x3ddc9b8 : ******** *********
0x3ddc9c8 : 0x00000030142c8352 0x0000000000000000
0x3ddc9d8: 0x0000000000000000 0x0000000000000058
0x3ddc9e8 : 0x0000000000000000 0x00000030144ec5e0
0x3ddc9f8 : 0x0000003014299d50 0x000000301429a9d0
0x3ddca08 : 0xffffffffffffffa8 0xffffffffffffffa8
0x3ddca18: 0x00000030144ec5e0 0x0000003014299d40
0x3ddca28: 0x000000301429a9c0 0x0000000000000000
(gdb)
从内存地址看,之前的内存地址都是0,不太像是被内存越界改掉的。
再来看第二种思路,用上面非法的字符串搜索代码中出现的字符串位置,在代码中检索出一段代码,往静态变量地址写数据的地方
之后在测试的时候,使用gdb watch这个地址,发现问题就是出在这里。
如果在代码中没有检索到dav关键字,可以在服务器上输入如下命令,看哪些第三方库使用到。
[root]$ find .|xargs grep -ri "string" -l