2011-02-27 70 views
1
void gctinp (char *inp, int siz) 
{ 

    puts ("Input value: "); 
    fgets (inp, siz, stdin); 
    printf ("buffer3 getinp read %s", inp); 
} 

從我讀過的內容來看,fgets應該用於限制輸入大小。所以這段代碼不應該是脆弱的嗎?這是脆弱的堆棧溢出?

它被稱爲像這樣:

int main (int argc, char *argv[]) 

{ 

char buf[16]; 

getinp (buf, sizeof (buf)); 

display (buf); 

printf ("buffer3 done\n"); 

} 

感謝您的時間。

+5

我認爲你有「堆棧溢出」和「緩衝區溢出「困惑。堆棧溢出問題的最常見原因是一個遞歸函數,它會自動調用多次而不返回。 – aschepler 2011-02-27 01:14:24

+0

是的,aschepler說的是正確的,但是另外,堆棧上可能會發生緩衝區溢出。如果你使用過「獲取」,它將容易受到堆棧上的緩衝區溢出(而不是堆棧溢出) – Hut8 2011-02-27 01:22:46

回答

4

,如果你不是可以安全地儲存,因爲fgets限制輸入輸入的字符的時候打緩衝區溢出問題。它還添加了一個空終止符(當然,假設緩衝區大小大於0)。

但是,你有被留在輸入的信息問題,緩衝嘗試讀的東西,下一次 - 這是一些用戶會覺得很討厭,進入像hello again並讓它作爲兩個獨立的處理輸入如hello again。並且fgets沒有指示它在行結束之前停止檢索輸入,因此,就您的代碼所知,一切都很好。

你需要尋找出重要的事情(重新緩衝輸入溢出)是在最低限度,scanf採用無界%s格式字符串和gets,它沒有限制大小參數,這兩者都不是在你的代碼。

如果你正在尋找一個大小限制,促使和緩衝器清空,看看這個代碼,它提供了所有這些功能更強大的輸入解決方案:

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

#define OK  0 
#define NO_INPUT 1 
#define TOO_LONG 2 
static int getLine (char *prmpt, char *buff, size_t sz) { 
    int ch, extra; 

    // Get line with buffer overrun protection. 
    if (prmpt != NULL) { 
     printf ("%s", prmpt); 
     fflush (stdout); 
    } 
    if (fgets (buff, sz, stdin) == NULL) 
     return NO_INPUT; 

    // If it was too long, there'll be no newline. In that case, we flush 
    // to end of line so that excess doesn't affect the next call. 
    if (buff[strlen(buff)-1] != '\n') { 
     extra = 0; 
     while (((ch = getchar()) != '\n') && (ch != EOF)) 
      extra = 1; 
     return (extra == 1) ? TOO_LONG : OK; 
    } 

    // Otherwise remove newline and give string back to caller. 
    buff[strlen(buff)-1] = '\0'; 
    return OK; 
} 

 

// Test program for getLine(). 

int main (void) { 
    int rc; 
    char buff[10]; 

    rc = getLine ("Enter string> ", buff, sizeof(buff)); 
    if (rc == NO_INPUT) { 
     // Extra NL since my system doesn't output that on EOF. 
     printf ("\nNo input\n"); 
     return 1; 
    } 

    if (rc == TOO_LONG) { 
     printf ("Input too long [%s]\n", buff); 
     rc = getLine ("Hit ENTER to check remains> ", buff, sizeof(buff)); 
     printf ("Excess [%s]\n", buff); 
     return 1; 
    } 

    printf ("OK [%s]\n", buff); 

    return 0; 
} 

並且,做一些基本的測試:

pax> ./prog 
Enter string> [CTRL-D] 
No input 

pax> ./prog 
Enter string> x 
OK [x] 

pax> ./prog 
Enter string> hello 
OK [hello] 

pax> ./prog 
Enter string> hello from earth 
Input too long [hello fro] 
Hit ENTER to check remains> [ENTER] 
Excess [] 

pax> ./prog 
Enter string> i am pax 
OK [i am pax] 
+2

錯誤..沒有。只要提供的「size」至少爲1,'fgets()'總是終止結果。 – caf 2011-02-27 01:25:08

+0

對不起,應該已經提出了「尺寸必須足夠大來終結器,否則它不會被存儲」第一段 - 修正。 – paxdiablo 2011-02-27 01:48:35

0

fgets最多隻能讀取一個小於指定的字節數,並且將確保讀取字符串以空字符結尾。所以只要你傳遞正確的大小,它應該沒問題(儘管字符串可能不會以換行符結束)。