代码测试之内存越界

发表于:2011-12-20 10:18

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:feixiaoxing    来源:51Testing软件测试网采编

  内存越界是我们软件开发中经常遇到的一个问题。不经意间的复制常常导致很严重的后果。经常使用memset、memmove、strcpy、strncpy、strcat、sprintf的朋友肯定对此印象深刻,下面就是我个人在开发中实际遇到的一个开发问题,颇具典型。

  1. #define MAX_SET_STR_LENGTH  50  
  2. #define MAX_GET_STR_LENGTH 100  
  3.   
  4. int* process(char* pMem, int size)  
  5. {  
  6.     char localMemory[MAX_SET_STR_LENGTH] = {0};  
  7.     int* pData = NULL;  
  8.   
  9.     /*  code process */  
  10.     memset(localMemory, 1, MAX_GET_STR_LENGTH);  
  11.     memmove(pMem, localMemory, MAX_GET_STR_LENGTH);  
  12.     return pData;  
  13. }

  这段代码看上去没有什么问题。我们本意是对localMemory进行赋值,然后拷贝到pMem指向的内存中去。其实问题就出在这一句memset的大小。根据localMemory初始化定义语句,我们可以看出localMemory其实最初的申明大小只有MAX_SET_STR_LENGTH,但是我们赋值的时候,却设置成了MAX_GET_STR_LENGTH。之所以会犯这样的错误,主要是因为MAX_GET_STR_LENGTH和MAX_SET_STR_LENGTH极其相似。这段代码编译后,产生的后果是非常严重的,不断冲垮了堆栈信息,还把返回的int*设置成了非法值。

  那么有没有什么好的办法来处理这样一个问题?我们可以换一个方向来看。首先我们查看,在软件中存在的数据类型主要有哪些?无非就是全局数据、堆数据、栈临时数据。搞清楚了需要控制的数据之后,我们应该怎么对这些数据进行监控呢,一个简单有效的办法就是把memset这些函数替换成我们自己的函数,在这些函数中我们严格对指针的复制、拷贝进行判断和监督。

  (1)事实上,一般来说malloc的数据是不需要我们监督的,因为内存分配的时候,通常库函数会比我们要求的size多分配几个字节,这样在free的时候就可以判断内存的开头和结尾处有没有指针溢出。朋友们可以试一下下面这段代码。

  1. void heap_memory_leak()  
  2. {  
  3.     char* pMem = (char*)malloc(100);  
  4.     pMem[-1] = 100;  
  5.     pMem[100] = 100;  
  6.     free(pMem);  
  7. }

  pMem[-1] = 100是堆左溢出, pMem[100]是堆右溢出。

  (2)堆全局数据和栈临时数据进行处理时,我们利用memset初始化记录全局指针或者是堆栈临时指针

  a)首先对memset处理,添加下面一句宏语句

  #define memset(param, value, size)      MEMORY_SET_PROCESS(__FUNCTION__, __LINE__, param, value, size)

  b)定义内存节点结构

  1. typedef struct _MEMORY_NODE  
  2. {  
  3.     char functionName[64];  
  4.     int line;  
  5.     void* pAddress;  
  6.     int size;  
  7.     struct _MEMORY_NODE* next;  
  8.   
  9. }MEMORY_NODE;

  其中functionName记录了函数名称,line记录文件行数, pAddress记录了指针地址, size指向了pAddress指向的内存大小,next指向下一个结构节点。

  c)记录内存节点属性

  在MEMORY_SET_PROCESS处理过程中,不仅需要调用memset函数,还需要对当前内存节点进行记录和保存。可以通过使用单链表节点的方法进行记录。但是如果发现pAddress指向的内存是malloc时候分配过的,此时就不需要记录了,因为堆内存指针溢出的问题lib库已经帮我们解决了。

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号