Yes, we break that, uintptr_t preserves provenance in CHERI C. Doing anything else is basically impossible without really disgusting hacks, and would be contrary to the principles of CHERI. We see it as a feature not a bug that we break this, and in practice almost nothing relies on such horrible practices. Every pointer has a single source of provenance and it is never ambiguous (as would be the case when hacking to make it work, e.g. maintaining a table "somewhere" in the runtime that tracks all pointers that were cast to ints and then searching this table when casting back, but even that isn't entirely possible because there might be more than one pointer in the table that it could be). The rules in C are really only what they are today because uintptr_t
is defined as long
or equivalent on traditional architectures and they have to keep that working; you could introduce a new opaque integral type for uintptr_t
that has the same representation as long
but different semantics so you can track its provenance, but you can't retroactively change existing architectures to use a different type for uintptr_t
. That corner of the C standard does not make any sense in the context of CHERI and is not necessary for real-world C code, it's primarily just a side-effect of trying to retroactively invent semantics for uintptr_t that make the normal cases we do support work.