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).