1. 程式人生 > 實用技巧 >新的C++安全編碼規則出爐

新的C++安全編碼規則出爐

新的安全編碼規則

在Visual Studio v16.8 Preview 3中,我們添加了一些新的安全編碼規則,來幫助開發者更容易找到一些更加容易導致Bug的編碼錯誤,這些錯誤涵蓋了從簡單的功能缺失到嚴重的安全漏洞問題。
這些規則都是來自於真實世界的產品缺陷報告,在微軟,我們會在我們的每一款產品中執行這些安全編碼規則,以滿足產品在安全和合規方面的需求。

在今天的文章中,我們會介紹VARIANT及其衍生的VARIANTARG和PROPVARIANT結構相關的編碼規則。為了更加容易的使用這些規則,我們構建了一個名為VariantClear的程式碼分析擴充套件工具,這個擴充套件將會檢測程式碼是否符合預期的編碼規則。為什麼叫這個擴充套件為VariantClear呢?因為它的主要目的就是為了檢測那些誤用VariantClear函式的程式碼。

VariantClear擴充套件將會檢測出如下的程式碼警告:


> C33001: VARIANT ‘var’ 在它被反初始化時被重置。

> C33004: VARIANT ‘var’ 在它被初始化之前被重置,且它被標記為輸出(Out)引數。

> C33005: VARIANT ‘var’ 被標記為輸入或輸入/輸出引數,但是它沒有被初始化。

VariantClear 規則

VARIANT是一個非常方便好用的結構體,可以使用它來對各種不同的資料型別進行資料交換。在任意時刻,它都可以被用來表示一個數據型別,或者空值。在這個結構體中有一個名為VARIANT::vt的成員,用來表示被封裝的資料型別或者空值型別。

一個VARIANT結構必須被在使用或者傳入到其他程式碼之前進行顯式的初始化。否則,就會出現訪問隨機記憶體資料的問題,進而帶來各種意想不到的Bug。

當一個VARIANT結構體不再使用的時候,也需要將它顯式的重置。否則,會出現潛在的資源洩露或者對已離開其作用域的資源的錯誤訪問。

通常,可以使用VariantInit函式來對一個VARIANT結構體進行初始化。對應地,可以使用VariantClear函式對它進行重置。

另外,還有一些對VARIANT結構的高階封裝結構,例如CComVariant和_variant_t。
在構造階段,它們的建構函式將呼叫VariantInit來對結構進行初始化,並將其資料型別設定為空值型別。

在析構階段,它們的解構函式將呼叫VariantClear來對結構體進行銷燬並將資料型別設定回空值。

VariantClear規則將嘗試對目的碼進行分析,並對那些沒有對VARIANT結構體進行合適的初始化或反初始化的程式碼給出提示。

C33001警告

當一個未初始化的VARIANT結構體傳遞給一個會使用VariantClear函式來重置VARIANT的API的時候,會觸發這個警告。
因為,這類API會期待傳入的VARIANT結構體是已經初始化的。但是很多開發者總是會忘記初始化這個步驟。
下面是一個簡單的例子:

在上面的程式碼中,會觸發C33001警告。因為VARIANT結構體僅在some_condition為true時才會被初始化。如果這個標誌為false,則當它傳遞給VariantClear函式時是未初始化的。
為了修復這個問題,我們可以以如下的方式修改程式碼,確保呼叫VariantClear時結構體肯定是經過初始化的。 如下圖所示:

C33004警告

當一個VARIANT結構體被標記為Out引數,而這個引數可能在輸入的時候並沒有被初始化,當它進一步被傳遞給一個會使用VariantClear函式來重置這個結構體的API時,會觸發此警告。

當呼叫一個函式的時候,一個被標記為Out的引數並不一定會被初始化。只有當它函式返回的時候,它才會被初始化。

從更加安全的角度來看,在進行程式碼分析的時候,一個Out引數被認為是未初始化的。如果當這個引數被傳遞到一個函式,而這個函式可能會使用VariantClear操作這個結構體時,它會嘗試重置這個結構體,或者使用記憶體裡的隨機資料。下面是一個簡單的例子:

為了修復這個問題,可以在訪問Out引數時對它進行初始化,如下圖所示:

C33005警告

當一個未初始化的VARIANTBeijing傳遞給一個需要輸入型引數的函式的時候,會觸發此警告。
如下圖所示:

通過這個C33005警告,我們可以更加清楚地明白為什麼C44004警告會被觸發。
當一個未經初始化的VARIANT的結構體被當做一個輸入型引數傳遞的時候,會顯式地違反C33005規則。

如何在Visual Studio中啟用新的規則

下圖中列出了可以用在工程上的不同的規則,可以根據這個表格在Visual Studio中啟用規則。

總結

當裡個當,宣告變數的時候,還是不要忘記初始化。

最後

Microsoft Visual C++團隊的部落格是我非常喜歡的部落格之一,裡面有很多關於Visual C++的知識和最新開發進展。大浪淘沙,如果你對Visual C++這門古老的技術還是那麼感興趣,則可以經常去他們那(或者我這)逛逛。
本文來自:《New Safety Rules in C++ Code Analysis》