我在一本书中读到了下面的代码,该书说这很容易受到堆栈溢出的影响。虽然已经使用了fgets(),但我无法理解为什么它容易受到攻击?
我的理解是使用fgets()而不是gets()通常可以通过在末尾放置null来帮助我们摆脱缓冲区溢出。我错过了什么吗?应该使用什么来代替fgets()来纠正堆栈溢出?
void getinp(char *inp, int siz)
{
puts("Input value: ");
fgets(inp, siz, stdin);
printf("buffer3 getinp read %s\n", inp);
}
void display(char * val)
{
char tmp[16];
sprintf(tmp, "read val: %s\n", val);
puts(tmp);
}
int main(int argc, char *argv[])
{
char buf[16];
getinp(buf, sizeof(buf));
display(buf);
printf("buffer3 done\n");
}
答案 0 :(得分:1)
在display
tmp
被宣布为16 char
s长,但您正在撰写(sprintf
)不仅val
(这是"read val: "
保证不超过16个字符),但\n
和最终display
)。
这意味着如果用户插入超过16-11 = 5个字符,则buf
中的缓冲区溢出。
一个解决方案可能是声明display
中的val
足够大以存储stdout
和其他文本,尽管在现实世界中您只需写入printf
使用sprintf
(没有中间缓冲区)。
此外,通常当你有snprintf
并且存在缓冲区溢出的潜在风险时,你可以使用snprintf
代替(实际上,我使用它总是); {{1}},而不是溢出缓冲区,如果输出太长则截断输出,并返回如果输出缓冲区足够大就会写入的字符数。
答案 1 :(得分:0)
在显示中,无法确定val + 12字节是否适合16个字符的缓冲区。