2016-12-01 99 views
-1

我正在EDX CS50课程,我应该写一个C代码,使用Vigenere密码加密消息。我做到了。但问题是我不断收到缓冲区溢出。C - 缓冲区溢出与strcpy()和strncpy()

如果我使用短字符串,如“Meet”,它可以正常工作。但是如果我使用更长的字符串,比如“上午11点在公园与我会面”,我会遇到缓冲区溢出。

如果我使用strcpy()同时复制在argv[1]传递到另一个变量键(假设k)和原始消息(msg)的加密消息(encMsg)的变量,然后将它删除了我必须在k 。 如果我再次使用strcpy()argv[1]的值复制到k再一次,我在encMsg连接两个字符串时发生缓冲区溢出。

如果我使用strccpy(),它将不会获得k的内容擦除,但它会溢出并连接encMsg上的两个字符串。

这一切都发生在我使用GetSting()(来自cs50.h);

如果我使用fgets(),那么我会在msg结尾处得到'\ n',然后必须添加一个if以在'\ n'处放置'\ 0',这解决了我的问题,但我想知道是否有人能解释我为什么会发生这种情况。

这里是我的代码:

#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

'如果(K [X] <65 ||(K [X]> 90 && K [X] <97)|| K [X]> 122)'是有标准C函数的原因,如'isalpha()','isupper()'和'islower()'。 –

+0

哦,非常感谢@Olaf。这是一个非常好的答复。但下一次,为自己节省麻烦。 –

+0

@AndrewHenle谢谢,朋友。我对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是一个字符串短于n 字节,NUL字符应阵列 通过s1指出,在被追加到拷贝,直到n字节都是书面。

由于目标串n短,只有源串中的非NUL字节被作为有他们的n复制。

正确代码可能是

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

否则,''strlen(argv [1])'空间用于终止NUL,但'strncpy(k,argv [1],strlen(argv [1]));'__by definition__不复制NUL字节因为它不包含在'argv [1]'的第一个'strlen(argv [1])'字节中。 –

+0

@MichaelFoukarakis那也是。我会补充一点。 –