#include <conio.h>
#include <windows.h>
#include <stdio.h>
int main ()
{
char input[255];
int i = 0;
for(;;i++) /* Infinite loop, exited when RETURN is pressed */
{
char temp;
temp = getch (); /* Get the current character of the password */
if (GetAsyncKeyState (VK_RETURN)) /* If the user has pressed return */
{
input[i]='\0';
break;
}
input[i] = temp;
printf("*"); /* Print a star */
}
//printf("%s",input);
if(strcmp(input,"kamal")==0)
{
printf("ACCEPTED");
}
else
printf("not");
_getch();
return EXIT_SUCCESS; /* Program was executed successfully */
}
这是我的代码。如何防止缓冲区溢出,如果我输入更多密码,那么我的程序崩溃了。无论如何我能解决这个问题吗?
答案 0 :(得分:2)
存储在堆栈中的局部变量char输入[255]。在C中没有对数组进行边界检查。问题是当我们添加超过255个字符时,堆栈中存储的另一个变量的值可能会发生变化。这可能会导致崩溃。
一种解决方案是,如果范围(i)小于255,则读取字符并仅分配给输入数组。
#include <conio.h>
#include <windows.h>
#include <stdio.h>
int main ()
{
char input[255];
int i = 0;
int flag = 0;
for(;;i++) /* Infinite loop, exited when RETURN is pressed */
{
char temp;
temp = getch (); /* Get the current character of the password */
if (GetAsyncKeyState (VK_RETURN)) /* If the user has pressed return */
{
input[i]='\0';
break;
}
if ( i< 255)
{
input[i] = temp;
}
else
{
flag = 1;
}
printf("*"); /* Print a star */
}
//printf("%s",input);
if(strcmp(input,"kamal")==0 && flag == 0)
{
printf("ACCEPTED");
}
else
printf("not");
getch();
return EXIT_SUCCESS; /* Program was executed successfully */
}
另一种解决方案是动态分配(realloc())输入数组的大小。
答案 1 :(得分:1)
始终检查边界。始终根据缓冲区的长度检查i的值。
答案 2 :(得分:1)
在某些情况下,扩展缓冲区是可以接受的。这很少是理想的,因为无限制的扩展可能会导致其他问题。
在其他情况下,截断输入是可以接受的。这可能是一个选项,但它也不理想。
在这种情况下,当您与不更改的字符串进行比较时,您可以跳过“将输入存储在数组中”阶段,并将输入的字节逐字节地与输入密码进行比较。这样的代码应该看起来像这样,但要小心,因为这是未经测试的:
char password[] = "kamal";
size_t position = 0;
char c = getch();
while (password[position] != '\0' || strchr("\r\n", (unsigned char) c) == NULL) {
if (c != password[position++] || position == sizeof password) {
// Password mismatch. Discard the rest of the password, then tell the user...
while (strchr("\r\n", (unsigned char) c) == NULL) {
c = getch();
}
position = 0;
puts("Invalid password. Please retry.");
}
c = getch();
}
...如果没有缓冲区溢出,那你还担心什么?
答案 3 :(得分:0)
尝试包装类似:
if(i<255) {
...
}
...围绕你的角色收集过程。
- 编辑 -
#include <conio.h>
#include <windows.h>
#include <stdio.h>
int main ()
{
char input[255];
int i = 0;
for(;;i++) /* Infinite loop, exited when RETURN is pressed */
{
if(i < 255)
{
char temp;
temp = getch (); /* Get the current character of the password */
if (GetAsyncKeyState (VK_RETURN)) /* If the user has pressed return */
{
input[i]='\0';
break;
}
input[i] = temp;
printf("*"); /* Print a star */
}
}
//printf("%s",input);
if(strcmp(input,"kamal")==0)
{
printf("ACCEPTED");
}
else
printf("not");
_getch();
return EXIT_SUCCESS; /* Program was executed successfully */
}
答案 4 :(得分:0)
如您所示,如果用户提供超过255个字符,则会编程崩溃。
所以,你应该检查已经提供的字符数量,如果达到最大值(你的缓冲区),你应该停止抓取更多的密钥(因为密码已经错了,这并不重要...... ):
#define BUFFER_MAX 255
// +1 so we can always add the 0-terminator
char input[BUFFER_MAX + 1];
do {
char temp;
temp = getch (); /* Get the current character of the password */
// Check if char does fit in the buffer
if(i < BUFFER_MAX) {
// add to buffer
input[i] = temp;
i++;
}
printf("*"); /* Print a star */
// Check if the user pressed return
} while(GetAsyncKeyState (VK_RETURN) == false);
input[i]='\0';
注意:我也重新安排了你的循环,因为它是'丑陋的'(在这种情况下是不好的做法和不必要的),使用无限循环并打破它们......