This code writes a value through a pointer if one array is one past the end of another array.
#include <stdio.h>
#include <inttypes.h>
extern int first[], second[];
#define ADDR_AFTER(ptr) ((uintptr_t)((ptr) + 1))
int test(int *an_int) {
*second = 1;
if (ADDR_AFTER(first) == (uintptr_t)an_int) {
// ubsan does not like this.
*an_int = 2;
}
return *second;
}
int first[1] = {0}, second[1] = {0};
int main() {
if (ADDR_AFTER(first) == (uintptr_t)second) {
printf("test: %d\n", test(second));
printf("x: %d y: %d\n", *first, *second);
}
}
At no point do I directly compare two pointers to different objects (because I convert them to uintptr_t
first). I create a pointer to one-past-the-end of an array (which is legal), but I never dereference that pointer. As far as I can tell this should either print nothing, or print:
test: 2 x: 0 y: 2
Which is printed on Clang when optimization is -O1
or lower. At -O2
, however, it prints:
test: 1 x: 0 y: 2
With -O2 -fsanitize=undefined
it prints the this to stdout:
test: 2 x: 0 y: 2
and the following to stderr:
runtime error: store to address 0x000000cd9efc with insufficient space for an object of type 'int' 0x000000cd9efc: note: pointer points here 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
with a reference to the assignment to an_int
in test
. Is this actually undefined behavior, or is this a bug in Clang?