2011-08-24 49 views
2

用這個代碼片段有可能是錯誤的(在軟件安全性方面),我似乎無法弄清楚......函數在顯示字符串參數後終止程序。c代碼片段中的安全缺陷?

void get_user(char* user) 
{ 
    char buf[1024]; 
    if (strlen(user) > sizeof(buf)) 
    die("error: user string too long\n"); 
    strcpy(buf, user); 
    … 
} 

-thx!

+2

這功課嗎? – Skizz

回答

4

它不計算NUL(\0)終止的字符串。

if (strlen(user) >= sizeof(buf)) 

這是不安全的,如果user有1024個字符(會寫0某處在堆棧上)。

+2

儘管'strlen(user)+ 1'的病態實現可能會溢出,原則上最好使用'> ='運算符而不是加法來避免數值溢出問題。 –

+0

@R ..這很有趣;你能詳細瞭解溢出問題嗎? – cnicutar

+2

'strlen(user)+ 1'不能溢出,因爲字符串對象的實際大小包含空終止符。但是,假設你想知道'size1'和'size2'的對象是否可以放在一個緩衝區中。 'if(size1 + size2> available)'不是一個正確的測試,因爲添加大小可能會換行(如果它們是未簽名的)或溢出並給予UB(如果它們是已簽名的)。因此,至少在我看來,這種形式的條件是*代碼氣味* - 它們表明潛在的安全缺陷,並需要進一步閱讀以確定代碼是否實際上是安全的。 –

1

答案是使用字符strcpy副本的數量與字符strlen返回的數量進行比較。

提示:strcpystrlen

4

如果strlen(user)等於1024,strcpy將在buf的末尾寫入一個字節。

3

的問題是在這裏:

if (strlen(user) > sizeof(buf)) 

這並不佔空終止時strlen(user) == sizeof(buf)。該檢查應

if (strlen(user) > sizeof(buf) - 1) 

使strcpy()可以隨時複製空終止。

2

有一個可能導致緩衝區溢出的錯誤的錯誤。請記住,strlen會爲您提供字符串中的字符數,,不包括空終止符。檢查應該是:

if (strlen(user) + 1 > sizeof(buf)) 
1

從strlen的手冊頁:

所述的strlen()函數計算的字符串s的長度,不 包括終止 '\ 0' 字符。

並從strcpy的手冊頁:

的的strcpy()函數將字符串由src指出,包括 終止空字節( '\ 0'),到緩衝區指向DEST。

尺寸比較存在不匹配。代碼檢查字符串長度是否小於緩衝區,但複製字符串長度爲+1個字符。如果字符串長度(小於終止'\ 0')爲1024,則會發生溢出。