2016-12-01 4 views
-1

私はedxでCS50コースを取っていますが、私はVigenere Cipherを使ってメッセージを暗号化するコードをCで書いています。そして私はしました。しかし、問題はバッファオーバーフローを続けていることです。C - strcpy()とstrncpy()のバッファオーバーフロー

"Meet"のような短い文字列を使用しても大丈夫です。しかし、私が長い弦を使用すると、「11時に私の公園で会いましょう」のように、バッファオーバーフローが発生します。

私は暗号化されたメッセージ(encMsg)の変数に別の変数にargv[1]に渡されたキー(のはkを言わせて)と、元のメッセージ(msg)の両方をコピーするstrcpy()を使用する場合、それは私がkていたものを消去。 strcpy()をもう一度argv[1]の値をもう一度kにコピーすると、encMsgに両方の文字列を連結してバッファオーバーフローが発生します。

strccpy()を使用すると、消去されたkの内容は取得されませんが、両方の文字列がオーバーフローして連結され、encMsgにオーバーフローして連結されます。

これはすべて、GetSting()(cs50.hから)を使用すると発生します。

fgets()を使用すると、msgの最後に '\ n'が表示され、 '\ 0'を配置するためにifを追加する必要があります。誰もが私にこのことがなぜ起こるのか説明できるかどうかを知りたかったのです。コードの

#include <stdio.h> 
#include <stdlib.h> 
#include <cs50.h> 
#include <string.h> 


int main(int argc, char *argv[]) 
{ 
    if (argc != 2) //Checks if number of command-line arguments is valid 
    { 
     printf ("usage: ./caesar + key \n"); 
     return 1;  
    } 

    char k[strlen(argv[1])]; 
    //strcpy(k, argv[1]);   //Saves argument into a string 
    strncpy(k, argv[1], strlen(argv[1])); 

    for (int x = 0; x < strlen(k); x++) 
    { 
     if (k[x] < 65 || (k[x] > 90 && k[x] < 97) || k[x] > 122) //Checks if there is any non-alphabetical character in key 
     { 
      printf ("key must contain only alphabetical characters \n"); 
      return 1;  
     } 
    } 

    //printf("Inform the message you want to encrypt: \n"); 
    string msg = GetString(); 
    //char msg[255]; 
    //fgets(msg, 255, stdin); 

    char encMsg[strlen(msg)]; 
    //strcpy(encMsg, msg); 
    strncpy(encMsg, msg, strlen(msg)); 

    //strcpy(k, argv[1]); 

    int y = 0; 
    for (int x = 0; x < strlen(msg); x++) 
    { 
     //if(msg[x] == '\n') msg[x] = '\0'; 
     if (msg[x] < 65 || (msg[x] > 90 && msg[x] < 97) || msg[x] > 122) encMsg[x] = msg[x]; 
     else if ((msg[x] + (k[y] - 97) > 90 && msg[x] + (k[y] - 97) < 97) || msg[x] + (k[y] - 97) > 122) 
     { 
      encMsg[x] = msg[x] + (k[y] - 97) - 26; 
      y++; 
     } 
     else 
     { 
      encMsg[x] = msg[x] + (k[y] - 97); 
      y++; 
     } 
     if (y >= strlen(k)) y = 0; 
    } 

    printf("key  = %s\n", k); 
    printf("msg  = %s\n", msg); 
    printf("encMsg = %s\n", encMsg); 


    return 0; 
} 
+0

'IF(K [X] <65 ||(K [X]> 90 && K [X] <97)|| K [X]> 122)であってもよいです'isalpha()'、 'isupper()'、 'islower()'のような標準的なCの関数がある理由です。 –

+0

ああああ、ありがとう。それは本当に良い返答でした。しかし、次回は、自分で問題を解決してください。 –

+0

@AndrewHenleありがとう、pal。私はCについてはかなり新しく、そのことについては知らなかった。 –

答えて

4

このスタイル:

char k[strlen(argv[1])]; 

が終了'\0 '文字のためにスペースを残さない

は、ここに私のコードです。それは

char k[strlen(argv[1]) + 1 ]; 

やコメントで指摘のようにする必要があり、そのよう

strncpy(k, argv[1], strlen(argv[1])); 

などのコードは、適切に対象の文字列を終了しません。 the standard for strncpy()パー:

配列はs2によって指されている場合は、NUL文字がすべてでnバイトがあるまで は、s1で指される配列内のコピーに追加されなければならない、n バイトより短い文字列です。書きました。ターゲット文字列n以上短いので

、ソース文字列にのみ非NULバイトは、それらのnあるとしてコピーされます。

適切なコードは '

strncpy(k, argv[1], 1 + strlen(argv[1])); 
+1

それ以外の場合は、終了NULのための 'strlen(argv [1])'スペースがありますが、 'strncpy(k、argv [1]、strlen(argv [1]));' __by定義__はNULバイトargv [1] 'の最初の' strlen(argv [1]) 'バイトには含まれていないからです。 –

+0

@MichaelFoukarakisあまりにも。私はそれを追加します。 –