簡體   English   中英

C-strcpy()和strncpy()的緩沖區溢出

[英]C - Buffer overflow with strcpy() and strncpy()

我正在edx上參加CS50課程,應該使用C語言編寫代碼,該代碼使用Vigenere Cipher加密消息。 而我做到了。 但是問題是我一直在緩沖區溢出。

如果我使用短字符串,例如“ Meet”,它可以正常工作。 但是,如果我使用更長的字符串,例如“上午11點在公園見我”,則會出現緩沖區溢出。

如果我使用strcpy()將傳入argv[1]的密鑰復制到另一個變量(比如說k ),並且將原始消息( msgencMsg到加密消息的變量( 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;
}

這種代碼風格:

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

不留空格來終止'\\0 '字符。 它應該是

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

正如注釋中指出的那樣,

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

將無法正確終止目標字符串。 按照strncpy()的標准

如果s2指向的數組是短於n個字節的字符串,則NUL字符應附加到s1指向的數組的副本中,直到總共寫入n個字節。

由於目標串小於短n ,只有非NUL作為有源串中的字節被復制n它們。

正確的代碼可能是

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM