unlink源码阅读总结
合并优先级
- 先合并物理低地址空闲块
- 后合并物理高地址空闲快
合并过程
Demo 程序
基于 glibc 2.23
1 |
|
编译指令:
1 | gcc main.c -o main |
Demo 说明
程序中 chunk0 chunk2 释放顺序可以互换不影响,当释放 chunk1 会同时发生向前和向后 unlink :
- 向前 unlink :与物理地址高 chunk2 合并
- 向后 unlink :与物理地址低 chunk0 合并
free chunk1 过程
进入 free 函数后,首先检查 hook 是否为空,不为空则跳转 hook 指向函数
经过一轮检查分配方式之后,从 __int_free
进入熟知的释放处理过程中
向后合并-合并低地址
首先进行向后合并-合并低地址空闲堆块,通过被释放堆块的 prev_inuse 标志位判断。合并之后堆块 size += prevsize
,然后将后面的(低地址)堆块 unlink 取出
unlink 之前 unsortedbin 状态:
unlink 之后 unsortedbin 状态:
注意这时还没有将取出堆块与被释放堆块进行合并,chunk0 size 还是 0x101、fd&bk 指针还是原来在 unsortedbin 的值:
向前合并-合并高地址(下一块不是topchunk)
判断前一块堆块是不是 topchunk :
nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
通过查询前两块的 prev_inuse 标志位,判断前一块堆块是不是空闲:
如果前一块空闲且不是 topchunk 则 unlink 出来
unlink 之前 unsortedbin 状态:
unlink 之后 unsortedbin 状态:
和向后合并一样现在只是将堆块 unlink 出来,并没有进行合并。
合并堆块&放入对应bin
通过 size 判断应该应该放入哪个 bin 中,再判断应该用哪个 size 的链表,最后在这里完成写入:
相关资料
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 SkYe231 Blog!