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;甚至难以获得。这种场景正是**少样本…