2010-07-05 36 views
0

我最近安裝了「klocwork」,並試圖擺脫現有代碼上的錯誤。 顯示的錯誤似乎很簡單。在char * _p_終止時不爲空。 我已經手動添加了空終止符(儘管沒有必要),但它並不請求Klocwork。有任何想法嗎?非空終止字符串 - KlocWork錯誤,無可理解的原因

確切信息是: -

Incorrectly terminated string 'p' causes a buffer overflow in p.

char *ptr; 
int writtenchars = 0 ; 
va_list args; 
char* destStr; 

if (argc != 2) { 
    printf(" wrong parameters number - %d instead of %d\n", argc, 2); 
    char str[25]="wrong parameters number "; 
    char *_p_; /********************************************************/ 

    va_start(args, str); 
    destStr = (char*) malloc(SNMP_BUF_LEN); 
    _p_= destStr; 
    if (destStr == NULL) { 
    printf("WARNING: Failed to alloc memory in in function \"snmp_rebuildstringinbuf!!!\" \n"); 
    destStr="kukuRiko"; 
    } 
    else { 
    writtenchars = (int) vsnprintf(destStr, 4095, str, args); 
    if (writtenchars>SNMP_BUF_LEN) { 
     printf("WARNING: Too long string rebuilded in function \"snmp_rebuildstringinbuf!!!\" %d chars\n",writtenchars); 
    } 
    destStr[writtenchars] = '\0' ; //Moshe - making sure the last value of the string is null terminated in order to prevent future buffer overflows. 
    } 
    va_end(args); 

    /******************************************************************************/ 
    //The KlocWork error relates to this line // 

    logCWriteLog_msg(moduleId, level, __FILE__, __LINE__, _p_, ltrue); 
    free (_p_); 

============================== ============================= 嗨,大家好, 感謝您的回答,但似乎比這更晦澀難懂。我已經將代碼細化爲這種簡單的情況: - 將代碼全部寫入一個函數時沒有錯誤,而當分配部分包含在一個函數中(以及作爲參數傳遞的文本)時,Klocwork錯誤返回。 參見此代碼: - 版本沒有一個錯誤: -

char *_p_; /*+++++++++++++++++++*/ 

int writtenchars = 0 ; 
va_list args; 
char* destStr; 
char* str = "hello World"; 
va_start(args, str); 
destStr = (char*)malloc(SNMP_BUF_LEN); 
if (destStr == NULL) { 
    printf("WARNING: Failed to alloc memory in function \n"); 
} 
else { 
    writtenchars = (int) vsnprintf(destStr, (SNMP_BUF_LEN) - 1, str, args); 
} 

/*+++++++++++++++++++*/ 
_p_ = destStr ; 
if (_p_ != NULL) { 
    logCWriteLog_msg(moduleId, level, __FILE__, __LINE__, _p_, ltrue); 
} 
free (_p_); 
/***********************************************************/ 

取代碼之間/ * ++++ * /和在函數包裹它時返回,而錯誤Klocwork的上述。

因此,

char *writingToSomeBuffer (char * str) { 
    int writtenchars = 0 ; 
    va_list args; 
    char* destStr; 
    va_start(args, str); 
    destStr = (char*)malloc(SNMP_BUF_LEN); 
    if (destStr == NULL) { 
    printf("WARNING: Failed to alloc memory in function \n"); 
    } 
    else { 
    writtenchars = (int) vsnprintf(destStr, (SNMP_BUF_LEN) - 1, str, args); 
    } 
    return destStr; 
} 

int main() { 
    char *_p_; 
    _p_ = writingToSomeBuffer("hello world"); 
    if (_p_ != NULL) { 
    logCWriteLog_msg(moduleId, level, __FILE__, __LINE__, _p_, ltrue); 
    } 
    free (_p_); 
    return 0 ; 
} 

什麼想法?

回答

0

拋開Klocwork的錯誤,我認爲這段代碼是錯誤的。你爲什麼將vsnprintf限制爲4096,而緩衝區大小是SNMP_BUF_LEN?這兩者如何相互關聯?如果SNMP_BUF_LEN < 4096,那麼你可能剛剛溢出你的緩衝區。爲什麼不通過SNMP_BUF_LEN作爲vsnprintf中的限制參數?

另外,懷疑寫入destStr[writtenchars]。根據vsnprintf的變體(它們確實有所不同),書寫者可能會寫想要的字符數,這會再次導致您寫入超過緩衝區的末尾。

大家都說,Klocwork並不完美。我們有非常明確地試圖安全的宏,而Kloc​​work錯誤地檢測到它們可能會超出字符串。我認爲這也是一個snprintf案例。

整體而言是一個好產品,但確實有一些漏洞,您無法修復所有投訴。

+0

我同意你的診斷,即4096和SNMP_BUF_LEN不是明顯相關的,並且通過在任何地方使用相同的名稱(SNMP_BUF_LEN)都會改進代碼。但Klockwork也在診斷一個恰當的錯誤 - 雖然不像人們想象的那麼清楚。 – 2010-07-05 18:28:00

3

Klocwork的正確診斷,你可以用一個空指針,如果內存分配失敗時寫的問題:

_p_= destStr; 
if (destStr == NULL) 
{ 
    printf("WARNING: Failed to alloc memory in in function ...\n"); 
    destStr = "kukuRiko"; 

在這點上,(可怕的名字命名)「_p_」變量仍然是空的,但你繼續並在下面的打印操作中使用它。

另請注意,在此之後添加'_p_'的'微不足道'修復會打破您的內存管理;你以後做'free(_p_);',如果'_p_'指向常量字符串,將導致可怕的問題。

您還有'函數'中的內存。而'錯誤的參數數'的含義與'錯誤的參數數量'大致相同,但後者更習慣於英語。我不確信任何驚歎號對錯誤信息都有幫助;有一個強有力的論點是,即使他們中的一個被認爲是可取的,他們也應該超出函數名稱的雙引號。


隨着問題的修訂版,不知是Klocwork的診斷其vsnprintf()微軟說的話,那它不保證空終止(這是從什麼C99和POSIX說不同)。