我是C的新手,我遇到了一个奇怪的问题。
此代码是更大程序的一部分,但问题在于此处,但我似乎无法弄明白。
#include <stdio.h>
#include <string.h>
#define WORDSIZE 512
int read_stdNum(const char prompt[], char store[], size_t n) {
char inHold[WORDSIZE];
char process[10];
int status = 0;
while (1) {
fprintf(stderr, "%s", prompt);
if(fgets(inHold, WORDSIZE, stdin) == NULL) {
return 0;
}
sscanf(inHold, "%s", process);
status = sscanf(process, "%s", store);
if (status > 0 && strlen(store) == n) {
return 1;
} else if (status == -1) {
continue;
} else {
continue;
}
}
}
int main(void) {
char arrow[] = "\n==> ";
char stdNum[10];
printf("%s\n", "store_student called.");
fprintf(stderr, "%s", "\nEnter a student number (axxxxxxxx)\n");
read_stdNum(arrow, stdNum, 9);
return 0;
}
程序要求用户输入,这里的测试是程序截断额外的数字,但当我输入&#34; a123456789101112131415
&#34;之类的东西时,输出什么都没有,哪个工作正常,但然后提示结束写,提示符如下所示:
==> a123456789101112131415
131415_
下划线是我仍然可以输入的地方。 字符数组&#39;进程&#39;还存储超过9个字符。 我问了一些同学,还有一个人说他的电脑上运行正常。 我知道我会因为愚蠢而受到抨击,但我真的想知道为什么这不起作用。 感谢。
答案 0 :(得分:1)
scanf
”的 %s
函数可能不安全并且创建缓冲区溢出(它可能会在输出字符串中写入比为字符串分配的空间更多的字节,覆盖一些有用数据),检查https://cwe.mitre.org/data/definitions/120.html“CWE-120:不检查输入大小的缓冲区复制('经典缓冲区溢出')&amp;例1
https://en.wikipedia.org/wiki/Scanf_format_string#Vulnerabilities
这意味着使用没有长度说明符的
%s
占位符本质上是不安全的,并且可用于缓冲区溢出。
scanf
的文档对s
格式使用有一些要求(数组必须足够长)http://man7.org/linux/man-pages/man3/scanf.3.html
s Matches a sequence of non-white-space characters; the next pointer must be a pointer to the initial element of a character array that is long enough to hold the input sequence and the terminating null byte ('\0'), which is added automatically. The input string stops at white space or at the maximum field width, whichever occurs first.
类似scanf的函数的更安全使用是使用“{field 1}}或%9s
等”最大字段宽度“进行动态内存分配。
(您对m
的检查为时已晚; strlen
已经对字符串进行了溢出/覆盖,因为它对读取的长度没有限制。)