| 3972 | /* --------------------------- realloc support --------------------------- */ |
| 3973 | |
| 3974 | static void* internal_realloc(mstate m, void* oldmem, size_t bytes, int cpymem) { |
| 3975 | if (bytes >= MAX_REQUEST) { |
| 3976 | MALLOC_FAILURE_ACTION; |
| 3977 | return 0; |
| 3978 | } |
| 3979 | if (!PREACTION(m)) { |
| 3980 | mchunkptr oldp = mem2chunk(oldmem); |
| 3981 | size_t oldsize = chunksize(oldp); |
| 3982 | mchunkptr next = chunk_plus_offset(oldp, oldsize); |
| 3983 | size_t nextsize = chunksize(next); |
| 3984 | mchunkptr newp = 0; |
| 3985 | void* extra = 0; |
| 3986 | |
| 3987 | /* Try to either shrink or extend into top. Else malloc-copy-free */ |
| 3988 | |
| 3989 | if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) && |
| 3990 | ok_next(oldp, next) && ok_pinuse(next))) { |
| 3991 | size_t nb = request2size(bytes); |
| 3992 | if (is_mmapped(oldp)) |
| 3993 | newp = mmap_resize(m, oldp, nb); |
| 3994 | else if (oldsize >= nb) { /* already big enough */ |
| 3995 | size_t rsize = oldsize - nb; |
| 3996 | newp = oldp; |
| 3997 | if (rsize >= MIN_CHUNK_SIZE) { |
| 3998 | mchunkptr remainder = chunk_plus_offset(newp, nb); |
| 3999 | set_inuse(m, newp, nb); |
| 4000 | set_inuse(m, remainder, rsize); |
| 4001 | extra = chunk2mem(remainder); |
| 4002 | } |
| 4003 | } |
| 4004 | else if (next == m->top && oldsize + m->topsize > nb) { |
| 4005 | /* Expand into top */ |
| 4006 | size_t newsize = oldsize + m->topsize; |
| 4007 | size_t newtopsize = newsize - nb; |
| 4008 | mchunkptr newtop = chunk_plus_offset(oldp, nb); |
| 4009 | set_inuse(m, oldp, nb); |
| 4010 | newtop->head = newtopsize |PINUSE_BIT; |
| 4011 | m->top = newtop; |
| 4012 | m->topsize = newtopsize; |
| 4013 | newp = oldp; |
| 4014 | } |
| 4015 | else if (!cinuse(next) && m->reallocfunc != NULL) { |
| 4016 | /* Get segment holding address `oldp' along with the previous segment */ |
| 4017 | msegmentptr prev_sp, sp; |
| 4018 | for (prev_sp = NULL, sp = &m->seg; sp->next != NULL; prev_sp = sp, sp = sp->next) { |
| 4019 | if ((char *)oldp >= sp->base && (char *)oldp < sp->base + sp->size) |
| 4020 | break; |
| 4021 | } |
| 4022 | |
| 4023 | // original base |
| 4024 | char *base = sp->base; |
| 4025 | // original size |
| 4026 | size_t size = sp->size; |
| 4027 | // 1st chunk in the segment |
| 4028 | mchunkptr p = align_as_chunk(base); |
| 4029 | // offset of base of the chunk to base of the segment |
| 4030 | size_t pofs = (char *)oldp - base; |
| 4031 | // offset of base of `top' to base of currently active segment |
no test coverage detected