On CHERI, and thus Arm's Morello prototype, pointers are implemented as hardware capabilities which, as well as having a normal integer address, have additional bounds, permissions and other metadata in a second word. In order to preserve this metadata, uintptr_t is also implemented as a capability, not a plain integer, which causes problems for binary operators, as the metadata preserved in the output can only come from one of the inputs. In most cases this is clear, as normally at least one operand is provably a plain integer, but if both operands are uintptr_t and have no indication they're just plain integers then it is ambiguous, and the current implementation will arbitrarily, but deterministically, pick the left-hand side, due to empirical evidence that it is more likely to be correct. In this instance, both operands are of type uintptr_t, with one being a function argument and one being cast from a pointer, so both could be valid pointers. Moreover, the left-hand side is not the actual pointer. This means that, currently, the code when run on a CHERI architecture will preserve the metadata from the integer, i.e. an invalid capability that will trap on deference, and not the pointer. This can be addressed by changing the type of the function argument in order to more clearly convey intent, both to the compiler so it knows to generate the right code but also to the developer so it's clear that the argument is not in fact a pointer but just a plain integer (in this case being either APPLY_SYMLINK_GOES_AWAY or APPLY_SYMLINK_IN_RESULT). Signed-off-by: Jessica Clarke <jrtc27@xxxxxxxxxx> --- apply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apply.c b/apply.c index fed195250b..7c7d56cacb 100644 --- a/apply.c +++ b/apply.c @@ -3814,7 +3814,7 @@ static int check_to_create(struct apply_state *state, static uintptr_t register_symlink_changes(struct apply_state *state, const char *path, - uintptr_t what) + size_t what) { struct string_list_item *ent; @@ -3823,7 +3823,7 @@ static uintptr_t register_symlink_changes(struct apply_state *state, ent = string_list_insert(&state->symlink_changes, path); ent->util = (void *)0; } - ent->util = (void *)(what | ((uintptr_t)ent->util)); + ent->util = (void *)((uintptr_t)what | ((uintptr_t)ent->util)); return (uintptr_t)ent->util; } -- 2.33.1