CTSRD-CHERI / clang

DO NOT USE. Use llvm-project instead
Other
9 stars 8 forks source link

Compiler crash via cast #154

Closed dstolfa closed 7 years ago

dstolfa commented 7 years ago

It would seem like the following code triggers a clang crash:

int
main(void)
{
        unsigned long foo[8];
        int * __capability yc;

        ((int * __capability *)foo)[0] = yc;
        return (0);
}

The output of the crash is the following:

clang version 5.0.0 (https://github.com/CTSRD-CHERI/clang.git a096992b7f6b044ba0dea832bfbc39df9f645020) (https://github.com/CTSRD-CHERI/llvm.git 8339c8e9bb939bdd8d08793c9fd870772a17b59c)
Target: cheri-unknown-freebsd
Thread model: posix
InstalledDir: /home/ds815/cheri/output/sdk256//bin
 "/home/ds815/cheri/output/sdk256/bin/clang-5.0" -cc1 -triple cheri-unknown-freebsd -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name test.c -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -masm-verbose -mconstructor-aliases -target-cpu cheri -target-abi n64 -mfloat-abi hard -v -dwarf-column-info -debugger-tuning=gdb -resource-dir /home/ds815/cheri/output/sdk256/lib/clang/5.0.0 -isysroot /home/ds815/cheri/output/sdk256/sysroot -fdebug-compilation-dir /home/ds815 -ferror-limit 19 -fmessage-length 547 -fobjc-runtime=gnustep -fdiagnostics-show-option -fcolor-diagnostics -cheri-linker -o /tmp/test-5aef30.o -x c test.c
clang -cc1 version 5.0.0 based upon LLVM 5.0.0svn default target cheri-unknown-freebsd
#include "..." search starts here:
#include <...> search starts here:
 /home/ds815/cheri/output/sdk256/lib/clang/5.0.0/include
 /home/ds815/cheri/output/sdk256/sysroot/usr/include
End of search list.
fatal error: error in backend: Cannot select: 0x805eb0548: ch = store<ST16[%7](align=8), trunc to i128> 0x805eb0270:1, 0x805eb04e0, FrameIndex:i64<1>, undef:i64
  0x805eb04e0: iFATPTR = srl 0x805eb0270, Constant:i32<128>
    0x805eb0270: iFATPTR,ch = load<LD32[%3](dereferenceable)> 0x805eb01a0, FrameIndex:i64<2>, undef:i64
      0x805eb0208: i64 = FrameIndex<2>
      0x805eb0138: i64 = undef
    0x805eb00d0: i32 = Constant<128>
  0x805eb02d8: i64 = FrameIndex<1>
  0x805eb0138: i64 = undef
In function: main
clang-5.0: error: clang frontend command failed with exit code 70 (use -v to see invocation)
clang version 5.0.0 (https://github.com/CTSRD-CHERI/clang.git a096992b7f6b044ba0dea832bfbc39df9f645020) (https://github.com/CTSRD-CHERI/llvm.git 8339c8e9bb939bdd8d08793c9fd870772a17b59c)
Target: cheri-unknown-freebsd
Thread model: posix
InstalledDir: /home/ds815/cheri/output/sdk256//bin
clang-5.0: note: diagnostic msg: PLEASE submit a bug report to http://llvm.org/bugs/ and include the crash backtrace, preprocessed source, and associated run script.
clang-5.0: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang-5.0: note: diagnostic msg: /tmp/test-0c8e36.c
clang-5.0: note: diagnostic msg: /tmp/test-0c8e36.sh
clang-5.0: note: diagnostic msg:

********************
davidchisnall commented 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.

davidchisnall commented 7 years ago

Note: It appears that this is only triggered for L-value casts.

arichardson commented 7 years ago

I think the problem is that yc is uninitialized and undef capability values cause all sorts of weird errors.

davidchisnall commented 7 years ago

@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 #includes before submitting reduce test cases. They are very unhelpful for debugging.

dstolfa commented 7 years ago

@davidchisnall Done. Sorry about that.

davidchisnall commented 7 years ago

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.

davidchisnall commented 7 years ago

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.

khilangudka commented 7 years ago

Here is a very reduced test case:

int main(void) {
  unsigned long foo[8];
  ((int * __capability *)foo)[0] = 0;
  return 0;
}
davidchisnall commented 7 years ago

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.

arichardson commented 7 years ago

@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

khilangudka commented 7 years ago

This is fixed in ac3493133e.