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

--- Comment #18 from Alexander Cherepanov <ch3root at openwall dot com> ---
A bit simplified variant:

#include <stdio.h>

int main()
{
   int x, y = 1;
   int *volatile v;
   int *p;

   v = &y;
   p = v;
   if (p == &x + 1) {
     *p = 2;
     printf("y = %d\n", y);
   }
}

077t.alias dump shows such "Points-to sets" (among others):

v = { y }
p_5 = { y } same as v

and then the code:

   <bb 3>:
   *p_5 = 2;
   y.0_7 = y;
   printf ("y = %d\n", y.0_7);

Seems right.

081t.vrp1 dump shows such "Value ranges after VRP":

p_11: [&MEM[(void *)&x + 4B], &MEM[(void *)&x + 4B]]  EQUIVALENCES: { 
p_5 } (1 elements)

and the code:

   <bb 3>:
   MEM[(int *)&x + 4B] = 2;
   y.0_7 = y;
   printf ("y = %d\n", y.0_7);

Seems wrong.

gcc 5.2.0

On 2015-11-16 01:30, ch3root at openwall dot com wrote:
> I guess it depends on the transitivity of the == operator. After this bug is
> fixed it will be possible to constuct a third pointer r from two pointer p and
> q such that r == p and r == q but p != q. For p and q take &x + 1 and &y as
> above, obtain r by stripping provenance info from p or q (e.g. by printf/scanf
> with %p).

This bug turned out to be not that tricky after all. The program:

#include <stdio.h>

int main()
{
   int x, y;
   void *p = &x + 1, *q = &y, *r;

   /* Strip p of provenance info */
   /* To simplify testing: */
   char s[100]; sprintf(s, "%p", p); sscanf(s, "%p", &r);
   /* Instead, imagine this:
   printf("%p or %p? ", p, q); scanf("%p", &r);
   */

   char *eq[] = {"!=", "=="};
   printf("r %s p, r %s q, p %s q\n", eq[r == p], eq[r == q], eq[p == q]);
}

prints "r == p, r == q, p != q" and the first two equalities are 
essentially mandated by C11 (unless you patch it by making one of them UB).

Reply via email to