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

--- Comment #13 from rguenther at suse dot de <rguenther at suse dot de> ---
On Tue, 24 Oct 2017, ch3root at openwall dot com wrote:

> I've also converted the testcase to allocated memory:
> 
> ----------------------------------------------------------------------
> #include <stdlib.h>
> #include <stdio.h>
> 
> __attribute__((__noinline__,__noclone__))
> void test(int *pi, long *pl, int k, int *pa)
> {
>   for (int i = 0; i < 3; i++) {
>     pl[k] = // something that doesn't change but have to be calculated
>     *pa; // something that potentially can be changed by assignment to *pi
>     *pi = 0;
>   }
> }
> 
> int main(void)
> {
>   int *pi = malloc(10);
>   int a = 1;
> 
>   test(pi, (void *)pi, 0, &a);
> 
>   printf("%d\n", *pi);
> }

Thanks for the unobfuscated testcase, this indeed shows exactly
the issue I mention (store motion sinking a store across another
store).  The *pa load prevents store-motion from also moving
the *pi store which would mitigate this issue (in a way earlier
fix we ensured the stores on exit are done in the original order).

Testcase for the testsuite that should fail on both big and little-endian:

__attribute__((__noinline__,__noclone__))
void test(__INT32_TYPE__ *pi, __INT64_TYPE__ *pl, int k, __INT32_TYPE__ 
*pa)
{
  for (int i = 0; i < 3; i++) {
      pl[k] = *pa;
      *pi = 1;
  }
}

int main()
{
  __INT32_TYPE__ *pi = __builtin_malloc (10);
  __INT32_TYPE__ a = 2;

  test(pi, (void *)pi, 0, &a);

  if (*pi != 1)
    __builtin_abort ();
  return 0;
}

Reply via email to