自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

C++ Core Check:安全編碼準(zhǔn)則更新

開發(fā) 后端
Rust和C++是兩門比較流行的系統(tǒng)級(jí)開發(fā)語言。多年來,業(yè)界對(duì)C++的關(guān)注主要是在性能上,我們也不斷地聽到來自客戶和安全研究員的反饋:他們希望C++應(yīng)該在語言層面有更多的安全編碼準(zhǔn)則。

要性能,更要安全

Rust和C++是兩門比較流行的系統(tǒng)級(jí)開發(fā)語言。多年來,業(yè)界對(duì)C++的關(guān)注主要是在性能上,我們也不斷地聽到來自客戶和安全研究員的反饋:他們希望C++應(yīng)該在語言層面有更多的安全編碼準(zhǔn)則。

在安全編程這個(gè)方面來說,C++經(jīng)常被認(rèn)為落后于Rust。

借鑒于Rust在安全編碼方面的特性,我們?cè)赩isual Studio 2019 v16.7的C++ Core Check中新增了四條編碼安全準(zhǔn)則。讓我們來瞧瞧。

switch語句沒有default標(biāo)簽

Rust中的模式匹配結(jié)構(gòu)類似于C++中的switch語言結(jié)構(gòu)。它們的主要差異在于,Rust要求開發(fā)者覆蓋所有的模式匹配可能性,可以通過為每個(gè)模式編寫一個(gè)顯式的處理器,或者添加一個(gè)默認(rèn)的處理器(如果其他所有的模式都不匹配的話)。

舉個(gè)例子,下面的Rust代碼將不會(huì)通過編譯,因?yàn)樗鄙倌J(rèn)的處理器。

 

C++ Core Check:安全編碼準(zhǔn)則更新

這是一個(gè)簡(jiǎn)潔的安全特性,因?yàn)樗梢苑乐惯@種很容易發(fā)生但又不那么容易捕獲的編程錯(cuò)誤。

如果switch語句中使用的是枚舉類型并且不是每個(gè)枚舉值都進(jìn)行了判斷,則Visual Studio會(huì)警告開發(fā)者并發(fā)出C4061和C4062。但是,對(duì)于其他其他類型,例如整型,則沒有這個(gè)警告。

這次的版本我們引入了一個(gè)安全編碼準(zhǔn)則:對(duì)于非枚舉類型(例如char, int),如果switch語句中沒有default處理標(biāo)簽,Visual Studio將發(fā)出警告。可以在項(xiàng)目的規(guī)則設(shè)置中選擇一下三種不同的規(guī)則然后進(jìn)行代碼分析。

  • > C++ Core Check Style Rules
  • > C++ Core Check Rules
  • > Microsoft All Rules

下面我們來使用C++來重寫上面Rust的例子。

 

C++ Core Check:安全編碼準(zhǔn)則更新

如果我們將default標(biāo)簽去掉,則Visual Studio會(huì)給出如下的警告:

 

C++ Core Check:安全編碼準(zhǔn)則更新

switch語句中的隱式跳轉(zhuǎn)(Unannotated fallthrough)

關(guān)于Rust中的模式匹配的另外一個(gè)限制是:它們不支持在case語句中隱式跳轉(zhuǎn)。而在C++中,下面的代碼能完美的通過編譯器的檢查。

 

C++ Core Check:安全編碼準(zhǔn)則更新

上面的C++代碼開起來非常合理,但是在case語句中進(jìn)行隱式的跳轉(zhuǎn)很容易成為程序的Bug。舉個(gè)例子,如果開發(fā)者忘記在each(food)調(diào)用后添加break語句,則代碼還是會(huì)通過編譯,但是運(yùn)行的結(jié)果卻大不一樣。如果工程的規(guī)模十分龐大,則對(duì)于這類的Bug將很難追蹤。

幸運(yùn)的是,C++17 添加了[[fallthrough]]這樣的標(biāo)注,主要目的就是在不同的case語句中進(jìn)行隱式跳轉(zhuǎn),這樣的話,在上面的例子中,開發(fā)者就可以使用這個(gè)標(biāo)注來向編譯器表明他的確希望執(zhí)行這種行為。

在Visual Studio 2019 v16.7中,如果代碼中沒有使用[[fallthrough]]標(biāo)注的情況下出現(xiàn)了隱式跳轉(zhuǎn),則編譯器會(huì)給出C26819警告。這條規(guī)則在Visual Studio執(zhí)行代碼分析時(shí)會(huì)默認(rèn)啟用。

 

C++ Core Check:安全編碼準(zhǔn)則更新

為了解決上面的警告,可以在case語句中添加[[fallthrough]]標(biāo)注,如下圖所示:

 

C++ Core Check:安全編碼準(zhǔn)則更新

昂貴的拷貝操作

Rust和C++中一個(gè)主要區(qū)別是,Rust默認(rèn)采用移動(dòng)(move)語義,而不是拷貝(copy)。

舉個(gè)例子:

 

C++ Core Check:安全編碼準(zhǔn)則更新

這意味著,當(dāng)你確實(shí)需要拷貝語義的時(shí)候,需要使用顯式的拷貝語句,如下圖所示:

 

C++ Core Check:安全編碼準(zhǔn)則更新

C++就不同了,它默認(rèn)是拷貝語義。通常來說,這也不算什么大問題,但是有時(shí)這可能導(dǎo)致某些Bug。一個(gè)經(jīng)常發(fā)生的例子是使用range-for語句的時(shí)候,讓我們來看一下這個(gè)例子:

 

C++ Core Check:安全編碼準(zhǔn)則更新

在上面的代碼中,在vector中的每個(gè)原始被在每次迭代循環(huán)中被拷貝到p里。如果元素是一個(gè)大型結(jié)構(gòu),則拷貝操作將會(huì)十分昂貴,而且這種情況還不太容易看出來。

為了避免這種不必要的拷貝,我們?cè)贑++ Core Check中添加了一條的編碼準(zhǔn)則,建議開發(fā)者移除這種拷貝操作,如下圖所示:

 

C++ Core Check:安全編碼準(zhǔn)則更新

以下是判斷某個(gè)拷貝操作是否有必要的方法:

如果類型的大小大于平臺(tái)相關(guān)指針大小的兩倍,并且該類型不是智能指針或gsl::span, gsl::string_span或std::string_view之一,則該拷貝被認(rèn)為是不必要的。這意味著對(duì)于較小的數(shù)據(jù)類型(例如整型),不會(huì)觸發(fā)該警告。對(duì)于較大的類型,例如上面示例中的Person類型,該拷貝操作被認(rèn)為是昂貴(不必要)的,編譯器將發(fā)出警告。

關(guān)于這條規(guī)則的最后一點(diǎn)是,如果循環(huán)體中的變量是mutated,則警告也不會(huì)觸發(fā),如下圖所示:

 

C++ Core Check:安全編碼準(zhǔn)則更新

如果使用的容器不是const類型,則可以通過修改對(duì)象為引用類型來避免不必要的拷貝。

 

C++ Core Check:安全編碼準(zhǔn)則更新

但是,這樣修改會(huì)導(dǎo)致一個(gè)新的副作用。因此,這個(gè)警告僅建議將循環(huán)變量標(biāo)記為const 引用,如果無法合法地將循環(huán)變量標(biāo)記為const類型,則這個(gè)警告不會(huì)觸發(fā)。

此編碼準(zhǔn)則默認(rèn)啟用。

auto類型變量的拷貝

最后一個(gè)檢查規(guī)則是有關(guān)auto類型變量的拷貝操作的。

考慮下面的Rust代碼,其中為分配了引用的變量進(jìn)行類型解析。

 

C++ Core Check:安全編碼準(zhǔn)則更新

由于Rust的要求,在大多數(shù)情況下,復(fù)制必須是顯式的,因此在上面的例子中,password類型在分配了immutable引用后會(huì)自動(dòng)解析為immutable引用,并且不會(huì)執(zhí)行昂貴的拷貝操作。

另一方面,考慮以下C++代碼:

 

C++ Core Check:安全編碼準(zhǔn)則更新

在上面的代碼中,即使getPassword的返回類型是對(duì)字符串的const引用,password的類型也會(huì)被解析為std::string。結(jié)果是,PasswordManager::password的內(nèi)容被復(fù)制到本地變量password中。

下面用一個(gè)返回指針的函數(shù)作為對(duì)比:

 

C++ Core Check:安全編碼準(zhǔn)則更新

在分配引用和指向標(biāo)記為auto的變量的指針之間的行為差異是不明顯的,從而可能導(dǎo)致不必要的拷貝和意外拷貝。

為了防止由于此行為而導(dǎo)致的錯(cuò)誤,檢查器檢查從引用到標(biāo)記為auto的變量的所有初始化實(shí)例。如果使用與范圍檢查相同的試探法將生成的拷貝操作視為昂貴,則檢查器會(huì)發(fā)出警告,建議將變量標(biāo)記為const引用類型。

 

C++ Core Check:安全編碼準(zhǔn)則更新

并且與范圍檢查一樣,只要無法將變量合法地標(biāo)記為const,就不會(huì)發(fā)出此警告。

 

C++ Core Check:安全編碼準(zhǔn)則更新

另一個(gè)不會(huì)發(fā)出警告的情況是,無論何時(shí)從臨時(shí)對(duì)象派生引用。在這種情況下,一旦臨時(shí)文件被銷毀,使用const auto引用將導(dǎo)致對(duì)已銷毀臨時(shí)變量的”懸掛”引用。

 

C++ Core Check:安全編碼準(zhǔn)則更新

此編碼準(zhǔn)則默認(rèn)啟用。

總結(jié)

能看(寫)到這里,我覺得也應(yīng)該是個(gè)漢子了吧。

有些編碼準(zhǔn)則(例如聲明變量時(shí)必初始化),最好能成為你的肌肉記憶,當(dāng)寫出某種代碼結(jié)構(gòu)的時(shí)候,是你的肌肉,而不是大腦,來完成安全編碼原則。

最后

Microsoft Visual C++團(tuán)隊(duì)的博客是我非常喜歡的博客之一,里面有很多關(guān)于Visual C++的知識(shí)和最新開發(fā)進(jìn)展。大浪淘沙,如果你對(duì)Visual C++這門古老的技術(shù)還是那么感興趣,則可以經(jīng)常去他們那(或者我這)逛逛。

責(zé)任編輯:未麗燕 來源: 今日頭條
相關(guān)推薦

2012-06-08 17:58:48

安全加速Check Point

2010-01-25 13:43:09

C++算術(shù)編碼

2016-01-28 14:41:06

CC++編碼

2009-07-01 09:44:31

2011-07-20 16:16:03

CC++

2020-11-13 10:17:28

ENISA物聯(lián)網(wǎng)安全準(zhǔn)則物聯(lián)網(wǎng)

2017-04-14 10:00:13

云備份云端云存儲(chǔ)

2010-01-08 16:23:11

Ubuntu C++

2023-09-24 23:44:10

C++類型安全

2015-02-04 10:49:13

Visual C++C++Windows API

2010-05-26 17:26:36

SVN提交更新

2010-07-20 08:49:00

Objective C

2011-07-21 10:10:42

Objective-C 內(nèi)存 Autoreleas

2022-06-01 14:02:47

谷歌Chrome 安全團(tuán)C++

2010-02-06 17:16:49

C++托管程序

2012-04-24 09:58:26

2023-06-09 09:32:52

DeepMindC++庫算法

2020-08-19 15:30:04

PHP網(wǎng)絡(luò)安全代碼

2009-07-16 10:20:21

赫夫曼編碼

2017-04-27 23:31:29

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)