C++ C+中的堆栈溢出校正+;

C++ C+中的堆栈溢出校正+;,c++,stack-overflow,C++,Stack Overflow,我在一本书中读到了下面的代码,书中说这很容易受到堆栈溢出的影响。虽然使用了fgets(),但我无法理解,为什么它容易受到攻击 我的理解是,使用fgets()而不是get()通常通过在末尾放置null来帮助我们消除缓冲区溢出。我错过什么了吗?应该使用什么代替fgets()来纠正堆栈溢出 void getinp(char *inp, int siz) { puts("Input value: "); fgets(inp, siz, stdin); printf("buffer3 g

我在一本书中读到了下面的代码,书中说这很容易受到堆栈溢出的影响。虽然使用了fgets(),但我无法理解,为什么它容易受到攻击

我的理解是,使用fgets()而不是get()通常通过在末尾放置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");
}

在display中,无法确定val+12字节是否适合16个字符的缓冲区。

display中
tmp
声明为16
char
s长,但您正在编写(使用
sprintf
)不仅
val
(保证为16个字符或更少),而且
“读取val:”
和最后的
\n

这意味着,如果用户插入的字符超过16-11=5个,则
显示中的缓冲区溢出

一种解决方案是在
display
中声明
buf
足够大,以存储
val
和附加文本,尽管在现实世界中,您只需使用
printf
写入
stdout
(无中间缓冲区)


另外,通常当您有一个
sprintf
并且存在缓冲区溢出的潜在风险时,您会使用
snprintf
(实际上,我总是使用它);
snprintf
,而不是溢出缓冲区,如果输出太长,则截断输出,并返回如果输出缓冲区足够大,将写入的字符数。

查看代码以及这两个答案如何解释它,我认为这实际上不是关于堆栈溢出,而是关于溢出用于读取文本的16字节缓冲区的流。该缓冲区实际上是在堆栈上分配的,但即使该缓冲区中存在溢出,我也不会将其称为堆栈溢出。不要混淆堆栈溢出(通常通过无限递归发生)缓冲区溢出是指将太多数据写入缓冲区;特别是堆栈缓冲区溢出是指存储在堆栈上的缓冲区溢出。感谢您的快速回复。因此,函数getinp不对溢出负责,是内置的sprintf函数在执行此操作。将此行添加到上述程序中在函数void display中,更正缓冲区溢出??snprintf(tmp,sizeof(tmp),“read val:%s\n”,val);这将防止缓冲区溢出,但不允许打印长度超过5个字符的输入字符串。您还应放大buf(或仅使用printf而不是sprintf+put)。