https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96503

nrk at disroot dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |nrk at disroot dot org

--- Comment #9 from nrk at disroot dot org ---
This bug is particularly nasty when you have `alloc` and `resize` and the
`alloc` call retains the `alloc_size` information but the `resize` call gets
inlined (thus losing the new `alloc_size`) and now you're left with a pointer
that GCC thinks has the *old* size.

Here's a minimal demo:

        static int *arena;

        __attribute(( malloc, alloc_size(1), noinline ))
        static void *alloc(int size) { return arena++; }

        //__attribute((noinline))
        __attribute(( alloc_size(2) ))
        static void *extend(void *oldptr, int newsize) { ++arena; return
oldptr; }

        #include <stdlib.h>
        int main(void)
        {
                arena = malloc(4 * sizeof(int));
                if (!arena) abort();

                int *a = alloc(sizeof *a);
                a[0] = 4;
                a = extend(a, sizeof *a * 2);
                a[1] = 8;
                return a[1];
        }

(The `alloc` and `resize` function in practice is more sophisticated, but the
above suffices for demo purposes).

Compile with `gcc -O2 -fsanitize=address,undefined` and the `a[1]` will trigger
UBSan because it's still operating on the old size information. Uncommenting
the `noinline` from extend() "fixes" the issue.

But littering the allocation routines with `noinline` is not really a good idea
since it'd regress performance for custom allocators that have trivial logic
(e.g bump allocators).

This bug unfortunately makes the `alloc_size` attribute unusable for my
purposes.

Reply via email to