-2
#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 */
}

これは私のコードです。バッファ オーバーフローを防ぐにはどうすればよいですか。パスワードをさらに入力すると、プログラムがクラッシュします。とにかく私はこれの問題を克服することができますか?

4

5 に答える 5

2

スタックに格納されたローカル変数 char input[255]。C には配列の境界チェックがありません。問題は、255 文字を超える文字を追加すると、スタックに格納されている他の変数の値が変更される可能性があることです。これにより、クラッシュが発生する可能性があります。

1 つの解決策は、文字を読み取り、範囲 (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()) ことです。

于 2013-02-25T13:04:09.690 に答える
1

常に境界を確認してください。i の値とバッファの長さを常にチェックしてください。

于 2013-02-25T12:46:09.027 に答える
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();
}

... オーバーフローするバッファーがない場合、何を心配していますか?

于 2013-02-25T13:16:31.623 に答える
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 */
}
于 2013-02-25T12:46:20.113 に答える
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';

注:無限ループを使用してそれらから抜け出すのは「醜い」(この場合は悪い習慣であり不要である)ため、ループを再配置しました...

于 2013-02-25T13:08:58.047 に答える