什麼是未初始化讀取?你能指出比特幣核心中的一些例子嗎?你如何檢測它們?
什麼是未初始化讀取?你能指出比特幣核心中的一些例子嗎?你如何檢測它們?
未初始化讀取是指在沒有初始值的情況下創建變數,然後讀取該變數的值。應該避免這種情況,因為結果行為是不可預測的,並且每次執行程序時都可能不同。根據cppreference.com:
通常未初始化的變數是一個壞主意,它們唯一有用的地方是當您要從某個輸入流中讀取變數時。
有多種工具可用於檢測未初始化的讀取,其中一些已在 2019 年 12 月的比特幣核心公關審查俱樂部會議中進行了介紹。
其中包括動態分析工具,例如MemorySanitizer (MSan)、Valgrind(特別是Memcheck)和無需執行即可檢查程式碼的靜態分析工具。
未初始化的讀取也可以通過單元、功能或模糊測試,通過使用
-Werror=uninitialized
標誌編譯或使用帶有標誌的 Clang 編譯,-ftrivial-auto-var-init=pattern
這將使用虛擬值預初始化變數。比特幣核心中檢測到未初始化讀取的歷史
Marco Falke 在最近合併的 Signet程式碼中發現了在撰寫本文時(2020 年 10 月)最近檢測到的未初始化讀取。他通過視覺審查發現了它,並在它成為主要的比特幣核心版本之前被抓住了。
作為實用迅速的亮點,近年來發現了許多未初始化讀取的範例,但隨著複雜工具的更廣泛使用,這些可能會以越來越低的頻率被發現。
2020:在 Erlay 網路程式碼中使用未初始化的記憶體- 在合併前發現
2020:在 BIP324 加密的 p2p 傳輸解/序列化器程式碼中使用未初始化的記憶體(廣告中的真相:我還沒有通過編寫 PoC 來驗證這一點) - 發現預合併
2020: util: 通過檢查 gmtime_s/gmtime_r 返迴避免潛在的未初始化讀取 FormatISO8601DateTime(int64_t)
2019:在收到我們已經擁有的交易時在網路程式碼中使用未初始化的記憶體- 合併後發現
2018:錢包:修復 ParseHDKeypath(…) 中的不確定性。避免在路徑計算中使用未初始化的變數。
2018:錢包:修復 CWallet::CreateTransaction(…) 中未初始化值 bnb_used 的使用
2017:[net] 修復 getnetworkinfo(const JSONRPCRequest&) 中未初始化值的使用
2017: [test] 避免讀取 tx_invalid-test (transaction_tests.cpp) 中可能未初始化的變數