Closed dstolfa closed 7 years ago
Test case:
int
main(void)
{
unsigned long foo[8];
int * __capability yc;
((int * __capability *)foo)[0] = yc;
return (0);
}
The error is apparent in the generated IR:
%1 = bitcast i64* %arraydecay to i32 addrspace(200)**
The issue appears to be in the handling of the C-style cast expression. In the AST dump, this appears as:
`-CStyleCastExpr 0x7f8516887698 <col:10, col:32> 'int * __capability *' <BitCast>
`-ImplicitCastExpr 0x7f8516887680 <col:32> 'unsigned long *' <ArrayToPointerDecay>
`-DeclRefExpr 0x7f85168875d0 <col:32> 'unsigned long [8]' lvalue Var 0x7f8516887460 'foo' 'unsigned long [8]'
Note the BitCast
in the CStyleCastExpr
. This should be a capability cast, not a bitcast.
Note: It appears that this is only triggered for L-value casts.
I think the problem is that yc is uninitialized and undef
capability values cause all sorts of weird errors.
@RichardsonAlex I don't think so. The same crash applies if you initialise yc, and the AST doesn't know about any of the value and is wrong.
@dstolfa Please can you remove any #include
s before submitting reduce test cases. They are very unhelpful for debugging.
@davidchisnall Done. Sorry about that.
Ooops, I misread the IR:
%1 = bitcast i64* %arraydecay to i32 addrspace(200)**
This is valid, because it's an AS0 pointer to an AS200 pointer in the destination, so this is correct.
The underlying issue appears to be that this code is attempting to store a capability in insufficiently-aligned memory. The store ends up being a capability store to 8-byte-aligned memory:
store i32 addrspace(200)* %0, i32 addrspace(200)** %arrayidx, align 8
This is invalid. We should probably turn the existing warning for under-aligned stores into a hard error if the thing being stored is a capability.
Here is a very reduced test case:
int main(void) {
unsigned long foo[8];
((int * __capability *)foo)[0] = 0;
return 0;
}
Yup. We should probably have an error, but the test cases are all undefined behaviour according to the C spec and so it is completely valid for the compiler to crash, or to cause monkeys to fly out of the nose of the person who wrote the code in the first place.
@dstolfa If you have a bigger test case and removing the #includes
is more tricky you can use $LLVM_BUILD_DIR/creduce_crash_testcase.py /tmp/crash-reproducer.sh
This is fixed in ac3493133e.
It would seem like the following code triggers a clang crash:
The output of the crash is the following: