cppcheck使用
一.splint介紹
splint是一個動態檢查C語言程序安全弱點和編寫錯誤的程序.splint會進行
多種常規檢查,包括未使用的變量,類型不一致,使用未定義變量,無法執行的
代碼,忽略返回值,執行路徑未返回,無限循環等錯誤.
二.splint的安裝
1.rpm安裝
GTES 10.5和11版本已經整合有splint軟件包,直接可以使用.
2.源代碼安裝
下載地址: http://www.splint.org/downloads/splint-3.1.2.src.tgz源碼包安裝: # tar zxvf splint-3.1.2.src.tgz # cd splint-3.1.2 # ./configure # make install
三.splint的使用
1.空引用錯誤
在引用沒有指向任何內存地址的指針時,會導致這種錯誤.也就是使用了一個沒有賦值的指針.
splint支持一種特別的注釋.這種注釋寫在C程序代碼中,用于對程序進行特殊說明.
如下面這段程序.使用了進行了說明,表示說明*s的值可能會是NULL.
//null.c char firstChar1 ( char *s) { return *s; } char firstChar2 ( char *s) { if (s ==NULL) return ''; return *s; } //END
使用splint掃描這個程序時,會輸出:
# splint null.c Splint 3.1.1 --- 28 Apr 2005 null.c: (in function firstChar1) null.c:3:11: Dereference of possibly null pointer s: *s null.c:1:35: Storage s may become null Finished checking --- 1 code warning found 由于firstChar1和firstChar2都使用了null說明,表示指針s可能是個NULL值. 所以,splint會對s值的使用情況進行檢查.因為firstChar2函數中,對s的值進行 了NULL的判斷.所以,沒有對firstChar2函數的指針s輸出警告信息.
2.未定義的變量錯誤
C語言中,要求先定義變量,而后才可使用.所以,當使用一個沒有定義的變量時,編譯就會出錯.
如下例,使用說明的變量,表示必須進行定義.使用說明的變量,表示在 執行過此函數后,這個變量就進行了定義.
// usedef.c extern void setVal ( int *x); extern int getVal ( int *x); extern int mysteryVal (int *x); int dumbfunc ( int *x, int i) { if (i > 3) return *x; else if (i > 1) return getVal (x); else if (i == 0) return mysteryVal (x); else { setVal (x); return *x; } } // END
使用splint檢查usedef.c
$ splint usedef.c Splint 3.1.1 --- 28 Apr 2005 usedef.c: (in function dumbfunc) usedef.c:7:19: Value *x used before definition An rvalue is used that may not be initialized to a value on some execution path. (Use -usedef to inhibit warning) usedef.c:9:18: Passed storage x not completely defined (*x is undefined): getVal (x) Storage derivable from a parameter, return value or global is not defined. Use to denote passed or returned storage which need not be defined. (Use -compdef to inhibit warning) usedef.c:11:22: Passed storage x not completely defined (*x is undefined): mysteryVal (x) Finished checking --- 3 code warnings //錯誤原因: 由于程序中沒有對x進行定義,所以報未定義錯誤.但setVal()使用了說明,所以 在setVal(x);和return x;中,沒有報未定義錯誤.
3.類型錯誤
C語言中的數據類型較多,各個之間有些細微差別.splint也可以對變量類型進行檢查.
示例1:
//bool.c int f (int i, char *s,bool b1, bool b2) { if (i = 3) return b1; if (!i || s) return i; if (s) return 7; if (b1 == b2) return 3; return 2; } //END
使用splint進行檢查:
$ splint bool.c Splint 3.1.1 --- 28 Apr 2005 bool.c: (in function f) bool.c:4:5: Test expression for if is assignment expression: i = 3 The condition test is an assignment expression. Probably, you mean to use == instead of =. If an assignment is intended, add an extra parentheses nesting (e.g., if ((a = b)) ...) to suppress this message. (Use -predassign to inhibit warning) // 錯誤原因: if語句中的條件表達式是一個賦值語句. bool.c:4:5: Test expression for if not boolean, type int: i = 3 Test expression type is not boolean or int. (Use -predboolint to inhibit warning) // 錯誤原因: if語句中的條件表達式的返回值,不是布爾型,而是整型. bool.c:4:8: Return value type bool does not match declared type int: b1 Types are incompatible. (Use -type to inhibit warning) // 錯誤原因: 返回值是布爾型,而不是整型. bool.c:5:6: Operand of ! is non-boolean (int): !i The operand of a boolean operator is not a boolean. Use +ptrnegate to allow ! to be used on pointers. (Use -boolops to inhibit warning) // 錯誤原因: "!"操作符的操作數不是布爾型,而是整型i. bool.c:5:11: Right operand of || is non-boolean (char *): !i || s // 錯誤原因: "||"操作符的右操作數不是布爾型,而是字符指針. bool.c:7:5: Use of == with boolean variables (risks inconsistency because of multiple true values): b1 == b2 Two bool values are compared directly using a C primitive. This may produce unexpected results since all non-zero values are considered true, so different true values may not be equal. The file bool.h (included in splint/lib) provides bool_equal for safe bool comparisons. (Use -boolcompare to inhibit warning) // 錯誤原因: 使用"=="對兩個布爾型進行比較.應該使用"&&". Finished checking --- 6 code warnings
示例2:
//malloc1.c #include <stdlib.h> #include <stdio.h> int main(void) { char *some_mem; int size1=1048576; some_mem=(char *)malloc(size1); printf("Malloed 1M Memory!
"); free(some_mem); exit(EXIT_SUCCESS); } //END
使用splint檢查malloc1.c
$ splint malloc1.c Splint 3.1.1 --- 28 Apr 2005 malloc1.c: (in function main) malloc1.c:9:25: Function malloc expects arg 1 to be size_t gets int: size1 To allow arbitrary integral types to match any integral type, use +matchanyintegral. Finished checking --- 1 code warning
修改變量size1的定義為:
size_t size1=1048576;
再使用splint進行檢查.
$ splint malloc1.c Splint 3.1.1 --- 28 Apr 2005 Finished checking --- no warnings
沒有檢查到錯誤.
4.內存檢查
緩沖區溢出錯誤是一種非常危險的C語言錯誤,大部分安全漏洞都與它有關.splint可以
對緩沖區的使用進行檢查.報告溢出或越界錯誤.
示例1:
//over.c int main() { int buf[10]; buf[10] = 3; retrun 0; } //END
使用splint進行檢查
$ splint over.c +bounds +showconstraintlocation Splint 3.1.1 --- 21 Apr 2006 Command Line: Setting +showconstraintlocation redundant with current value over.c: (in function main) over.c:6:3: Likely out-of-bounds store: buf[10] Unable to resolve constraint: requires 9 >= 10 needed to satisfy precondition: requires maxSet(buf @ over.c:6:3) >= 10 A memory write may write to an address beyond the allocated buffer. (Use -likely-boundswrite to inhibit warning) Finished checking --- 1 code warning
數組buf的大小是10字節.最大可使用的元素位置為buf[9],但程序中使用了buf[10].
所以報錯.
示例2:
// bound.c void updateEnv(char *str) { char *tmp; tmp = getenv("MYENV"); if(tmp != NULL) strcpy(str,tmp); } void updateEnvSafe(char *str, size_t strSize) { char *tmp; tmp = getenv("MYENV"); if(tmp != NULL) { strncpy(str, tmp, strSize -1); str[strSize - 1] = '/0'; } } //END
$ splint bound.c +bounds +showconstraintlocation Splint 3.1.1 --- 21 Apr 2006 Command Line: Setting +showconstraintlocation redundant with current value bound.c: (in function updateEnv) bound.c:6:19: Possible out-of-bounds store: strcpy(str, tmp) Unable to resolve constraint: requires maxSet(str @ bound.c:6:26) >= maxRead(getenv("MYENV") @ bound.c:5:9) needed to satisfy precondition: requires maxSet(str @ bound.c:6:26) >= maxRead(tmp @ bound.c:6:30) derived from strcpy precondition: requires maxSet(<parameter 1>) >= maxRead(<parameter 2>) A memory write may write to an address beyond the allocated buffer. (Use -boundswrite to inhibit warning) 錯誤原因: 由于使用strcpy函數時,沒有指定復制字符串的長度,所以可能導致緩沖區 溢出.后面的updateEnvSafe函數,使用了strncpy進行字符串復制,避免了這種情況.
總結
以上是生活随笔為你收集整理的cppcheck使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HTML转义字符大全
- 下一篇: ArcGIS学习记录—KMZ