-
Notifications
You must be signed in to change notification settings - Fork 0
Warning description
Not capability-aligned pointer cast to pointer to capability-aligned type.
Example:
typedef struct S_t {
/* other fields */
double f[1]; // aligned to 8-byte boundary
} S;
void foo(int n) {
S* p = malloc(sizeof(S) + (n-1)*sizeof(double) + n*sizeof(T*));
/* 1. &p->f[n] is 8-bytes aligned
* 2. T** type requires 16-byte alignment
*/
T** t = (T**)&p->f[n];
}
Warning message:
Pointer value aligned to a 8 byte boundary cast to type 'T * __capability * __capability' with 16-byte capability alignment
Underaligned pointer value assigned to a pointer that must be capability-aligned.
Example:
uint8_t extra[100]; // aligned to 1-byte boundary
void alloc(void** pp) {
*pp = &extra[0]; // assign
}
intptr_t *foo(void) {
intptr_t *cp; // requires 16-byte alignment
alloc((void**)&cp); // cp initialised with underaligned value
return cp;
}
Warning message:
Pointer value aligned to a 1 byte boundary stored as value of type 'intptr_t * __capability'. Memory pointed by it is supposed to hold capabilities, for which 16-byte capability alignment will be required
This checker assumes that void*
fields and global variables are intended to hold pointers to arbitrary data, potentially including capability-containing objects.
Assigning an address of an underaligned allocation to such variable is reported (unless this allocation is already initialized).
Example:
struct S {
void *p; // *p may be used to hold capabilities
};
uint8_t extra[100]; // aligned to 1-byte boundary
void foo(struct S *pS) {
pS->p = &extra[0]; // assigning underaligned allocation to void* field
}
Warning message:
Pointer value aligned to a 1 byte boundary stored as value of type 'void * __capability'. Memory pointed by it may be used to hold capabilities, for which 16-byte capability alignment will be required
Example:
uint8_t extra[100]; // aligned to 1-byte boundary
void foo(intptr_t *pCap, int n) {
memcpy(extra, pCap, n * sizeof(intptr_t));
}
Warning message:
Copied memory object pointed by 'intptr_t * __capability' pointer contains capabilities that require 16-byte capability alignment. Destination address alignment is 1. Storing a capability at an underaligned address leads to tag stripping.
Example:
char *foo(char *a, unsigned x) {
intptr_t ip = ((ptrdiff_t)a | (intptr_t)x); // ip derived from x
char *p = (char*) ip; // p is not a valid pointer
return p;
}
Warning message:
NULL-derived capability used as pointer
Similar to previous warning, but with immediate integer->(u)intptr_t
->pointer conversion. This is usually intentional.
Example:
void* foo(unsigned x) {
void *q = (void*)(uintptr_t)x; // q is not a valid pointer
}
Warning message:
cheri_no_provenance capability used as pointer
Example:
intptr_t cmp1 (char *e0, char *e1) {
intptr_t x = (intptr_t)e0 ^ (intptr_t)e1; // single-provenance rule violated
return x & (cmp(e0, e1) >> 31); // x is not a valid capability
}
Clang warning:
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
CSA-warning:
Result of '^' on capability type 'unsigned __intcap'; it is unclear which side should be used as the source of provenance. Note: along this path, LHS and RHS were derived from pointers. Result capability will be derived from LHS by default. This code may need to be rewritten for CHERI.
Example:
uintptr_t foo(unsigned d, char *p) {
uintptr_t a = d; // NULL-derived
uintptr_t b = (uintptr_t)p;
uintptr_t s = a + b; // s is derived from a
return s;
}
Clang warning:
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
CSA-warning:
Result of '+' on capability type 'unsigned __intcap'; it is unclear which side should be used as the source of provenance. Note: along this path, LHS was derived from NULL, RHS was derived from pointer. Currently, provenance is inherited from LHS, therefore result capability will be invalid
Example:
uintptr_t align_down(void *p, size_t a) {
uintptr_t sz = (uintptr_t)p;
uintptr_t m = a - 1;
return (sz & ~m);
}
Clang warning:
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
CSA-warning:
Result of '&' on capability type 'unsigned __intcap'; it is unclear which side should be used as the source of provenance; consider indicating the provenance-carrying argument explicitly by casting the other argument to 'size_t'. Note: along this path, LHS was derived from pointer, RHS was derived from NULL
Capability-unaware implementation of data copying routines.
Example:
static void swapfunc(void *a, void *b, int n) {
long i = n;
char *pi = (char *)(a);
char *pj = (char *)(b);
/* if *a or *b is a capability, it will lose the tag after swap */
do {
char t = *pi;
*pi++ = *pj;
*pj++ = t;
} while (--i > 0);
}
Warning message:
Tag-stripping store of a capability
Individual bytes of a capability are used in arithmetic. This may be an indication of using pointer values to compute hash value or for the similar purposes. It's recommended to extract address value from a capability and use it instead for the sake of performance.
Example:
int hash(void *key0, size_t len) {
char *k = key0;
int h = 0;
while (len--)
h = (h << 5) + *k++;
return h;
}
int ptr_hash(void) {
int *p = &x;
return hash(&p, sizeof(int*));
}
Warning message:
Part of capability representation used as argument in binary operator