PVS-Studio 7.34 版本在分析器中引入了一系列新的診斷規則:Java 的污點分析、C# 的 Unity 特定診斷規則、深入研究 OWASP 等等!本文將涵蓋所有這些。
在此版本中,C 團隊專注於通用分析診斷規則以及對各種軟體開發標準的支援。
但是請戴好帽子,這只是開始!團隊計畫涵蓋更多 MISRA 標準診斷規則,敬請關注更多新聞:)
現在,讓我們來看看 7.34 版本中的主要規則。
此診斷規則旨在偵測在沒有解釋訊息的情況下所建立的異常。
缺少訊息可能會阻礙錯誤偵測和修復的過程,以及整體程式碼的可讀性。
以下是讓 PVS-Studio 分析器產生警告的程式碼範例:
void SomeCheck(const char *val) { if (!val) throw std::runtime_error { "" }; .... } void Foo() { const char *val = ....; try { SomeCheck(val); // <= } catch(std::runtime_error &err) { std::cerr << err.what() << std::endl; } }
如果發生錯誤,SomeCheck 函數會拋出一個帶有空訊息的異常,該異常將在 Foo 函數中處理。在處理過程中,std::cerr 應該包含有關異常原因的信息,但事實並非如此。
透過這種方式編寫程式碼,開發人員向同事傳達了「調試愉快」的願望。這阻礙了理解到底是什麼導致了失敗。
此規則適用於標準例外。您可以使用自訂註釋機制對自訂異常發出警告。
查看文件以了解有關此診斷規則的更多詳細資訊。
此診斷規則僅適用於C語言。
它的目的是偵測使用 const 或 volatile 限定符的函數類型定義的情況。
根據 C23 標準(第 6.7.4.1 段第 10 點),使用這些類型會導致未定義的行為。
使 PVS-Studio 分析器產生警告的程式碼範例:
typedef int fun_t(void); typedef const fun_t const_qual_fun_t; // <= typedef const fun_t * ptr_to_const_qual_fun_t; // <= void foo() { const fun_t c_fun_t; // <= const fun_t * ptr_c_fun_t; // <= }
查看文件以了解有關此診斷規則的更多詳細資訊。
C 語言的另一個診斷規則,可以在重構和調試時提供幫助。
此規則使分析器能夠偵測整數類型到枚舉類型的隱式轉換。
帶有 PVS-Studio 警告的程式碼範例:
void SomeCheck(const char *val) { if (!val) throw std::runtime_error { "" }; .... } void Foo() { const char *val = ....; try { SomeCheck(val); // <= } catch(std::runtime_error &err) { std::cerr << err.what() << std::endl; } }
此程式碼使用條件運算子 (?:) 在兩個整數變數 posOne 和 posTwo 之間進行選擇,從而產生隱式強制轉換。
查看文件以了解有關此診斷規則的更多詳細資訊。
這是一個專注於安全性的新診斷規則,與 SAST 原則保持一致。
此規則是根據OWASP安全驗證標準設計的。
它的目的是檢測過時的加密函數的呼叫。它們的使用可能會導致嚴重的軟體安全問題。
帶有 PVS-Studio 警告的程式碼範例:
typedef int fun_t(void); typedef const fun_t const_qual_fun_t; // <= typedef const fun_t * ptr_to_const_qual_fun_t; // <= void foo() { const fun_t c_fun_t; // <= const fun_t * ptr_c_fun_t; // <= }
根據 Microsoft 文檔,CryptoImportKey 和 CryptoDestroyKey 函數已棄用。這些應該替換為下一代密碼學的安全對應項(BCryptoImportKey 和 BCryptoDestroyKey)。
查看文件以了解有關此診斷規則的更多詳細資訊。
但這只是熱身! C 和 C 團隊計劃涵蓋各種軟體開發標準的更多診斷規則。我們將特別關注 MISRA 標準。所以,等待訊息吧:)
在新的 PVS-Studio 7.34 版本中,C# 團隊專注於建立特定於 Unity 的診斷規則,但也沒有忘記通用分析規則。
讓我們從後者開始。
這個新的診斷規則旨在偵測非 A 或 B 模式的錯誤使用。此問題源自於開發者對操作優先順序的混淆。
帶有 PVS-Studio 警告的程式碼範例:
Orientation GetOrientation (bool b) { int posOne = 1; int posTwo = 2; return b ? posOne : posTwo; // V2022 }
在方法開始時,檢查輸入參數鍵是否為空字串或 null。
但是條件式的邏輯有錯誤。 not 運算子的優先權高於 or 運算子。因此,否定不適用於表達式的右側。另外,如果 key 設定為 null,則條件將為 true。
查看文件以了解有關此診斷規則的更多詳細資訊。
這是一系列新的 Unity 特定規則中的第一個診斷規則。
它的目的是偵測 UnityEngine.Object(或從它繼承的其他物件)與 System.WeakReference 的使用。
由於引擎本身隱式使用實例,弱引用的行為可能與預期不同。
帶有 PVS-Studio 警告的程式碼範例:
void SomeCheck(const char *val) { if (!val) throw std::runtime_error { "" }; .... } void Foo() { const char *val = ....; try { SomeCheck(val); // <= } catch(std::runtime_error &err) { std::cerr << err.what() << std::endl; } }
在範例中,我們可以看到對 GameObject 類別的物件的弱引用。即使作者沒有創建對此物件的強烈引用,垃圾收集器也無法清理它。
查看文件以了解有關此診斷規則的更多詳細資訊。
在 Unity 的另一個診斷規則中,分析器透過等待運算子搜尋多次使用相同 UnityEngine.Awaitable 物件的位置。
出於最佳化目的,物件儲存在物件池中。
在等待呼叫時,Awaitable 物件將會回到池中。之後,如果再次將await應用於同一個對象,我們會得到一個異常。在某些情況下,也可能出現死鎖。
帶有 PVS-Studio 警告的程式碼範例:
typedef int fun_t(void); typedef const fun_t const_qual_fun_t; // <= typedef const fun_t * ptr_to_const_qual_fun_t; // <= void foo() { const fun_t c_fun_t; // <= const fun_t * ptr_c_fun_t; // <= }
在此程式碼中,我們遇到異常或死鎖。讓我解釋一下原因。我們使用awaitable 的await 呼叫來取得一個值。然後我們用這個值初始化結果變數。發生死鎖是因為await 先前已在條件構造中應用於awaitable。
查看文件以了解有關此診斷規則的更多詳細資訊。
此診斷規則旨在偵測與呼叫 UnityEngine.Object 類別的 Destroy 或 DestroyImmediate 方法相關的異常。
此問題發生在使用 UnityEngine.Transform 類型的參數的情況下。這會導致方法呼叫期間出現錯誤。 Unity 中不允許從遊戲物件中刪除 Transform 元件。
帶有 PVS-Studio 警告的程式碼範例:
Orientation GetOrientation (bool b) { int posOne = 1; int posTwo = 2; return b ? posOne : posTwo; // V2022 }
MonoBehaviour 基底類別的transform 屬性傳回Transform 類別的實例,該實例作為參數傳遞給Destroy 方法。
以這種方式呼叫該方法時,Unity會給予錯誤訊息,但元件本身不會被銷毀。
查看文件以了解有關此診斷規則的更多詳細資訊。
此診斷規則針對不同範圍的錯誤 - 效能問題。
如果您對靜態分析如何幫助優化 Unity 專案感興趣,我邀請您閱讀這篇文章。
此規則的目的是幫助分析器偵測頻繁執行的方法中 Unity 物件的建立。
定期建立/銷毀遊戲物件不僅會增加CPU的負載,還會導致垃圾收集器呼叫頻率增加。這會影響效能。
帶有 PVS-Studio 警告的程式碼範例:
void SomeCheck(const char *val) { if (!val) throw std::runtime_error { "" }; .... } void Foo() { const char *val = ....; try { SomeCheck(val); // <= } catch(std::runtime_error &err) { std::cerr << err.what() << std::endl; } }
在Update方法中,創建並銷毀了一個遊戲物件_instance。由於每次更新幀時都會執行 Update,因此建議盡可能避免其中的這些操作。
查看文件以了解有關此診斷規則的更多詳細資訊。
順便說一句,其他 Unity 診斷尚未推出!準備好迎接我們團隊的好消息:)
我們必須告訴您 C# 分析器的一項重要增強功能 - 追蹤呼叫之間方法傳回值的變化。它改變了什麼?讓我們來分解一下。
看看這個範例:
typedef int fun_t(void); typedef const fun_t const_qual_fun_t; // <= typedef const fun_t * ptr_to_const_qual_fun_t; // <= void foo() { const fun_t c_fun_t; // <= const fun_t * ptr_c_fun_t; // <= }
Example() 方法檢查 Foo() 的回傳值是否為 null。然後在條件體中再次呼叫 Foo() 方法,並且其回傳值被取消引用。
之前,分析器在這種情況下會產生警告,因為它沒有考慮呼叫的上下文,只專注於其聲明的程式碼。分析器曾經暗示可以傳回 null。
現在分析器知道 Foo() 在兩種情況下傳回相同的值,並且不會出現警告。
但是讓我們來看一個程式碼稍作修改的範例...
Orientation GetOrientation (bool b) { int posOne = 1; int posTwo = 2; return b ? posOne : posTwo; // V2022 }
從 Foo() 方法宣告我們可以知道,當 _condition == true 時,該方法傳回非 null。
分析器將在第二次呼叫之前看到 _condition 欄位發生變化,並做出假設:如果 Foo() 內部使用的欄位發生變化,則 Foo() 的傳回值也可能發生變化。
因此,潛在取消引用的警告將保留。
C# 分析器現在支援分析 .NET 9 專案!在此處詳細了解 PVS-Studio 7.34 中的這些功能和其他新功能。
隨著 PVS-Studio 7.34 的發布,Java 分析器現在有了污點分析機制!
此機製成為第一個診斷規則-搜尋 SQL 注入的基礎。 Java 分析器的未來更新將重點放在 SAST、OWASP Top-10 最常見潛在漏洞清單以及其他與污點相關的診斷規則。
現在,讓我們從一些新的一般分析規則開始,因為它們也很有價值。
這個新的診斷規則突顯了程式碼中未使用後綴運算值的區域。
問題在於,要么操作是多餘的,或者更嚴重的是,操作混淆了,開發人員想要使用前綴一。
帶有 PVS-Studio 警告的程式碼範例:
void SomeCheck(const char *val) { if (!val) throw std::runtime_error { "" }; .... } void Foo() { const char *val = ....; try { SomeCheck(val); // <= } catch(std::runtime_error &err) { std::cerr << err.what() << std::endl; } }
運算子不會影響calculateSomething方法傳回的值。
查看文件以了解有關此診斷規則的更多詳細資訊。
從這個診斷規則的名稱可以看出,它偵測到可能的溢出。
帶有 PVS-Studio 警告的程式碼範例:
typedef int fun_t(void); typedef const fun_t const_qual_fun_t; // <= typedef const fun_t * ptr_to_const_qual_fun_t; // <= void foo() { const fun_t c_fun_t; // <= const fun_t * ptr_c_fun_t; // <= }
給整數變數賦值超出了有效範圍,會導致溢位。
變數顯然會儲存與開發人員嘗試指派的值不同的值。
查看文件以了解有關此診斷規則的更多詳細資訊。
此診斷有助於識別同步問題。
帶有 PVS-Studio 警告的程式碼範例:
Orientation GetOrientation (bool b) { int posOne = 1; int posTwo = 2; return b ? posOne : posTwo; // V2022 }
分析器發現wait、notify和notifyAll方法,因為它們可能在不同步的上下文中被呼叫。它們與發生同步的物件的監視器一起操作。也就是說,它們的呼叫僅在同步上下文中並且僅在發生同步的物件上才是正確的。
如果在不同步的上下文或錯誤的物件上呼叫 wait、notify 或 notifyAll 方法,我們會收到 IllegalMonitorStateException 異常。
查看文件以了解有關此診斷規則的更多詳細資訊。
Java分析器的第一個與污點相關的診斷規則!更具體地說,分析器現在可以檢測潛在的 SQL 注入。
SQL 注入是一個漏洞,允許攻擊者將其程式碼注入 SQL 查詢中。如果查詢使用外部資料而沒有正確驗證它,則會面臨資料庫中儲存資訊的完整性和機密性的風險。
void SomeCheck(const char *val) { if (!val) throw std::runtime_error { "" }; .... } void Foo() { const char *val = ....; try { SomeCheck(val); // <= } catch(std::runtime_error &err) { std::cerr << err.what() << std::endl; } }
如果使用者被證明是惡意的,且參數的值大約如下:-“111'或1=1;刪除表使用者;選擇'”,—您可以告別使用者表。因此,檢查外部資料很重要。
查看文件以了解有關此診斷規則的更多詳細資訊。
感謝您的閱讀!
如果您有文章或問題的請求,請隨時透過回饋表發送。最後但並非最不重要的一點是,我們很樂意在評論中聽到您的想法:)
以上是PVS-Studio 4 中的新診斷規則的詳細內容。更多資訊請關注PHP中文網其他相關文章!