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

            Bug ID: 85800
           Summary: A miscompilation bug with unsigned char
           Product: gcc
           Version: 7.3.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: juneyoung.lee at sf dot snu.ac.kr
  Target Milestone: ---

Created attachment 44136
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44136&action=edit
A source file that raises the bug.

```
$ cat test-main.c
#include <string.h>
#include <stdio.h>
#include <stdint.h>

// If f(A, B + 4) is given, and integer representation of A and B + 4
// are the same, c1 == c2 in the loop becomes true,
// so arr3 = arr1. Hence r = A, and *A should be 10.
// However, if compiled with -O3, *A is still 1.
void store_10_to_p(int *p, int *q) {
  unsigned char arr1[8];
  unsigned char arr2[8];
  unsigned char arr3[8];
  // Type punning with char* is allowed.
  memcpy((unsigned char*)arr1, (unsigned char *)&p, sizeof(p));
  memcpy((unsigned char*)arr2, (unsigned char *)&q, sizeof(q));
  // Now arr1 is p, arr2 is q.

  for (int i = 0; i < sizeof(q); i++) {
    int c1 = (int)arr1[i], c2 = (int)arr2[i];
    // Note that c1 == c2 is a comparison between _integers_ (not pointers).
    if (c1 == c2)
      // Always true if p and q have same integer representation.
      arr3[i] = arr1[i];
    else
      arr3[i] = arr2[i];
  }
  // Now arr3 is equivalent to arr1, which is p.
  int *r;
  memcpy(&r, (unsigned char *)arr3, sizeof(r));
  // Now r is p.
  *p = 1;
  *r = 10;
}

int main() {
  int B[4], A[4];
  printf("%p %p\n", A, &B[4]);
  store_10_to_p(A, &B[4]);
  printf("%d\n", A[0]);
  return 0;
}
$ gcc -O3 -o test-main test-main.c
$ ./test-main
0x7fffffffe5a0 0x7fffffffe5a0
1
$ gcc -O0 -o test-main test-main.c
$ ./test-main
0x7fffffffe5b0 0x7fffffffe5b0
10
```

The output should be 10 because the integral representation of A and B[4] are
the same, but compiling with -O3 gives 1.

Reply via email to