什么可以解释调用 free() 时的堆损坏?

2024-02-01

我已经调试了几天的崩溃,该崩溃发生在 OpenSSL 的深处(与维护者讨论here https://www.mail-archive.com/openssl-dev@openssl.org/msg38571.html)。我花了一些时间进行调查,所以我会尽力使这个问题变得有趣且内容丰富。

首先,为了提供一些背景信息,我重现崩溃的最小样本如下:

#include <openssl/crypto.h>
#include <openssl/ec.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/engine.h>

int main()
{
    ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); 
    ENGINE_load_builtin_engines();

    EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_sect571k1);
    EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
    EC_KEY* eckey = EC_KEY_new();
    EC_KEY_set_group(eckey, group);
    EC_KEY_generate_key(eckey);
    BIO* out = BIO_new(BIO_s_file());
    BIO_set_fp(out, stdout, BIO_NOCLOSE);
    PEM_write_bio_ECPrivateKey(out, eckey, NULL, NULL, 0, NULL, NULL); // <= CRASH.
}

基本上,此代码生成一个椭圆曲线密钥并尝试将其输出到stdout。类似的代码可以在openssl.exe ecparam以及在线维基百科。它在 Linux 上运行良好(valgrind 根本没有报告任何错误)。它仅在 Windows (Visual Studio 2013 - x64) 上崩溃。我确保正确的运行时间已链接到(/MD就我而言,对于所有依赖项)。

不怕邪恶,我在 x64-debug 中重新编译了 OpenSSL(这次链接了所有内容/MDd),并单步执行代码以找到有问题的指令集。我的搜索引导我找到了这段代码(在 OpenSSL 中tasn_fre.c file):

static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
{
    // ... some code, not really relevant.
    tt = it->templates + it->tcount - 1;

    for (i = 0; i < it->tcount; tt--, i++) {
        ASN1_VALUE **pseqval;
        seqtt = asn1_do_adb(pval, tt, 0);
        if (!seqtt) continue;

        pseqval = asn1_get_field_ptr(pval, seqtt);
        ASN1_template_free(pseqval, seqtt);
    }
    if (asn1_cb)
        asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
    if (!combine) {
        OPENSSL_free(*pval); // <= CRASH OCCURS ON free()
        *pval = NULL;
    }
    // Some more code...
}

对于那些不太熟悉 OpenSSL 及其 ASN.1 例程的人来说,基本上这是什么for-loop 的作用是遍历序列的所有元素(从最后一个元素开始)并“删除”它们(稍后会详细介绍)。

就在崩溃发生之前,删除了 3 个元素的序列(在*pval,即0x00000053379575E0)。查看内存,可以看到发生了以下事情:

该序列有 12 个字节长,每个元素有 4 个字节长(在本例中,2, 5, and 10)。在每次循环迭代中,元素都会被 OpenSSL“删除”(在这种情况下,既不会删除元素,也不会删除元素)delete or free被调用:它们只是被设置为特定值)。以下是一次迭代后内存的样子:

这里的最后一个元素被设置为ff ff ff 7f我认为这是 OpenSSL 确保稍后未分配内存时不会泄漏关键信息的方法。

就在循环之后(以及调用之前OPENSSL_free()),内存如下:

所有元素均设置为ff ff ff 7f, asn1_cb is NULL所以没有打电话。接下来的事情是调用OPENSSL_free(*pval).

这个电话给free()似乎有效且分配的内存失败并导致执行中止并显示一条消息:“检测到堆损坏”.

对此感到好奇,我迷上了malloc, realloc and free(如 OpenSSL 允许)以确保这不是双重释放或从未分配的内存上的释放。事实证明内存在0x00000053379575E0实际上是一个确实已分配的 12 字节块(之前从未释放过)。

我不知道这里发生了什么:根据我的研究,似乎free()通常返回的指针失败malloc()。除此之外,该内存位置之前已被写入几条指令,没有任何问题,这证实了内存已正确分配的假设。

我知道在没有所有信息的情况下远程调试即使不是不可能也是很困难的,但我不知道下一步应该做什么。

所以我的问题是:Visual Studio 的调试器到底是如何检测到这个“HEAP CORRUPTION”的?当源自呼叫时,所有可能的原因是什么?free() ?


一般来说,可能性包括:

  1. 免费重复。
  2. Prior免费重复。
  3. (最有可能)您的代码在开始之前或结束之后写入超出了分配的内存块的限制。malloc()朋友们在这里放置了额外的簿记信息,例如大小,可能还包括健全性检查,如果覆盖,您将失败。
  4. 释放一些不存在的东西malloc()-ed.
  5. 继续写入已经存在的块free()-d.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么可以解释调用 free() 时的堆损坏? 的相关文章

  • 调用 McAfee 病毒扫描引擎

    我收到客户的请求 要求使用他们服务器上的 McAfee 病毒扫描将病毒扫描集成到应用程序中 我做了一些调查 发现 McScan32 dll 是主要的扫描引擎 它导出各种看起来有用的函数 我还发现提到了 McAfee Scan Engine
  • C# 异步等待澄清?

    我读了here http blog stephencleary com 2012 02 async and await html that 等待检查等待的看看它是否有already完全的 如果 可等待已经完成 那么该方法将继续 运行 同步
  • 根据属性的类型使用文本框或复选框

    如果我有这样的结构 public class Parent public string Name get set public List
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • 无限循环与无限递归。两者都是未定义的吗?

    无副作用的无限循环是未定义的行为 看here https coliru stacked crooked com view id 24e0a58778f67cd4举个例子参考参数 https en cppreference com w cpp
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • DotNetZip:如何提取文件,但忽略zip文件中的路径?

    尝试将文件提取到给定文件夹 忽略 zip 文件中的路径 但似乎没有办法 考虑到其中实现的所有其他好东西 这似乎是一个相当基本的要求 我缺少什么 代码是 using Ionic Zip ZipFile zf Ionic Zip ZipFile
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template

随机推荐

  • 如何使用R做多项选择题?

    我试图弄清楚如何分析我最近进行的一项调查中的多个选择 多个响应 即 选择所有适用的 问题 SPSS 具有分析在线调查数据和此类问题的出色功能 因此我猜测 R 具有该功能以及更多功能 在 Excel 中处理这些调查答案有点棘手 例如 按年龄显
  • Pathauto 中的菜单路径

    如何在 Drupal 7 下获取 pathauto 以通过完整菜单路径生成 URL 别名 只是一个更新 以防有人在使用更新版本的 Pathauto Token 时遇到此问题 这对我有用 节点 菜单链接 父母 加入路径 节点 菜单链接
  • 为什么0=0.5?

    我注意到 Z3 4 3 1 在处理 smt2 文件时出现一些奇怪的行为 If I do assert 0 0 5 就会得到满足 但是 如果我改变顺序并执行 assert 0 5 0 这是不能令人满意的 我对发生的情况的猜测是 如果第一个参数
  • pandas:将多列转换为字符串

    我有一些专栏 a b c etc a and c are float64 while b is object 我想将所有列转换为字符串并保留nans 尝试使用df a b c df a b c astype str 但这留下了空白float
  • spring-boot 数据源配置文件 w/ application.properties

    根据反馈更新了问题 我有一个 spring boot 应用程序 它具有三个数据库 用于集成测试的 H2 以及用于质量保证和生产的 Postgresql 由于 spring boot 为您创建了默认数据源 因此我没有为集成测试定义任何内容 我
  • PHP 在特定索引处插入

    我想将第一个索引处的数组元素移动到数组中的第五个索引 我怎样才能做到这一点 尽管目前对于您提出的问题至少有 2 个有效答案 但数组并不是保存频繁更改且排序很重要的列表的正确数据结构 随着数组大小的增加 这些解决方案将开始变得非常慢 正确的结
  • 按钮动作监听器

    好的 所以我制作了一个简单的程序 每次单击按钮时都会添加要计数器的值 现在 我想添加 自动 按钮功能 以在单击 自动 按钮时增加计数器的值 我遇到了问题 因为它不会在屏幕上呈现每个计数器值 而是在循环完成时更新值 这是我的代码 import
  • 用正则表达式替换第 n 个匹配项

    我正在尝试找到一种方法来替换更多比赛的第n场比赛 string one two three one one 如何定位第二次出现的 一 可以做这样的事情吗 string replace bone b gi 2 one 得到这样的东西 one
  • 迁移 Feign Load Balancer 实现以兼容 Spring cloud 2020.0.0

    我有以下与 Spring Cloud 一起使用的 Feign 负载均衡器的实现Hoxtan SR6依赖关系 import feign auth BasicAuthRequestInterceptor import org apache ht
  • C# GC 不释放内存[重复]

    这个问题在这里已经有答案了 我在 C 中度过了一段糟糕的时光 在我不再引用它之后 它没有为我保存在内存中的大型结构释放内存 我在下面添加了一些代码 这些代码展示了与我遇到的问题类似的问题 我想我一定是误解了关于 GC 的一些东西 因为我不确
  • C# 只读计算属性,它们应该是方法吗?

    我有几个实体具有计算字段 例如 TotalCost 现在我将它们全部作为属性 但我想知道它们是否实际上应该是方法 有这方面的 C 标准吗 public class WorkOrder public int LaborHours get se
  • gdb:记录一些东西而不是破坏?

    是否可以让 gdb 将某些内容记录到终端而不是中断它 例如 我想在某个方法上设置一个 断点 并让 gdb 在每次调用该方法时打印 self 以及参数 基本上我想将打印语句插入任意位置而不实际重新编译 感谢您的任何建议 这是我在这些有用的评论
  • 在 Visual Studio 中更改项目中所有图像的“构建操作”属性?

    我想知道是否有办法更新 Visual Studio 项目中所有图像的属性 我有多个嵌套的图像文件夹 我想将它们的 构建操作 属性从 资源 更改为 内容 目前我只能突出显示并选择 更改一个文件夹中的所有图像 当我有数百个文件夹和数千个图像时
  • update_sequence 更改了 cloudant 数据库中的语义?

    我使用 cloudant couchdb 我注意到数据库上的 changes 查询返回的 update sequence 不是数字 例如 437985 g1AAAADveJzLYWBgYM 更重要的是 响应不稳定 如果查询数据库 3 次 我
  • Tomcat v7.0 Server 中的 Apache Axis2 Web 服务运行时不支持服务项目 Test

    Tomcat v7 0 Server 中的 Apache Axis2 Web 服务运行时不支持服务项目 Test 为什么 请帮我 我刚刚遇到了同样的问题 事实证明 Axis2不喜欢Eclipse的3 0动态Web项目 只需创建一个新的动态W
  • 在Python中将一个类的方法安全地绑定到另一个类[重复]

    这个问题在这里已经有答案了 我知道我可以将一个函数附加到一个类并使其成为一个方法 gt gt gt def is not bound inst name print Hello s name gt gt gt gt gt gt class
  • 停止调用 JNI 函数的 Java 线程

    在这里我想停止我的线程或杀死我的线程它是在Java层创建的 该线程正在调用JNI函数 有时根据我的应用程序要求 我必须停止此操作JNI函数执行在某些条件下 如果它正在进行 否则不会 new Thread new Runnable Overr
  • 如何管理具有不同数据库模式的git分支?

    我有一个项目 需要开发一项新功能 该功能需要重新设计部分数据库 同时保持主要开发分支在旧模式上工作 您管理此类项目的最佳实践是什么 我考虑过在开发新功能时拥有一个单独的数据库 但意识到这需要将数据库配置签入存储库 这是不行的 我还有其他方法
  • Angular2 与 Material Design Lite

    我在我的 angular2 应用程序中添加了以下代码 以帮助 MDL 在应用程序中移动时重新注册组件 ngAfterViewInit componentHandler upgradeDom 尽管它似乎工作正常 如预期 但我收到以下错误 16
  • 什么可以解释调用 free() 时的堆损坏?

    我已经调试了几天的崩溃 该崩溃发生在 OpenSSL 的深处 与维护者讨论here https www mail archive com openssl dev openssl org msg38571 html 我花了一些时间进行调查 所