C++ Logo

std-discussion

Advanced search

Schrödinger's UB

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Sat, 3 Dec 2022 11:56:04 +0000
Hi,

Consider the following program:

```
void foo(int, int) {}

int main() {
  int i;
  foo(i=0, i=1);
  if (i == 1) {
    *(int*)nullptr = 42;
  }
}
```

As the evaluation order of function arguments is unspecified, this
program has two possible executions, where `i` ends up with the value 0
or 1 after the call to `foo`.

As one of the executions has undefined behavior, the program simply has
undefined behavior [1]. So far so good, I'm OK with this.

Now consider adding input to the same program:

```
#include <iostream>

void foo(int, int) {}

int main() {
  int i;
  foo(i=0, i=1);
  int j;
  std::cin >> j;
  if (i != j) {
    *(int*)nullptr = 42;
  }
}
```

Here at first sight the user has a chance to guess which execution
happens, but it has no way to observe it. This doesn't matter, whatever
is the input, there is a possible execution the invokes UB, so this is
still UB. This is still covered by the wording of [1]. I'm OK with this
as well.

Now consider a case where a user can observe which execution happens
before providing the input.

```
#include <iostream>

void foo(int, int) {}

int main() {
  int i;
  foo(i=0, i=1);
  int j;
  std::cout << "% Type " << j << " to not invoke UB" << std::endl;
  std::cin >> j;
  if (i != j) {
    *(int*)nullptr = 42;
  }
}
```

Here I assume that cout and cin form an "interactive device" outlined
at [2].

Consider this execution:

```
$ ./a.out
% Type 0 to not invoke UB
0
```

I don't think that [1] makes an allowance for an execution like this
not to be UB, as it has no regard for the output of the program at all.
Since there are executions of the program with input '0' that invoke
undefined operations, this is still UB.

It would make sense to define the behavior of executions like this.
The set of possible executions gets narrowed down with observed
outputs of the program, and it doesn't make sense to treat inputs that
are provided after these outputs as if they were provided ahead of
even starting the program. Is this a defect?

[1] https://timsong-cpp.github.io/cppwp/n4868/intro.abstract#5.sentence-2
[2] https://timsong-cpp.github.io/cppwp/n4868/intro.abstract#6.3

Cheers,
Lénárd

Received on 2022-12-03 11:56:13