如何更改此代码才能不存在算术溢出漏洞? [已关闭]

问题描述 投票:0回答:1

计算机系统:程序员的视角 说:

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 行开始将尝试复制所有这些字节, 超出了分配的缓冲区的末尾,因此损坏 其他数据结构。这可能会导致程序崩溃或 否则行为不当。

我想知道如何更改代码以不因算术溢出而出现漏洞?

谢谢。

c overflow integer-arithmetic defensive-programming
1个回答
2
投票

从数学角度来看,你想要检查

(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
是无符号类型,所以转换定义良好,并且计算结果为可以存储在
size_t
中的最大值。

© www.soinside.com 2019 - 2024. All rights reserved.