Unclear provenance warning

If you see a CHERI Clang/LLVM warning message like this:

binary expression on capability types 'uintptr_t'
(aka 'unsigned __intcap') and 'uintptr_t'; it is
not clear which should be used as the source of
provenance; currently provenance is inherited
from the left-hand side [-Wcheri-provenance]

then you probably have tried to compile code that looks something like this:

#include <stdint.h>

uintptr_t combine(uintptr_t a, uintptr_t b) {
  uintptr_t c;
  c = (a&b);
  return c;
}

The problem is that capability values a and b both have their own metadata, including bounds and validity tag bits. It is not clear how to combine these distinct capability metadata sets using the binary operation & (or any binary operation, for that matter).

In general, CHERI Clang takes the left-hand operand’s capability metadata (here, variable a) but the compiler emits a warning, which might be an error if you turn on the -Werror compile flag.

Avoiding this warning

The best way to avoid the warning is to consider whether the binary operation on capability values makes sense. It would be better to convert to a simple integer type and do the calculation in that (non-capability) domain instead as follows

#include <stdint.h>

uintptr_t combine(uintptr_t a, ptraddr_t b) {
  uintptr_t c;
  c = (a&b);
  return c;
}

where b is now a ptraddr_t which is a simple integer. When doing bitwise-and operation, a’s metadata will be retained.

If you do continue to use capabilities, break the complex calculation down into two-address style code with a combined assignment expression, for example:

#include <stdint.h>

uintptr_t combine(uintptr_t a, uintptr_t b) {
  uintptr_t c;
  c = a;
  c &= b;
  return c;
}

which does not trigger any compiler warnings. The c=a; assignment assigns a’s metadata to c. Then the c&=b retains c’s metadata and throws away b’s metadata.