数组越界错误

buggy code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
#include <string.h>
using std::string;

int main() {
string str = "abc";
char *s = (char *)malloc(str.size());
memcpy(s, str.data(), str.size());
for (int i = 0; i < 4096*8; ++i) {
printf("(%p,%c)", s + i, s[i]);
}
free(s);
return 0;

}

运行结果截图

解释

这是我为了复现这个bug而写的demo,实际情况要复杂得多。这类bug在真实环境中出现具有随机性。

我将i设置为 4096*8 ,而真实的s的大小只有3,由于访问越界将报出一个segmentation fault。有趣的是,这个报错并不在i = 3的时候出现,而是i很大并使得s + i等于0xd14000时才报错。多次尝试后发现,每次出现报错的地址不同,但后三位总是000

在真实环境中,i可能没有这么大,s + i很可能后三位总不为000,这将导致这个bug随机出现。

后三位总是000也很好解释,由于FS的特性,缺页读写的基本单元page size等于4096,即0x1000。虽然读s[3]时越界了,但由于s[3]仍在当前页中,不会触发异常,直到读到下一页0xd14000时,才报出读写权限冲突的错误。