2012-05-10 67 views
3

我目前正在研究基於C語言的日誌解析器(製作基於原始bash的日誌解析器的C版本),我想知道應該如何防止緩衝區溢出,如果輸入有誤,很可能只是在內存不足時自動停止程序的一種方式,我也提供了下面的代碼,謝謝!如何實現某種機制來防止緩衝區溢出

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#define _GNU_SOURCE 
void main(int argc, char *argv[], char *envp[]) 
{ 
    FILE *fd; 
    char *name; 
    name = getenv("MCEXEC_PLAYERNAME"); 
    char *filename; 
    filename = malloc(sizeof "/home/minecraft/freedonia/playerdata/deathlog-.txt" - 1 + strlen(name) + 1); 
    if (!filename) exit(EXIT_FAILURE); 
    sprintf(filename,"/home/minecraft/freedonia/playerdata/deathlog-%s.txt",name); 
    char buff[1024]; 
    if ((fd = fopen(filename, "r")) != NULL) 
    { 
    fseek(fd, 0, SEEK_SET); 

    while(!feof(fd)) 
    { 
     memset(buff, 0x00, 1024); 
     fscanf(fd, "%[^\n]\n", buff); 
    } 
    printf("%s\n", buff); 
    } 
    else 
    printf("fail"); 
} 

下面這段代碼是實現fgets和scanf的一種嘗試,但是當我運行它,它只是坐在那裏不顯示任何輸出

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#define _GNU_SOURCE 
void main(int argc, char *argv[], char *envp[]) 
{ 
    FILE *fd; 
    char *name; 
    name = getenv("MCEXEC_PLAYERNAME"); 
    char *filename; 
    filename = malloc(sizeof "/home/minecraft/freedonia/playerdata/deathlog-.txt" - 1 +  strlen(name) + 1); 
    if (!filename) exit(EXIT_FAILURE); 
    sprintf(filename,"/home/minecraft/freedonia/playerdata/deathlog-%s.txt",name); 
    char *buff; 
    buff = malloc(1024); 
    char *finbuff; 
    finbuff = malloc(1024); 
    if ((fd = fopen(filename, "r")) != NULL) 
    { 
    fseek(fd, 0, SEEK_SET); 

    while(!feof(fd)) 
    { 
     memset(buff, 0x00, 1024); 
     memset(finbuff, 0x00, 1024); 
    // fscanf(fd, "%[^\n]\n", buff); 
     fgets(buff, 1024, fd); 
     scanf(buff, "%[^\n]\n", finbuff); 
    } 
    printf("%s\n", finbuff); 
    } 
    else 
    printf("fail"); 
} 
+1

程序中還有另一個緩衝區溢出。如果環境變量'MCEXEC_PLAYERNAME'足夠長,'filename'的計算緩衝區大小將環繞,並且分配的方式太少。 –

+0

IIRC你需要''#define _GNU_SOURCE' * * *''include'標題之前,因爲他們檢查是否定義了_GNU_SOURCE。 – fuz

回答

5

而不是使用fscanf,你應該使用組合fgetssscanf ... fgets()的優點是您可以指定讀取的最大字節數,從而防止緩衝區溢出。其次,用snprintf代替sprintf

防止緩衝區溢出的基本方法是避免寫入緩衝區而沒有指定最大寫入字節數的函數。

+0

好吧,用這個特定的例子,我將如何實現你用fgets和scanf描述的內容?有點新的C,所以沒有一切順利完成 – lacrosse1991

+0

+1同意這個問題。 – DevNull

+1

@ lacrosse1991我所描述的基本上是將'fscanf'分成兩個獨立的步驟。使用'fgets'來讀取最多N個字節或最多一個分隔符(例如行尾字符)。這可以防止緩衝區溢出。然後使用'scanf'(與'fscanf'相同,只能從緩衝區而不是文件)解析'fgets'讀取的緩衝區數據。 – Jason

1

我同意@Jason。

您可以使用fgets()將一行文本轉換爲一個字符數組,它將以null結尾(即:一個字符串)。然後,您可以使用sscanf()來分析每行,假定每行文本都有嚴格的格式。

以下文章也可能有幫助。

fgets and sscanf