C/C++中「安全」和「不安全」代碼之間的區別是什麼?什麼是C/C++中的「安全」和「不安全」代碼?
我讀過「C++在導致嚴重安全漏洞方面不安全」的文章:How Rust Compares to Other Languages and More。什麼是不安全的不安全的代碼?
C/C++中「安全」和「不安全」代碼之間的區別是什麼?什麼是C/C++中的「安全」和「不安全」代碼?
我讀過「C++在導致嚴重安全漏洞方面不安全」的文章:How Rust Compares to Other Languages and More。什麼是不安全的不安全的代碼?
我相信約翰·雷吉漢弗的文章A Guide to Undefined Behavior in C and C++, Part 1帶給你的文章是在獲得很好的概述:
編程語言通常使正常 程序的行爲和錯誤行爲之間的區別。對於圖靈完整語言 ,我們無法可靠地確定離線程序是否有潛在的 執行錯誤;我們必須運行它才能看到。
在安全的編程語言中,錯誤在發生時被困住。例如,Java通過其異常系統在很大程度上是安全的。在不安全的編程語言中,錯誤不會被捕獲。相反,在 執行錯誤的操作之後,程序繼續進行,但是以後會出現可觀察到的後果的默默無知的方式。 Luca Cardelli關於類型系統的文章有一個很好的清晰介紹 這些問題。 C和C++在很強的意義上是不安全的:執行一個錯誤的操作會導致整個程序變得毫無意義,因爲 與僅僅具有不可預測的結果的錯誤操作相反。在這些語言中,錯誤操作據說有 未定義的行爲。
因此,一旦我們進入未定義行爲的領域之中,我們現在有「不安全」代碼。覆蓋未定義行爲不安全代碼的另一篇好文章是What Every C Programmer Should Know About Undefined Behavior #2/3:
在我們的系列的第一部分,我們討論了什麼是未定義行爲, 如何讓C和C++編譯器,以產生更高的性能 應用比「安全「的語言。這篇文章講述了「不安全」是如何實現的,解釋了未定義行爲可能導致的一些非常令人驚訝的效應。在第3部分中,我們討論編譯器可以採取哪些友好的 來減輕某些意外,即使它們不是 所需的。
我喜歡稱之爲「爲什麼未定義的行爲通常是C程序員可怕的事情」。 :-)
C和C++由它們各自的標準和we can find links to the latest ones here指定並且這些標準留下很多指定爲未定義的行爲的行爲的。這基本上意味着行爲是不可預測的。 C++標準定義未定義的行爲如下:
行爲指此國際標準並沒有規定要求 [注意:當該國際標準省略的 行爲的任何明確的定義,或者當一個程序使用可以預期未定義行爲錯誤的構造或錯誤的數據。允許的未定義的行爲 的範圍從完全忽略具有不可預知的結果的情況,到在翻譯期間的行爲或以環境特徵的文檔化方式執行程序(伴隨或不伴有發出診斷消息),終止翻譯或執行發出診斷信息)。許多錯誤的程序結構不會導致未定義的行爲;他們需要被診斷。 末端注]
不需要編譯器爲未定義行爲提供診斷,我們可以找到很多情況下,不確定的行爲已導致安全漏洞中,比較知名的案例之一可能是Linux kernel null pointer check removal:
這個想法是尋找當C/C++編譯器 明智地利用未定義的行爲時死掉的代碼。 的典型例子是幾年前在Linux內核中發現的這類錯誤。 代碼基本上是:
struct foo *s = ...; int x = s->f; if (!s) return ERROR; ... use s ...
的問題是,S的行中的解引用2只允許編譯器 推斷S不爲空(如果該指針爲空,則功能 未定義;編譯器可以簡單地忽略這種情況)。因此,在3線 空支票被默默優化掉,現在內核 包含一個可利用的漏洞,如果攻擊者能夠找到一種方法來調用 空指針
大部分時間避免不確定的驗證碼行爲是良好的編碼習慣的問題:
,並使用正確的工具,如ubsan但可以有一些模糊的情況下,如infinite loops,很多開發商可能會覺得奇怪。
C++不是不安全的;不安全的代碼是不安全的,不管其寫入的語言如何。 –
有些語言「本質上是安全的」,並且(理論上)不允許(妥善設計和配置的)系統的完整性受到威脅。 C/C++不是其中之一。 –
@HotLicks:系統的安全性實際上不應取決於程序編寫的語言。那麼,「系統」是什麼意思?一個程序? – Olaf