OpenSSL 內存泄漏修復全景:119 個歷史 Commit 的類型分析與防御啟示

1 前言

openssl 開源庫作為 C/C++ 項目中常用的組件庫,截至 2025年7月4日 ,openssl 的提交記錄包含 119 個 Fix memory leak

本文基于源碼 Commit 分析,揭示了 OpenSSL 內存泄漏修復從被動應對到主動防御的演進趨勢,給各位 C/C++ 開發者提供了從漏洞分類到防御實踐的完整參考。

2 內存泄漏類型分類

1. 動態內存分配未釋放

  • 場景:使用malloc/new分配內存后未調用free/delete釋放
  • Commit ID示例
    • 6543f34:PKCS7_add_signed_attribute失敗時未釋放seq指針
    • 20a2f3b:ecdsa_keygen_knownanswer_test未釋放EC_POINT對象
    • d48874a:sk_OPENSSL_STRING_push返回失敗時未釋放字符串數組

示例代碼 DIFF:

-    return PKCS7_add_signed_attribute(si, NID_id_smime_aa_signingCertificate,
-                                      V_ASN1_SEQUENCE, seq);
+    if (!PKCS7_add_signed_attribute(si, NID_id_smime_aa_signingCertificate,
+                                    V_ASN1_SEQUENCE, seq)) {
+        ASN1_STRING_free(seq);
+        return 0;
+    }
+    return 1;
  • 發現方式:人工代碼審查、單元測試

2. 資源句柄未關閉

  • 場景:BIO對象、SSL會話、文件句柄等資源未正確釋放
  • Commit ID示例
    • 857c223:load_key_certs_crls使用stdin時未關閉BIO對象
    • 9561e2a:PSK會話文件加載后未釋放會話資源
    • 35b1a43:tls_decrypt_ticket未釋放HMAC_CTX和EVP_CIPHER_CTX

示例代碼 DIFF:

-    return PKCS7_add_signed_attribute(si, NID_id_smime_aa_signingCertificate,
-                                      V_ASN1_SEQUENCE, seq);
+    if (!PKCS7_add_signed_attribute(si, NID_id_smime_aa_signingCertificate,
+                                    V_ASN1_SEQUENCE, seq)) {
+        ASN1_STRING_free(seq);
+        return 0;
+    }
+    return 1;
  • 發現方式:Valgrind內存分析、功能測試

3. 容器/棧內存泄漏

  • 場景:數組、鏈表等容器結構在錯誤路徑未清空
  • Commit ID示例
    • 1c42216:crl2pkcs7工具錯誤路徑未釋放OPENSSL_STRING棧
    • 55500ea:X509_verify_cert未釋放證書擴展數據棧
    • 4798e06:X509V3_add1_i2d未釋放證書擴展對象

示例代碼 DIFF:

         bio = BIO_new_fp(stdin, 0);
-        if (bio != NULL)
+        if (bio != NULL) {ctx = OSSL_STORE_attach(bio, "file", libctx, propq,get_ui_method(), &uidata, NULL, NULL);
+            BIO_free(bio);
+        }
  • 發現方式:Coverity靜態分析、集成測試

4. 跨模塊資源泄漏

  • 場景:引擎(ENGINE)、密碼學模塊間資源未協調釋放
  • Commit ID示例
    • 8c63b14:engine_cleanup_add_first未釋放引擎輔助結構
    • a076951:X509_PUBKEY_set創建新密鑰后未釋放舊資源
    • 3a1d2b5:i2d_ASN1_bio_stream未釋放ASN.1編解碼狀態數據

示例代碼 DIFF:

item = int_cleanup_item(cb);
-    if (item)
-        sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0);
+    if (item != NULL)
+        if (sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0) <= 0)
+            OPENSSL_free(item);
  • 發現方式:模塊間接口測試、人工代碼審查

5. 異常處理路徑泄漏

  • 場景:函數在異常/錯誤返回時未執行清理邏輯
  • Commit ID示例
    • 009fa4f:test_evp_cipher_pipeline錯誤時未釋放密碼學上下文
    • fa856b0:copy_issuer中sk_GENERAL_NAME_reserve失敗未釋放ialt
    • b2474b2:tls_parse_ctos_psk錯誤路徑未釋放SSL_SESSION

示例代碼 DIFF:

if (sesstmp == NULL) {SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
-                return 0;
+                goto err;
}
SSL_SESSION_free(sess);
sess = sesstmp;
  • 發現方式:錯誤注入測試、AddressSanitizer

3 測試與驗證方式分類

1. 靜態分析工具

  • 工具:Coverity、Clang Scan-Build
  • Commit ID示例
    • 009fa4f:Coverity檢測到test_evp_cipher_pipeline泄漏
    • 33c4187:Coverity發現apps/cmp.c資源泄漏
    • 8515534:Coverity報告crltest錯誤路徑泄漏

示例代碼 DIFF:

-    aint = ASN1_INTEGER_new();
-    if (aint == NULL || !ASN1_INTEGER_set(aint, value))
+    if ((aint = ASN1_INTEGER_new()) == NULL)goto oom;val = ASN1_TYPE_new();
-    if (val == NULL) {
+    if (!ASN1_INTEGER_set(aint, value) || val == NULL) {ASN1_INTEGER_free(aint);goto oom;}
@@ -2065,6 +2064,7 @@ static int handle_opt_geninfo(OSSL_CMP_CTX *ctx)return 1;oom:
+    ASN1_OBJECT_free(type);CMP_err("out of memory");return 0;}
  • 特點:可發現代碼邏輯缺陷,提前預防泄漏

2. 動態內存檢測

  • 工具:AddressSanitizer(ASan)、Valgrind
  • Commit ID示例
    • a906436:ASan檢測到x509_req_test中53字節泄漏
    • 6b5c7ef:ASan發現TLS1.2壓縮導致35KB泄漏
    • 9c7a780:Valgrind定位到內存泄漏報告未釋放bio_err

示例代碼 DIFF:

@@ -435,6 +431,10 @@ int main(int Argc, char *ARGV[])#endifapps_shutdown();CRYPTO_mem_leaks(bio_err);
+    if (bio_err != NULL) {
+        BIO_free(bio_err);
+        bio_err = NULL;
+    }OPENSSL_EXIT(ret);}
  • 特點:運行時捕獲實際泄漏,定位具體分配位置

3. 單元與功能測試

  • 場景:密鑰生成、證書驗證、加密解密等測試用例
  • Commit ID示例
    • 21f0b80:ssl_old_test.c中TLS密鑰協商測試泄漏
    • 81d61a6:ectest橢圓曲線測試未釋放臨時密鑰
    • c5d0612:asynctest異步測試未調用清理函數
  • 發現方式:測試覆蓋率分析、持續集成(CI)

4. 模糊測試(Fuzzing)

  • 工具:libFuzzer、oss-fuzz
  • Commit ID示例
    • 6afef8b:libFuzzer發現無效CertificateRequest泄漏
    • 1400f01:libFuzzer檢測到ASN.1編解碼泄漏
    • a1d6a0b:oss-fuzz發現tls_parse_stoc_key_share泄漏

示例代碼 DIFF:

@@ -1027,6 +1027,7 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, int *al)PACKET_remaining(&encoded_pt))) {*al = SSL_AD_DECODE_ERROR;SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_ECPOINT);
+        EVP_PKEY_free(skey);return 0;}
  • 特點:通過異常輸入觸發邊緣場景泄漏

4 防御與修復措施分類

1. 錯誤處理優化

  • 措施:統一使用goto err模式,確保所有路徑釋放資源
  • Commit ID示例
    • 6543f34:在失敗路徑添加free(seq)
    • fa856b0:在通用錯誤路徑添加sk_GENERAL_NAME_free(ialt)
    • b2474b2:錯誤路徑中調用SSL_SESSION_free(sess)
  • 實現方式:代碼重構,增加統一清理標簽

示例代碼 DIFF:

@@ -648,8 +648,12 @@ static int ossl_ess_add1_signing_cert(PKCS7_SIGNER_INFO *si,}OPENSSL_free(pp);
-    return PKCS7_add_signed_attribute(si, NID_id_smime_aa_signingCertificate,
-                                      V_ASN1_SEQUENCE, seq);
+    if (!PKCS7_add_signed_attribute(si, NID_id_smime_aa_signingCertificate,
+                                    V_ASN1_SEQUENCE, seq)) {
+        ASN1_STRING_free(seq);
+        return 0;
+    }
+    return 1;}

2. 智能指針與引用計數

  • 措施:使用組件特定釋放函數(如SSL_SESSION_free)
  • Commit ID示例
    • 4798e06:使用X509V3_EXT_free釋放擴展對象
    • 70f589a:BN_rand_range提前檢查rnd指針NULL
    • 20c7feb:DTLS記錄層釋放前檢查消息緩沖區
  • 實現方式:封裝資源管理類,自動處理生命周期

示例代碼 DIFF:

@@ -136,6 +136,11 @@ static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range,int n;int count = 100;+    if (r == NULL) {
+        ERR_raise(ERR_LIB_BN, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+

3. 防御性編程

  • 措施:分配前驗證參數,失敗時立即釋放已分配資源
  • Commit ID示例
    • d48874a:檢查sk_OPENSSL_STRING_push返回值
    • 19b87d2:s390x_HMAC_CTX_copy先釋放目標緩沖區
    • 62b0a0d:CTLOG_new_from_base64限制填充字符數
  • 實現方式:前置條件檢查,分層錯誤處理

4. 工具輔助修復

  • 措施:集成靜態分析結果,針對性修復
  • Commit ID示例
    • 33c4187:根據Coverity報告修復apps/cmp.c泄漏
    • 8515534:根據Valgrind輸出修復BIO引用計數
    • d0a4b7d:修復libFuzzer發現的DTLS碎片泄漏
  • 實現方式:建立漏洞修復工作流,關聯工具報告

5 代碼提交分析

泄漏類型部分Commit ID示例發現方式
動態內存未釋放6543f34, 20a2f3b, d48874a, 70f589a人工審查、單元測試
資源句柄未關閉857c223, 9561e2a, 35b1a43, 28adea9Valgrind、功能測試
容器/棧泄漏1c42216, 55500ea, 4798e06, 74c929dCoverity、集成測試
跨模塊資源泄漏8c63b14, a076951, 3a1d2b5, 981a5b7接口測試、人工審查
異常路徑泄漏009fa4f, fa856b0, b2474b2, 026e012錯誤注入、ASan
靜態分析發現009fa4f, 33c4187, 8515534, a1d6a0bCoverity、Clang Scan-Build
動態內存檢測a906436, 6b5c7ef, 9c7a780, d0a4b7dASan、Valgrind
單元功能測試21f0b80, 81d61a6, c5d0612, 875db35CI測試、覆蓋率分析
模糊測試發現6afef8b, 1400f01, a1d6a0b, 1b8f193libFuzzer、oss-fuzz

可以在命令行通過 git show <Commit ID> 查看特定提交的詳細信息。

6 總結

OpenSSL內存泄漏修復呈現以下特點:

  1. 泄漏成因:錯誤處理路徑遺漏釋放、跨模塊資源管理不一致、高并發場景競爭條件。
  2. 檢測手段:靜態分析( Coverity )、動態檢測( ASan )、模糊測試( libFuzzer )形成互補。
  3. 修復趨勢:從被動修復轉向主動防御,通過RAII原則和智能指針減少人為錯誤。
  4. 最佳實踐:統一錯誤處理模式、定期運行內存分析工具、在CI中集成泄漏檢測。

我的后續文章將具體講解這些典型漏洞的原理檢測工具的具體應用

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87689.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87689.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87689.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

十一、Python 3.13 的新特性和更新內容

1. 性能提升 1.1 解釋器性能優化 更快的啟動速度&#xff1a;Python 3.13 啟動時間比 3.12 快約 10-15%。內存使用優化&#xff1a;減少了內存占用&#xff0c;特別是在處理大型數據結構時。 1.2 字節碼優化 新的字節碼指令&#xff1a;引入了更高效的字節碼指令&#xff0…

后端 Maven打包 JAR 文件、前端打包dist文件、通過后端服務訪問前端頁面、Nginx安裝與部署

打包 JAR 文件通常使用 Maven 或 Gradle 構建工具&#xff08;Spring Boot 項目默認推薦 Maven&#xff09;。以下是詳細步驟和常見問題解答&#xff1a; 一、后端 Maven打包 JAR 文件 1. 確保項目是 Spring Boot 項目 項目結構應包含 pom.xml&#xff08;Maven 配置文件&am…

大數據系列 | 日志數據采集工具Filebeat的架構分析及應用

大數據系列 | 日志數據采集工具Filebeat的架構分析及應用 1. Filebeat的由來2. Filebeat原理架構分析3. Filebeat的應用3.1. 安裝Filebeat3.2. 實戰采集應用程序日志1. Filebeat的由來 在介紹Filebeat之前,先介紹一下Beats。Beats是一個家族的統稱,Beats家族有8個成員,早期的…

基于 Vue + RuoYi 架構設計的商城Web/小程序實訓課程

以下是基于 Vue RuoYi 架構設計的商城Web/小程序實訓課程方案&#xff0c;結合企業級開發需求與教學實踐&#xff0c;涵蓋全棧技術棧與實戰模塊&#xff1a; &#x1f4da; 一、課程概述 目標&#xff1a;通過Vue前端 RuoYi后端&#xff08;Spring Boot&#xff09;開發企業…

Puppeteer 相關漏洞-- Google 2025 Sourceless

題目的代碼非常簡單,核心只有這一句 page.goto(url, { timeout: 2000 });方案1 Puppeteer 是一個常用的自動化瀏覽器工具&#xff0c;默認支持 Chrome&#xff0c;但也可以配置支持 Firefox。然而&#xff0c;當 Puppeteer 運行在 Firefox 上時&#xff0c;會自動關閉一些安全特…

LucidShape 2024.09 最新

LucidShape的最新版本2024.09帶來了一系列新功能與增強功能&#xff0c;旨在解決光學開發者面臨的最常見和最復雜的挑戰。從微透鏡陣列&#xff08;MLA&#xff09;的自動掩模計算&#xff0c;到高級分析功能的改進&#xff0c;LucidShape 2024.09致力于簡化工作流程并增強設計…

mini-electron使用方法

把在官方群里“官方132版”目錄里下載的包里的minielectron_x64.exe解壓到你本地某個目錄&#xff0c;改名成electron.exe&#xff0c;比如G:\test\ele_test\mini_electron_pack\electron.exe。 修改你項目的package.json文件。一個例子是&#xff1a; {"name": &q…

Android 網絡全棧攻略(七)—— 從 OkHttp 攔截器來看 HTTP 協議二

Android 網絡全棧攻略系列文章&#xff1a; Android 網絡全棧攻略&#xff08;一&#xff09;—— HTTP 協議基礎 Android 網絡全棧攻略&#xff08;二&#xff09;—— 編碼、加密、哈希、序列化與字符集 Android 網絡全棧攻略&#xff08;三&#xff09;—— 登錄與授權 Andr…

45-使用scale實現圖形縮放

45-使用scale實現圖形縮放_嗶哩嗶哩_bilibili45-使用scale實現圖形縮放是一次性學會 Canvas 動畫繪圖&#xff08;核心精講50個案例&#xff09;2023最新教程的第46集視頻&#xff0c;該合集共計53集&#xff0c;視頻收藏或關注UP主&#xff0c;及時了解更多相關視頻內容。http…

軟件開發早期階段,使用存儲過程的優勢探討:敏捷開發下的利器

在現代軟件開發中&#xff0c;隨著持續集成與敏捷開發的深入推進&#xff0c;開發團隊越來越重視快速響應需求變更、快速上線迭代。在這種背景下&#xff0c;傳統將業務邏輯全部放在應用層的方式在某些階段顯得笨重。本文將探討在軟件開發初期&#xff0c;特別是在需求尚不穩定…

『 C++入門到放棄 』- string

C 學習筆記 - string 一、什麼是string ? string 是 C 中標準函數庫中的一個類&#xff0c;其包含在 中 該類封裝了C語言中字符串操作&#xff0c;提供內存管理自動化與更多的操作 支持複製、比較、插入、刪除、查找等功能 二、常用接口整理 類別常用方法 / 說明建立與指…

ARM架構下C++程序堆溢出與棧堆碰撞問題深度解析

ARM架構下C程序堆溢出與棧堆碰撞問題深度解析 一、問題背景&#xff1a;從崩潰現象到內存異常 在嵌入式系統開發中&#xff0c;程序崩潰是常見但棘手的問題。特別是在ARM架構設備上&#xff0c;一種典型的崩潰場景如下&#xff1a;程序在執行聚類算法或大規模數據處理時突然終…

.NET9 實現排序算法(MergeSortTest 和 QuickSortTest)性能測試

在 .NET 9 平臺下&#xff0c;我們對兩種經典的排序算法 MergeSortTest&#xff08;歸并排序&#xff09;和 QuickSortTest&#xff08;快速排序&#xff09;進行了性能基準測試&#xff08;Benchmark&#xff09;&#xff0c;以評估它們在不同數據規模下的執行效率、內存分配及…

RabbitMQ - SpringAMQP及Work模型

一、概述RabbitMQ是一個流行的開源消息代理&#xff0c;支持多種消息傳遞協議。它通常用于實現異步通信、解耦系統組件和分布式任務處理。Spring AMQP是Spring框架下的一個子項目&#xff0c;提供了對RabbitMQ的便捷訪問和操作。本文將詳細介紹RabbitMQ的工作模型&#xff08;W…

微信小程序51~60

1.界面交互-loading提示框 loading提示框用于增加用戶體驗&#xff0c; 對應的API有兩個&#xff1a; wx.showLoading()顯示loading提示框wx.hideLoading()關閉loading提示框 Page({getData () {//顯示loading提示框wx.showLoading({//提示內容不會自動換行&#xff0c;多出來的…

SqueezeBERT:計算機視覺能為自然語言處理在高效神經網絡方面帶來哪些啟示?

摘要 人類每天閱讀和撰寫數千億條消息。得益于大規模數據集、高性能計算系統和更優的神經網絡模型&#xff0c;自然語言處理&#xff08;NLP&#xff09;技術在理解、校對和組織這些消息方面取得了顯著進展。因此&#xff0c;將 NLP 部署于各類應用中&#xff0c;以幫助網頁用…

Springboot開發常見注解一覽

注解用法常用參數Configuration用于標記類為配置類&#xff0c;其中通過Bean方法定義Spring管理的組件。它替代XML配置&#xff0c;用Java代碼聲明對象創建邏輯&#xff0c;并確保單例等容器特性生效。相當于給Spring提供一個“制造說明書”來組裝應用部件RestControllerRestCo…

Maven高級——分模塊設計與開發

目錄 ?編輯 分模塊設計與開發 拆分策略 繼承與聚合 版本鎖定 聚合 作用 實現 Maven中繼承與聚合的聯系與區別&#xff1f; 聯系 區別 私服 分模塊設計與開發 將一個大項目拆分成若干個子模塊&#xff0c;方便項目的管理維護&#xff0c;擴展&#xff0c;也方便模…

線程池的七個參數設計源于對高并發場景下資源管理、系統穩定性與性能平衡的深刻洞察

?? 一、核心參數設計目標與解決的問題 參數設計目標解決的核心問題典型取值策略corePoolSize&#xff08;核心線程數&#xff09;維持常備線程資源避免頻繁創建/銷毀線程的開銷&#xff0c;提高響應速度CPU密集型&#xff1a;N_cpu 1 IO密集型&#xff1a;2 N_cpu maximum…

少樣本學習在計算機視覺中的應用:原理、挑戰與最新突破

在深度學習的黃金時代&#xff0c;大量標注數據似乎成了算法性能的前提。然而在許多現實場景中&#xff0c;如醫療圖像分析、工業缺陷檢測、遙感識別、甚至個性化視覺服務中&#xff0c;高質量、成規模的標注數據往往昂貴、稀缺&#xff0c;甚至難以獲得。這種場景正是**少樣本…