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

--- Comment #7 from Sergei Trofimovich <slyfox at gcc dot gnu.org> ---
(In reply to qinzhao from comment #6)
> (In reply to Sergei Trofimovich from comment #3)
> > (In reply to qinzhao from comment #2)
> > > could you please reduce the testing case to help me debug?
> > 
> > Will do. Might take some time as I'm not very familiar with `file` code 
> > base.
> 
> Thanks a lot. will you use C-reduce to reduce the testing case?
> I tried your instructions in the Description part to 
> git clone, autoreconf -ivf, these have no issues, but when make

I'm afraid I reduce wrong-code manually to make sure transformations are not
too bad.

> [opc@qinzhao-ol8u3-x86 file]$ make
> make: *** No targets specified and no makefile found.  Stop.
> 
> did I do anything wrong?

I missed a few crucial steps like default CFLAGS. My apologies. Here is more
isolated example instead. I'm a bit more confident it's gcc's problem of
inferring wrong target object size after some optimization. It still needs
glibc, but if you would not be able to reproduce I'll preprocess it as well (I
suspect memcpy() macro is crucial there).

The example:

// $ cat apprentice.c
// $
/nix/store/925dmxv72ap648ipwnswz5lx4j8xp11d-gcc-wrapper-16.0.0.99999999/bin/gcc
-D_FORTIFY_SOURCE=3 apprentice.c -O1 -o bug && ./bug
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

struct magic_ {
        char unused[9]; // at least 9
};

struct magic_map {
        struct magic_ *magic[1];
};

static int coalesce_entries(struct magic_ **ma)
{
        uint32_t i, mentrycount = 0;
        size_t slen;

        for (i = 0; i < 1; i++) {
                mentrycount += 1;
        }

        slen = sizeof(**ma) * mentrycount;
        *ma = malloc(slen);

        mentrycount = 0;
        for (i = 0; i < 1; i++) {
                char b[1024] = {};
                (void)memcpy(*ma + mentrycount, b,
                    1 * sizeof(**ma));
                mentrycount += 1;
        }
        return 0;
}

__attribute__((noipa))
static void pin_pointer(void *){}

__attribute__((noipa))
static int some_value(void){ return 1; }

__attribute__((optimize(1))) // (2) makes it disappear
__attribute__((noipa))
static struct magic_map *
apprentice_load(void)
{
        char buf[128]; // did not shrink, but needs to be more than 100
        struct magic_map *map2;

        map2 = calloc(1, sizeof(*map2));

        pin_pointer(&buf);
        if (some_value() == 42) {
          // does not really execute, but needed for complex control flow
                goto out;
        }

  coalesce_entries(&map2->magic[0]);
  pin_pointer(map2);

out:
        return map2;
}

int main() {
        apprentice_load();
}

Crashing:

$ gcc/xgcc -Bgcc -D_FORTIFY_SOURCE=3 -O1  apprentice.c  -o bug && ./bug
In file included from /usr/include/string.h:548,
                 from apprentice.c:4:
In function 'memcpy',
    inlined from 'coalesce_entries' at apprentice.c:30:9,
    inlined from 'apprentice_load' at apprentice.c:59:3:
/usr/include/bits/string_fortified.h:29:10: warning: '__builtin___memcpy_chk'
writing 9 bytes into a region of size 8 overflows the destination
[-Wstringop-overflow=]
   29 |   return __builtin___memcpy_chk (__dest, __src, __len,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   30 |                                  __glibc_objsize0 (__dest));
      |                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
*** buffer overflow detected ***: terminated
Aborted (core dumped)

Compiler details:

$ gcc/xgcc -Bgcc -v
Reading specs from gcc/specs
COLLECT_GCC=gcc/xgcc
COLLECT_LTO_WRAPPER=gcc/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /home/slyfox/dev/git/gcc/configure --disable-multilib
--disable-bootstrap --disable-lto --disable-libsanitizer --enable-languages=c
CFLAGS='-O1 -g0' CXXFLAGS='-O1 -g0' LDFLAGS='-O1 -g0'
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 16.0.0 20250702 (experimental) (GCC)

Reply via email to