[llvm] [llvm] Improve llvm.objectsize computation by computing GEP, alloca a… (PR #117849)

Martin Storsjö via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 18 01:48:09 PST 2024


mstorsjo wrote:

This causes some cases of buffer overflow checks to fail - we ran into this in https://github.com/llvm/llvm-test-suite/pull/188.

I've managed to reduce the issue down to a small standalone reproducer:
```c
void *checkasm_check_func(void *func, const char *name, ...);
void randomize_loopfilter_buffers(int lineoff, int str,
                                         int dir, int flim_E, int flim_I,
                                         int hev_thresh, unsigned char *buf,
                                         int force_hev);
void fill_loopfilter_buffers(unsigned char *buf, int stride, int w, int h);
void func(void *ptr);

#define memcpy(dst, src, n) __builtin___memcpy_chk((dst), (src), (n), __builtin_object_size((dst), 0))

void check_loopfilter_16y(void)
{
    unsigned char base0[32 + 16 * 16];
    unsigned char base1[32 + 16 * 16];
    int dir, edge, force_hev;
    int flim_E = 20, flim_I = 10, hev_thresh = 7;

    for (dir = 0; dir < 2; dir++) {
        int midoff = dir ? 4 * 16 : 4;
        int midoff_aligned = dir ? 4 * 16 : 16;
        unsigned char *buf0 = base0 + midoff_aligned;
        unsigned char *buf1 = base1 + midoff_aligned;
        for (edge = 0; edge < 2; edge++) {
            if (checkasm_check_func(func, "vp8_loop_filter16y")) {
                for (force_hev = -1; force_hev <= 1; force_hev++) {
                    fill_loopfilter_buffers(buf0, 16, 16, 16);
                    randomize_loopfilter_buffers(0, 16, dir, flim_E, flim_I, hev_thresh, buf0, force_hev);
                    memcpy(buf1 - midoff, base0, 16 * 16);
                    func(buf1 - midoff);
                }
            }
        }
    }
}
```

If we compile this with e.g. `clang --target=aarch64-linux-gnu -O2 repro.c -S -o -` before this change, the whole `memcpy` and `__builtin_memcpy_chk` gets expanded into an inline memcpy with no call to `__memcpy_chk`.

After this change, we instead get this:
```
        add     x0, x23, x22
        add     x1, sp, #296
        mov     w2, #256                        // =0x100
        mov     x3, xzr
        bl      __memcpy_chk
```
Parameter `x3` here is the buffer size parameter to `__memcpy_chk`, which gets passed as zero - i.e. we're doing memcpy to a zero byte output buffer, which will fail as soon as we're copying more than zero bytes into it.

The same reproduces for `arm64-apple-darwin` and `x86_64-linux-gnu` too, and presumably any target, just pick whichever you're most comfortable with reading :-)

Can we revert this until this issue is fixed?

https://github.com/llvm/llvm-project/pull/117849


More information about the llvm-commits mailing list