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

            Bug ID: 127925
           Summary: memcmp folding ignores scalar_storage_order of a
                    constant initializer
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kyuwoncho18 at gmail dot com
  Target Milestone: ---

godbolt: https://godbolt.org/z/5zP8oexda

GCC trunk miscompiles this at -O1 and above:

```c
#include <stdio.h>
#include <string.h>
typedef struct __attribute__((scalar_storage_order("big-endian"))) S { unsigned
int x; } S;
static const S s = { 0x11223344u };
static int f(const void *p) {
  return __builtin_memcmp(p, "\x11\x22\x33\x44", 4);
}
int main(void) {
  const unsigned char *p = (const unsigned char *)&s;
  printf("%02x%02x%02x%02x %d\n", p[0], p[1], p[2], p[3], f(p));
  return 0;
}
```
```console
$ gcc -O0 t.c && ./a.out
11223344 0
$ gcc -O2 t.c && ./a.out
11223344 1
```
Expected `11223344 0` at every level. `s.x` is big-endian, so `s` is stored as
the bytes `11 22 33 44`. GCC emits those bytes in `.rodata`, and the same
program prints them. `memcmp` against `"\x11\x22\x33\x44"` must then return 0.
Taking the address of a reverse-order struct is permitted, and the bytes are
only read as `unsigned char`, like `gcc.dg/sso/p1.c` does, and `gcc.dg/sso-7.c`
checks a reverse-order struct with `__builtin_memcmp` against a byte pattern.

`fold_const_call` folds the `memcmp` through `getbyterep`, which reaches
`constant_byte_string (..., valrep=true)`. That function encodes the
initializer with `native_encode_initializer`, in native (little-endian) order
`44 33 22 11`, and neither function checks `TYPE_REVERSE_STORAGE_ORDER`.
`fold_ctor_reference` and the `memcpy` folds in gimple-fold.cc already refuse
reverse-order aggregates. `__builtin_memchr (p, 0x11, 4)` is also folded
wrongly: it returns offset 3 instead of 0.

Fails with GCC 11.1, 12.1, 13.3, 14.1, 15.1 and trunk (17.0.0 20261015). GCC
10.3, which predates the value-representation folding of `memcmp`/`memchr`
added by r11-2709-g866626efd749ed (PR78257), returns 0 from the `memcmp`.

Disclaimer: This test case was generated by a fuzzer, and the report was
written with LLM assistance.

Reply via email to