I don't think that works. Consider the following (contrived) program:
char* q[1] = {0};
int iq = (uintptr_t)q;
int ip = 0;
while (iq>0) {
iq--;
ip++;
}
char* p = (char*) ip;
You can make this more efficient (albeit no less contrived) by iterating through iq bit-wise.
Less contrived would be sending a pointer through some IPC mechanism (allowing it to be used as an opaque handle externally, while the program will blindly dereference it when it is passed back in); or even passing it within a program across compilation units.
If you treat provenance like a taint, you need to track every way it could be propagated, and that does not seem solvable.
So what are the optimizations here? iq is tainted, you can't hoist the loop out. You've said "I'm doing a weird thing here with an integer which used to be a pointer, you have to assume that it involves memory and treat it more like a pointer than an integer"
Less contrived would be sending a pointer through some IPC mechanism (allowing it to be used as an opaque handle externally, while the program will blindly dereference it when it is passed back in); or even passing it within a program across compilation units.
If you treat provenance like a taint, you need to track every way it could be propagated, and that does not seem solvable.