if (in_smallbin_range (nb)) { idx = smallbin_index (nb); bin = bin_at (av, idx);
if ((victim = last (bin)) != bin) //victim就是要脱链的堆块,也就是small bin里的最后一个 //这个if在判断我们所需要的size的那条small bin链上是否存在堆块,存在的话就把victim给脱链 { bck = victim->bk; if (__glibc_unlikely (bck->fd != victim))//对small bin的双向链表的完整性做了检查,确保victim->bk->fd指向的还是victim //如果我们在这里劫持了victim的bk指针,就会导致bck的fd指向的并不是victim,从而触发异常 malloc_printerr ("malloc(): smallbin double linked list corrupted"); set_inuse_bit_at_offset (victim, nb);//设置下一个(高地址)chunk的prev_inuse位 bin->bk = bck;//将victim脱链 bck->fd = bin; if (av != &main_arena) set_non_main_arena (victim); check_malloced_chunk (av, victim, nb); #if USE_TCACHE /* While we're here, if we see other chunks of the same size, stash them in the tcache. */ size_t tc_idx = csize2tidx (nb);//获取size对应的tcache索引 if (tcache && tc_idx < mp_.tcache_bins)//如果这个索引在tcache bin的范围里,也就是这个size属于tcache bin的范围 { mchunkptr tc_victim;
/* While bin not empty and tcache not full, copy chunks over. */ while (tcache->counts[tc_idx] < mp_.tcache_count//如果tcache bin没有满 && (tc_victim = last (bin)) != bin)//如果small bin不为空,tc_victim为small bin中的最后一个堆块 { if (tc_victim != 0) { bck = tc_victim->bk;//这里取tc_victim的bk指针,并没有针对bck做双向链表完整性检查,因此我们可以去攻击tc_victim的bk指针 set_inuse_bit_at_offset (tc_victim, nb); if (av != &main_arena) set_non_main_arena (tc_victim); bin->bk = bck;//将tc_victim从small bin中脱链 bck->fd = bin;//如果我们伪造bck,这里就可以将bck->fd的位置写入一个bin的地址(main_arena+96) tcache_put (tc_victim, tc_idx);//将tc_victim链入tc_idx这条链 } } } #endif void *p = chunk2mem (victim); alloc_perturb (p, bytes); return p; } }