自整理2.23版本下的malloc和free流程
1.如果处于mmap的范围,直接调用mmap分配
2.如果所需分配内存在fastbin的范围里会在fastbin里查找空闲的合适大小的chunk,如找到则结束。
3.如果所需分配的内存在smallbin的范围里,就去smallbin里查找,如找到则结束。
4.如果所需分配的内存不在smallbin里(也就是大于0x400),那么就会先尝试合并fastbin里的chunk(注意合并条件需要chunk相邻)并放入到unsorted bin准备接下去的工作(没有合并也会被放入unsortedbin)
5.在unsorted bin里查找last_remainder是否大于等于所需分配内存的chunk,如果大于,就分割出来将小地址的那块chunk使用,剩下的高地址的chunk作为新的last_remainder(依旧是在unsortedbin里),如果刚好的大小chunk,则会直接将其使用;如果last_remainder小于所需分配内存的chunk,就会先把此chunk放入 small/large bin 中去,然后去遍历其他在unsortedbin里的chunk,从链表的尾部(也就是循着bk指针)开始遍历,也就是FIFO先进先出(除了fastbin和tcachebin是LIFO:后进先出,其他bin遍历chunk都是从尾部指针开始遍历),如果有刚好的大小chunk,则会直接将其使用,并终止遍历,如果此chunk小于或大于所需分配内存,就会先把此chunk放入 small/large bin 中去,接着再重复循环下一个chunk,直至找到精确大小的chunk或找完所有unsortedbin中的chunk就会结束循环
在unsortedbin当中,若malloc(0x80),当链表中没有0x90size的chunk,则size为0xa0的freechunk也会被拿去给malloc使用,但是其他bin不行。
6.根据所申请的chunk的大小在small bin或large bin中循着bk指针搜索第一个大于等于所需空间的chunk(如果是大于的话则会进行切块操作,切下剩余的如果大于 MINSIZE就会被放入unsortedbin里当作last_remainder)
7.若topchunk空间足够则使用topchunk分配
8.若topchunk空间不足,则将旧的所剩无几的topchunk放入unsortedbin里,进行新的内存块申请,分配新的topchunk,然后再由新的topchunk分配(这种情况下一般是topchunk已经被多次分配而导致变为很小了,所以需要重新申请一块topchunk)
free流程:
1.如果free的空间是由mmap分配的(也就是ISMMAP 位为1),则直接归还操作系统
2.如果free的chunk在fastbin的范围内,放入fast bin,结束(以下合并操作不会进行,就算此chunk相邻topchunk也不会合并,tcachebin也一样)
3.如果物理相邻的前一个chunk(远离topchunk的)是free(并且不是fastbin里的)的,将前面的chunk合并,并且将两个chunk的size相加覆盖两个chunk中低地址的chunk的size以及修改低地址的chunk的fd和bk指针。然后放入unsorted bin,执行unlink
4.如果后一个chunk是top chunk,则将当前chunk(经过步骤2的合并也一样会)并入top chunk
5.如果后一个chunk是free的(并且不是fastbin里的),将后面的chunk合并,并且将两个chunk的size相加覆盖两个chunk中低地址的chunk的size以及修改低地址的chunk的fd和bk指针。然后放入unsorted bin,执行unlink
6.前后chunk都不是free的,放入unsorted bin
free之后的chunk第一时间只会进入unsortedbin或者fastbin,直到malloc之后才可能会进入到smallbin或其他bin
fastbin的chunk的下一个chunk的PREV_INUSE位始终为1,也就是说fastbin里chunk始终不会合并,但是可以通过某些漏洞强制修改下一个chunk的PREV_INUSE位为0,接着再释放临近范围不在fastbin或tcachebin(因为释放满足这两个bin范围的chunk不会进行合并操作)的chunk使其合并