fastbin_dup_consolidate.c 源码
调试分析
首先malloc两个0x40大小的fastbin chunk
同样申请0x40,加上0x10大小的chunk头,1字节的假大小(由于inuse位为1),实际大小为0x50
继续调试,对p1进行了free
p1被放进fastbin的空闲链表
然后再malloc一个0x400大小的largbin chunk
来看一下_int_malloc()源码
检查是否是fastbin范围
检查是否是smallbin范围
都不是就判断属于largebin
可以看到这里在获取了largebin的下表后会检查在分配区(av)内是否有fast chunk (本例有)
如果有则触发malloc_consolidate,对分配区内的chunk进行合并分类
查看consolidate源码
主要做的就是向前合并、向后合并相邻的chunk,如果相邻的是top chunk则并入top chunk,重复这三步直到fastbin链表为空,且合并后的chunk会放到unsortedbin中,除了top chunk
而这里在free完p1后malloc了一个0x400大小的chunk
0x400 = 1024,实际分配大小为0x400 + 0x10 = 0x410
大于1024字节的chunk会从largebins中申请
此时就会触发malloc_consolidate
p1就会从fastbin中被放到unsortedbin
之后会先在unsortedbin里面整理查找是否有符合大小的chunk,在这个过程中p1就会被分类到smallbin中(因为这里已经没有去fastbin的选择了)
这个过程我们没有跟踪所以我们查看heap的时候会看到0x40大小的p1 chunk被分到了smallbin中而不是unsortedbin
然后unsortedbin为空,仍未返回需要大小的chunk,则在largebin中查找是否有合适大小的chunk(这里就不是’exact fit’了),由于largebin此时为空,则在lastremainder中切割一块0x410大小的chunk出来返回给用户,并将剩下的lastremainder保存为top chunk
而由于在consolidate的过程中p1被移动到smallbin中了,fastbin现在没有记录p1
所以我们可以再次free p1
现在,我们就同时在fastbin和smallbin里有p1
我们就可以malloc p1两次
第一次malloc结束
p1从原来的fastbin记录变为了smallbin
第二次malloc结束
p1被malloc两次才变为allocated状态
此时就发生了 ‘double free’,两次申请的chunk指针指向同一块内存,