当整数溢出时,(unsigned int) * (int)
的结果是什么?unsigned
还是int
? 对于char*
,数组索引运算符(operator[]
)使用什么类型: int
、unsigned int
或其他类型?
我在审计以下函数时,突然出现了这个问题。该函数在第17行存在漏洞。
// Create a character array and initialize it with init[]
// repeatedly. The size of this character array is specified by
// w*h.
char *function4(unsigned int w, unsigned int h, char *init)
{
char *buf;
int i;
if (w*h > 4096)
return (NULL);
buf = (char *)malloc(4096+1);
if (!buf)
return (NULL);
for (i=0; i<h; i++)
memcpy(&buf[i*w], init, w); // line 17
buf[4096] = '\0';
return buf;
}
考虑到
w
和 h
都是非常大的无符号整数。第 9 行的乘法有通过验证的机会。现在问题出在第 17 行。将
int i
与 unsigned int w
相乘:如果结果是 int
,则可能导致乘积为负数,从而访问了 buf
之前的位置。如果结果是 unsigned int
,则乘积总是为正数,从而访问了 buf
之后的位置。很难编写代码来证明这一点:
int
太大了。有人有什么想法吗?是否有任何规定产品类型的文档?我已经搜索过了,但迄今为止还没有找到任何东西。
我认为就漏洞而言,
(unsigned int) * (int)
生成 unsigned int
或 int
并不重要,因为在编译的目标文件中,它们只是字节。以下代码对于产品类型的类型都是相同的:unsigned int x = 10;
int y = -10;
printf("%d\n", x * y); // print x * y in signed integer
printf("%u\n", x * y); // print x * y in unsigned integer
因此,乘法返回的类型并不重要。重要的是消费函数是否使用
int
或unsigned
。这里的问题不是函数有多差,或者如何改进函数使其更好。函数无疑存在漏洞。问题是基于标准规定的预期行为,该函数的确切行为是什么。
if (!h || w > 4096/h) return NULL;
。 - R.. GitHub STOP HELPING ICElong long
进行检查更好、更快。long*long
比除法更高效。 - Mark Lakata