一个变量越界导致破坏堆栈的bug

前一段时间在商用系统上出现了core dump,原因是由于一个局部变量写越界导致堆栈被破坏了。在这里,我把这个bug分享一下,希望给需要的朋友一点帮助。简化的代码如下:

typedef struct
{
    ......
} A;

void func1(char *p)
{
    ......
}

void main(void)
{
    A a;
    A *p = &a;
    char b[10];

    ......
    /* 
     * 这个程序运行在SPARC处理器上, 而SPARC处理器的堆栈生长
     * 方向是从高地址向低地址生长的.
     * 这个函数里会把b这个数组写越界,导致p这个变量被破坏, 
     * 结果在下面访问p时,是一个无效的值,导致core dump.
     */
    func1(b);
    printf("%p\n", p);
    ......

    return;
}

通过分析这个bug,分享一下我的心得体会:
(1)SPARC处理器是当年SUN公司开发的一款RISC处理器,如果有朋友从事Solaris软件开发,应该还是会接触到的。我一直觉得作为底层软件工程师,还是应该对处理器结构(包括汇编语言)有尽可能多的了解,这样对我们分析和解决问题都会有很大帮助。比方说,在分析这个bug时,如果知道SPARC处理器的堆栈生长方向是从高地址向低地址生长的,就会让我们把注意力集中在变量定义在p后面的变量上,这样就有了分析问题的方向。在这里,我推荐一篇介绍SPARC处理器的文章(http://web.cecs.pdx.edu/~apt/cs577_2008/sparc_s.pdf),有兴趣的朋友可以看一下。
(2)当遇到堆栈上的变量被莫名其妙改变时,首先还是检查那些地址比被破坏变量地址低的变量。因为一般有可能引起内存越界的代码,像memcpy,都会破坏高地址的值。以这个bug为例。变量p在一开始就赋了值,以后对p都是读操作,没有写操作。现在p变成了一个无效的值,那么首先就应该怀疑访问定义在p后面的变量出了问题。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.