|
今天算了一下,从做测试到现在差不多6年半了。从没有任何的测试知识与经验的newbie到中级测试大概花了4年半的时间,因此把一些文章收集起来编辑了《我的测试观点与经验(初中级篇)》。从中级到高级则是一个更加艰辛的道路,很多人甚至十几年而达不到,而我也面临着最后一步了,不知道能否坚持下来。我今天想了一下,从到达中级到现在的两年的时间里,我主要在两方面取得了较大进步。一是丰富了更多的测试方法与经验,包括驱动的测试,性能测试,压力测试等等。二是在debugging上取得了公认的进步,现在基本上上有任何debugger break都会来找我先看看,有很多是dev没搞清楚而是我找到的root cause的。由于出现的问题都是零零散散的,所以我想是不是应该回顾一下把他们总结一下,系统一下呢。
Debugging分user mode和kernel mode, 由于工作的原因我对kernel mode的debugging感觉还不是非常的自信,而user mode的话则基本没有太大问题,因此想先总结一下user mode。
我们在发现程序crash的时候,基本上都是因为AV产生了。所谓AV,就是Access Violation, 也就是说代码去访问了不该访问的内存。AV有read AV和write AV。AV产生意味着程序处于不正常的工作状态,如果继续运行下去的behavior是不可预测的,因此系统对付它最好的办法就是crash。初级测试人员对此类bug的描述一般用crash,因为不了解crash的原理,而中级测试则常常用AV来描述。这代表了一他懂debugging, 二他懂code。而debugging则是对初级与中级测试人员的一个明显的区分。
AV产生的原因大概有以下几种。
1. NULL pointer。程序对一个指针没有validation就直接使用。在debugging信息中你会看到access address 是 0×00000000。一看到这个地址你就去code里寻找通常很容易发现root cause。比如,
void foo(char* input)
{
printf(input);
}
正确代码应该是
void foo(char* input)
{
if(input)
printf(input);
}
2. Access freed memory。有些时候指针不是null,但是memory已经free了,因此上面的正确代码还是会产生AV。这时候你要去找free时候的代码。比如,
char* str=new char[5];
delete str;
foo(str);
正确的代码应该是
char* str=new char[5];
delete str;
str=null;
foo(str);
3. Buffer overrun。也就是著名的缓冲区溢出,几乎所有的安全漏洞都是根源于此。比如,
char* str=new char[5];
for(int i=0;i<5;i++)
str=’a’+i;
foo(str);
正确的代码应该是
char* str=new char[6];
for(int i=0;i<5;i++)
str=’a’+i;
str[5]=’’;
foo(str);
应该注意的是buffer overrun造成的后果不一定是AV。因为overrun之后访问的内容有可能是valid,而不会产生AV。黑客也正是利用了这个道理而注入malicious code。
最后,发现AV和root cause以后通常工作并没有完成。在open bug的时候要做security consequence的分析。比如AV很多时候可能引起DOS攻击,而Buffer overrun也常常造成系统漏洞。如果你进行了完整的分析之后就可以精确地设置bug severity和priority。
以上是造成AV的几个常见原因。我一般在自己的code crash的时候都不需要进行debugging,code review就足够了。
原文在http://peking2toronto.wordpress.com/ |
|