问题描述
计算机系统:程序员的观点说:
1 /* Illustration of code vulnerability similar to that found in 2 * Sun’s XDR library. 3 */ 4 void* copy_elements(void *ele_src[],int ele_cnt,size_t ele_size) { 5 /* 6 * Allocate buffer for ele_cnt objects,each of ele_size bytes 7 * and copy from locations designated by ele_src 8 */ 9 void *result = malloc(ele_cnt * ele_size); 10 if (result == NULL) 11 /* malloc failed */ 12 return NULL; 13 void *next = result; 14 int i; 15 for (i = 0; i < ele_cnt; i++) { 16 /* Copy object i to destination */ 17 memcpy(next,ele_src[i],ele_size); 18 /* Move pointer to next memory region */ 19 next += ele_size; 20 } 21 return result; 22 }
copy_elements函数旨在复制ele_cnt数据 结构,每个结构由ele_ size个字节组成,并分配给缓冲区 通过第9行上的函数。所需的字节数计算为 ele_cnt * ele_size。
但是,想象一下,一个恶意的程序员使用 ele_cnt是1,048,577(2 ^ 20 +1)和ele_size是4,096(2 ^ 12) 程序编译为32位。 然后在线进行乘法 9将溢出,导致仅分配4,096字节,而不是 保持这么多数据所需的4,294,971,392字节。循环 从第15行开始,将尝试复制所有这些字节, 超出分配的缓冲区的末尾,因此损坏 其他数据结构。这可能导致程序崩溃或 否则行为不正常。
我想知道如何将代码更改为由于算术溢出而没有漏洞?
谢谢。
解决方法
从数学角度来看,您要检查((?:\d\s*){5,11}\d?)
。但是由于溢出,您无法在代码中执行此操作。您可以改用一些代数来避免溢出。您还想先检查两个值都为正:
(size_t)-1 < ele_cnt * ele_size
关于强制转换if ((ele_size == 0) || (ele_cnt <= 0) || ((size_t)-1 / ele_size < ele_cnt)) {
return NULL;
}
,因为(size_t)-1
是无符号类型,所以转换定义得很好,并求值可以存储在size_t
中的最大值。