如何防止扫描导致C中的缓冲区溢出?

如何防止扫描导致C中的缓冲区溢出?

我使用以下代码:

while ( scanf("%s", buf) == 1 ){

防止可能的缓冲区溢出从而传递随机长度字符串的最佳方法是什么?

我知道可以通过调用以下命令来限制输入字符串:

while ( scanf("%20s", buf) == 1 ){

但我更希望能够处理用户输入的任何内容。或者这不能安全地使用scanf,我应该使用fget?


叮当猫咪
浏览 809回答 3
3回答

精慕HU

在他们的书里编程实践(这很值得一读),克尼汉和派克讨论了这个问题,他们用snprintf()创建具有正确缓冲区大小的字符串以传递到scanf()功能家族。实际上:int&nbsp;scanner(const&nbsp;char&nbsp;*data,&nbsp;char&nbsp;*buffer,&nbsp;size_t&nbsp;buflen){ &nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;format[32]; &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(buflen&nbsp;==&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;snprintf(format,&nbsp;sizeof(format),&nbsp;"%%%ds",&nbsp;(int)(buflen-1)); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;sscanf(data,&nbsp;format,&nbsp;buffer);}注意,这仍然将输入限制在作为“缓冲区”提供的大小上。如果您需要更多的空间,那么您必须进行内存分配,或者使用一个非标准的库函数来为您分配内存。注意,POSIX 2008(2013)版scanf()函数族支持格式修饰符m(赋值-分配字符)用于字符串输入(%s,&nbsp;%c,&nbsp;%[)。而不是采取char *争论,这需要一个char **参数,并为其读取的值分配必要的空间:char&nbsp;*buffer&nbsp;=&nbsp;0;if&nbsp;(sscanf(data,&nbsp;"%ms",&nbsp;&buffer)&nbsp;==&nbsp;1){ &nbsp;&nbsp;&nbsp;&nbsp;printf("String&nbsp;is:&nbsp;<<%s>>\n",&nbsp;buffer); &nbsp;&nbsp;&nbsp;&nbsp;free(buffer);}如果sscanf()函数无法满足所有转换规范,然后它为其分配的所有内存。%ms-在函数返回之前释放类似的转换。

MYYA

如果您正在使用GCC,则可以使用GNU分机。a为您分配内存以保存输入的说明符:int&nbsp;main(){ &nbsp;&nbsp;char&nbsp;*str&nbsp;=&nbsp;NULL; &nbsp;&nbsp;scanf&nbsp;("%as",&nbsp;&str); &nbsp;&nbsp;if&nbsp;(str)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("\"%s\"\n",&nbsp;str); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(str); &nbsp;&nbsp;} &nbsp;&nbsp;return&nbsp;0;}编辑:正如乔纳森所指出的,您应该咨询scanf说明符可能与手册页不同(%m),您可能需要在编译时启用某些定义。

素胚勾勒不出你

在大多数情况下,fgets和sscanf做这份工作。另一件事是编写自己的解析器,如果输入格式化良好的话。还请注意,您的第二个示例需要进行一些修改才能安全地使用:#define&nbsp;LENGTH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;42#define&nbsp;str(x)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;x#define&nbsp;xstr(x)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;str(x)/*&nbsp;...&nbsp;*/&nbsp;int&nbsp;nc&nbsp;=&nbsp;scanf("%"xstr(LENGTH)"[^\n]%*[^\n]",&nbsp;array);上面的输入流向上丢弃,但不包括换行符(\n)性格。您将需要添加一个getchar()来消费这个。还请检查是否到达了流的末尾:if&nbsp;(!feof(stdin))&nbsp;{&nbsp;...仅此而已。
打开App,查看更多内容
随时随地看视频慕课网APP