Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Hey, it actually works!

    int main() {
        int tobias[24] = {0,0,33};
        delete(tobias+4);
    }
Compile and run on Ubuntu 20.04 (may work on other Linuxes), no errors, no warnings, runs perfectly fine.

Bonus fun: try printing out the address of `tobias` and `new int[6]` afterwards :)



I assume you have it on x86_64. I'm trying to make sense of that according to glibc implementation details[1] and Sys V/Itanium ABI.

Default new and delete just use malloc/free.

First 4 ints are interpreted as prev_size and size. prev_size is 0. 33 is 0b10001, size is 32 (bytes, so 8 ints), AMP is 0b001, so not in arena (default sbrk heap, I assume), not mmap'd, prev is used.

I didn't follow how the internal bookkeeping will be updated, but I assume 8 size chunk will be immediately reused on a following `new int[6]`.

Obviously don't write code like this.

[1] https://sourceware.org/glibc/wiki/MallocInternals


Essentially correct. 33 sets up the pointer to appear to glibc as if it were a small, “normal” 32-byte allocation. The default behavior for glibc free() with a small allocation size will be to put it into the thread cache (tcache), which makes it immediately available to be reused by the same thread.

Although you should obviously never write code like this by yourself, understanding weird details like this is very helpful when exploiting memory error bugs in software, as it lets you understand how precisely to subvert the memory allocator to give you access to desired parts of memory.


Weird that undefined behaviour is undefined.

Undefined behaviour is no joke.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: