Issue 60596
Summary [clang] Taking address of unreachable function can be used to obtain identical integers that compare unequal
Labels new issue
Assignees
Reporter SvizelPritula
    Using `__builtin_unreachable`, it's possible to create a function `a` that compiles to zero assembly instructions, like this:

```c
void a() {
 __builtin_unreachable();
}

void b() {}
```

With `-O1` or higher this compiles to:

```as
a:
b:
 ret
```

The function `a` is pretty useless, since calling it will unconditionally result in undefined behaviour. It is, however, possible to take its address, like this:

```c
#include <stdlib.h>
#include <stdio.h>

void a() {
    __builtin_unreachable();
}

void b() {}

int main() {
    size_t ap = (size_t) a;
    size_t bp = (size_t) b;

    printf("%zu %zu %d\n", ap, bp, ap == bp);
}
```

Executing this will reveal that `ap` and `bp` have identical values, since `a` and `b` have the same address. However, it will also show that `ap == bp` is false, which contradicts that.

My guess is that some optimization pass assumes that different functions have different addresses, which is required by the  C standard.

This bug is unlikely to happen in real programs, since:
a) few programs have functions that have unconditionally undefined behaviour,
b) even fewer programs will take the address of such a function, and
c) fewer still programs compare function pointers.

`__builtin_unreachable` can also be replaced by other statements with undefined behaviour, such as `for (int i=0; i>=0; i++);`.

Tested with `clang` and `clang++` 15.0.7 with an optimization level of 1.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to