如何更改此代码以使其不容易受到算术溢出的影响?[关闭]

How can this code be changed to have no vulnerability to arithmetic overflow? [closed]

提问人:Tim 提问时间:10/8/2020 更新时间:10/8/2020 访问量:191

问:


想改进这个问题吗?更新问题,使其仅通过编辑这篇文章来关注一个问题。

3年前关闭。

Computer Systems: a Programmer's Perspective说道:

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_ 大小的字节组成,分配到一个缓冲区中 按第 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 溢出 整数算术 防御规划

评论

0赞 Tim 10/8/2020
@EugeneSh。有符号整数和无符号整数之间的乘法是无符号乘法吗?

答:

2赞 dbush 10/8/2020 #1

从数学的角度来看,您要检查 .但是,由于溢出,您无法在代码中执行此操作。您可以改用一些代数来避免溢出。您还需要首先检查这两个值是否为正数:(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)-1size_tsize_t

评论

0赞 Tim 10/8/2020
谢谢。在第 9 行中,有符号整数和无符号整数之间的乘法是无符号乘法吗?在乘法之前是否存在 from to 的隐式转换?是否需要在函数的参数列表中更改为?ele_cnt * ele_sizeele_cntintunsigned intint ele_cntsize_t ele_cnt
0赞 dbush 10/8/2020
@Tim 是的,存在 to 类型的隐式转换,以匹配乘法运算符和关系运算符的其他操作数。ele_cntsize_t
0赞 Tim 10/8/2020
这是个问题吗?是否需要在函数的参数列表中将 int ele_cnt更改为 size_t ele_cnt?
0赞 dbush 10/8/2020
@Tim 您可以更清楚地了解其用法,但这不是必需的。我提供的检查应该解决传入的任何问题。