网上很多地方都可以找到下面的例子:
以下摘自 OpenSSH 3.3 的代码演示了整数溢出的经典案例: (错误代码) 示例语言:C
nresp = packet_get_int();
if (nresp > 0) {
response = xmalloc(nresp*sizeof(char*));
for (i = 0; i < nresp; i++) response[i] = packet_get_string(NULL);
}
如果 nresp 的值为 1073741824 并且 sizeof(char*) 有其典型值 值为4,则运算结果
溢出,xmalloc() 的参数将为 0。大多数 malloc() 实现将愉快地分配一个 0 字节缓冲区,从而导致 随后的循环迭代会溢出堆缓冲区响应。nresp*sizeof(char*)
如果 nresp 是一个 int 并且 sizeof() 返回一个 size_t(在 x86_64 中本质上是 unsigned long),则结果应该是 unsigned long。上面的问题是 xmalloc 的参数是 int 吗?或者该示例是否假设 IA32?如果不是,那是什么问题?
即使
nresp >= 0
和 sizeof(char*)
是一个很小的值,像 nresp*sizeof(char*)
这样的计算也存在溢出风险,因为它是 int * size_t
。
C 没有指定
size_t
比 int
更宽,尽管 v 是某种 unsigned 类型。 size_t
只能比 int
多 1 位,当 sizeof(char*)
大于 2 时,可能会发生溢出。
强大的代码可防止/检测潜在的溢出。
int nresp = packet_get_int();
if (nresp > 0) {
response = nresp > SIZE_MAX/sizeof(char*) ? NULL : xmalloc(nresp*sizeof(char*));
if (response == NULL) {
; // TBD code to handle allocation failure.
} else {
for (i = 0; i < nresp; i++) response[i] = packet_get_string(NULL);
}
}
}