1. 程式人生 > >程式碼審計--19--FindBugs詳細

程式碼審計--19--FindBugs詳細

3.1 軟體介紹

Findbugs 是一個靜態分析工具,通過檢查類或者 JAR 檔案,將位元組碼與一組缺陷模式進行對比以發現可能的問題。Findbugs不注重style及format,注重檢測真正的bug及潛在的效能問題,尤其注意了儘可能抑制誤檢測(falsepositives)的發生。工具自帶了60餘種Bad practice,80餘種Correntness,1種Internationalization,12種Malicious code vulnerability,27種Multithreaded correntness,23種Performance,43種Dodgy。利用這個工具,就可以在不實際執行程式的情況對軟體進行分析。它可以幫助改進程式碼的質量。

Findbugs可以通過Ant工具,通過Ant提供的Swing操作介面和作為Eclipse的一個外掛來使用。

3.2 使用Findbugs

1、開始Findbugs Ant操作

Findbugs的Swing工具使用操作如下:

Findbugs 主介面:

在這裡插入圖片描述

在分析專案之前,通過新建一個專案來分析,選擇檔案->新建

然後新增要分析的類包和目錄(可以選擇編譯好的類所在的資料夾,也可以選擇生成的jar包),再新增輔助類所在的資料夾和原始檔所在的資料夾(java檔案所在的資料夾)。再點選完成就可以建立一個要分析的專案。

新建專案 在這裡插入圖片描述

建立專案後,會自動開始解析專案。解析後的結果介面如下所示:

在這裡插入圖片描述

其中左邊是缺陷的樹結構列表,點選其中一個Bug,可以在右邊的介面中,顯示Bugs的原始檔以及所在的位置。

2、開始Findbugs Eclipse外掛使用

Eclipse的Findbugs外掛,可以將Findbugs整合到Eclipse中使用。

安裝好Findbugs後啟動eclipse。在eclipse中選擇某個工程的屬性。如下圖所示:

在這裡插入圖片描述

點選“屬性”彈出屬性對話方塊,選擇對話方塊左邊的樹上的“Findbugs”節點:

在這裡插入圖片描述

下面對Findbugs各項屬性的配置進行一下說明:

1、Run Findbugs automnaticaly:編譯工程和檔案的時候自動執行 2、Minimum priority to report:根據bug的優先權級別報告bug。 3、Enable bug categories: bug種類。 ----Correctness:正確性。 ----Performance:效能。 ----Internationalization:國際化。 ----Mutithreaded correctness:多執行緒的正確性。 ----Style:樣式。 ----Malicious code vulnerability:惡意程式碼。 4、Select bug patterns to check for: bug的校驗模式 ----Bug的校驗模式的設定是確定哪一類問題應該作為bug報告給使用者。

當根據部門規範選擇要校驗的模式後。點選”ok” 按鈕就可以對工程進行校驗。 如下圖:在工程的選單中選擇findbugs的選單項“Find bugs”。

在這裡插入圖片描述

執行後可以在problems檢視中看到工程的所有可能的“偽問題”

在這裡插入圖片描述

Findbugs的問題描述一般都是:問題型別+‘:’+問題描述構成的。如果想看到詳細的問題描述,可以選擇問題然後點選右鍵選單,在“bug Details”檢視中看到相應的說明。如下圖所示:

在這裡插入圖片描述 在這裡插入圖片描述

Bug選擇的其他方式:

在這裡插入圖片描述

另外,如果想看到僅僅是Findbugs檢查出來的問題的話可以對問題列表進行過濾。如下圖所示的方法可以實現問題過濾:

在這裡插入圖片描述

在這裡插入圖片描述

如果想要檢視某個Bug詳細的資訊,則可以選擇Windows選單->Open Perspective,然後選擇FindBugs就可以開啟FindBugs的Properties面板,在這個面板裡面可以看到最詳盡的Bugs資訊。

3.3 Bug分類表

Bad practice不好的習慣,例如:

HE:類定義了equals(),卻沒有hashCode();或類定義了equals(),卻使用Object. hashCode();或類定義了hashCode(),卻沒有equals();或類定義了hashCode(),卻使用Object.equals();類繼承了equals(),卻使用Object.hashCode()。

SQL:Statement的execute方法呼叫了非常量的字串;或Prepared Statement是由一個非常量的字串產生。

DE:方法終止或不處理異常,一般情況下,異常應該被處理或報告,或被方法丟擲。

Correctness程式碼正確性,例如:

NP:空指標被引用;在方法的異常路徑裡,空指標被引用;方法沒有檢查引數是否null;null值產生並被引用;null值產生並在方法的異常路徑被引用;傳給方法一個宣告為@NonNull的null引數;方法的返回值宣告為@NonNull實際是null。

Nm:類定義了hashcode()方法,但實際上並未覆蓋父類Object的hashCode();類定義了tostring()方法,但實際上並未覆蓋父類Object的toString();很明顯的方法和構造器混淆;方法名容易混淆。

SQL:方法嘗試訪問一個Prepared Statement的0索引;方法嘗試訪問一個ResultSet的0索引。

UwF:所有的write都把屬性置成null,這樣所有的讀取都是null,這樣這個屬性是否有必要存在;或屬性從沒有被write。

Internationalization國際化問題,例如:

當對字串使用upper或lowercase方法,如果是國際的字串,可能會不恰當的轉換。

Malicious code vulnerability惡意程式碼,例如:

FI:一個類的finalize()應該是protected,而不是public的。 MS:屬性是可變的陣列;屬性是可變的Hashtable;屬性應該是package protected的。

Multithreaded correctness多執行緒問題

ESync:空的同步塊,很難被正確使用。 MWN:錯誤使用notify(),可能導致IllegalMonitorStateException異常;或錯誤的使用wait()。 No:使用notify()而不是notifyAll(),只是喚醒一個執行緒而不是所有等待的執行緒。 SC:構造器呼叫了Thread.start(),當該類被繼承可能會導致錯誤。

Performance效能問題,例如:

DM:方法呼叫了低效Boolean的構造器,而應該用Boolean.valueOf(…);用類似Integer.toString(1)代替new Integer(1).toString();方法呼叫了低效的float的構造器,應該用靜態的valueOf方法。 SIC:如果一個內部類想在更廣泛的地方被引用,它應該宣告為static。 SS:如果一個例項屬性不被讀取,考慮宣告為static。 UrF:如果一個屬性從沒有被read,考慮從類中去掉。 UuF:如果一個屬性從沒有被使用,考慮從類中去掉。

Dodgy,小問題,例如

BC:對抽象集合如List、Set的造型;對具體集合如ArrayList、HashSet的造型;未檢查或無法保證的造型; CI:類宣告為final但聲明瞭protected的屬性。 DLS:對一個本地變數賦值,但卻沒有讀取該本地變數;本地變數賦值成null,卻沒有讀取該本地變數。 ICAST:整型數字相乘結果轉化為長整型數字,應該將整型先轉化為長整型數字再相乘。 INT:沒必要的整型數字比較,如X <= Integer.MAX_VALUE。 NP:對readline()的直接引用,而沒有判斷是否null;對方法呼叫的直接引用,而方法可能返回null。 REC:直接捕獲Exception,而實際上可能時RuntimeException。 ST:從例項方法裡直接修改類變數,即static屬性。