trailofbits / vast

VAST is an experimental compiler pipeline designed for program analysis of C and C++. It provides a tower of IRs as MLIR dialects to choose the best fit representations for a program analysis or further program abstraction.
https://trailofbits.github.io/vast/
Apache License 2.0
381 stars 23 forks source link

[Bug]: Verifier fails to verify subscript expressions when index operand is an enum type #648

Open PappasBrent opened 2 months ago

PappasBrent commented 2 months ago

VAST version

Ubuntu clang version 18.1.8 (++20240615103753+3b5b5c1ec4a3-1~exp1~20240615223858.136) Target: x86_64-pc-linux-gnu Thread model: posix

LLVM version

18.1.8

Operating system

Ubuntu 22.04.4 LTS x86_64

Description

The VAST codegen module verifier fails to verify subscript expressions when the index operand is an enum value. I receive the following error:

loc("test_subscript_enum_verify.c":6:12): error: 'hl.subscript' op operand #1 must be integer like type, but got '!hl.elaborated<!hl.enum<"FOO">>'
[VAST fatal] codegen: module verification error before running vast passes
PLEASE submit a bug report to https://github.com/trailofbits/vast/issues and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: ./builds/default/tools/vast-front/Debug/vast-front -x c -vast-emit-mlir=hl test_subscript_enum_verify.c
1.      <eof> parser at end of file
 #0 0x00007f424c776716 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/usr/lib/llvm-18/lib/libLLVM.so.18.1+0xd94716)
 #1 0x00007f424c7746d0 llvm::sys::RunSignalHandlers() (/usr/lib/llvm-18/lib/libLLVM.so.18.1+0xd926d0)
 #2 0x00007f424c6c61f0 (/usr/lib/llvm-18/lib/libLLVM.so.18.1+0xce41f0)
 #3 0x00007f424b464520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x000055b0250b9ed3 vast::cg::driver::finalize() /home/bpappas/github.com/trailofbits/vast/lib/vast/CodeGen/CodeGenDriver.cpp:76:17
 #5 0x000055b0250b1626 vast::cc::vast_consumer::HandleTranslationUnit(clang::ASTContext&) /home/bpappas/github.com/trailofbits/vast/lib/vast/Frontend/Consumer.cpp:67:5
 #6 0x000055b0250b1ea7 vast::cc::vast_stream_consumer::HandleTranslationUnit(clang::ASTContext&) /home/bpappas/github.com/trailofbits/vast/lib/vast/Frontend/Consumer.cpp:125:15
 #7 0x00007f4253b90fc6 clang::ParseAST(clang::Sema&, bool, bool) (/usr/lib/llvm-18/lib/libclang-cpp.so.18.1+0xb7ffc6)
 #8 0x000055b024c86fd5 vast::cc::vast_stream_action::ExecuteAction() /home/bpappas/github.com/trailofbits/vast/lib/vast/Frontend/Action.cpp:75:5
 #9 0x00007f42559c1ab5 clang::FrontendAction::Execute() (/usr/lib/llvm-18/lib/libclang-cpp.so.18.1+0x29b0ab5)
#10 0x00007f425593b084 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/usr/lib/llvm-18/lib/libclang-cpp.so.18.1+0x292a084)
#11 0x000055b024c6eee7 vast::cc::execute_compiler_invocation(clang::CompilerInstance*, vast::cc::vast_args const&) /home/bpappas/github.com/trailofbits/vast/tools/vast-front/compiler_invocation.cpp:101:28
#12 0x000055b024c835e0 vast::cc::cc1(vast::cc::vast_args const&, llvm::ArrayRef<char const*>, char const*, void*) /home/bpappas/github.com/trailofbits/vast/tools/vast-front/cc1.cpp:116:23
#13 0x000055b024c74614 execute_cc1_tool(llvm::SmallVectorImpl<char const*>&) /home/bpappas/github.com/trailofbits/vast/tools/vast-front/driver.cpp:71:16
#14 0x000055b024c7f5ed int llvm::function_ref<int (llvm::SmallVectorImpl<char const*>&)>::callback_fn<int (*)(llvm::SmallVectorImpl<char const*>&)>(long, llvm::SmallVectorImpl<char const*>&) /usr/lib/llvm-18/include/llvm/ADT/STLFunctionalExtras.h:45:5
#15 0x00007f42555f35c9 (/usr/lib/llvm-18/lib/libclang-cpp.so.18.1+0x25e25c9)
#16 0x00007f424c6c5f8c llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/usr/lib/llvm-18/lib/libLLVM.so.18.1+0xce3f8c)
#17 0x00007f42555f2f5e clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (/usr/lib/llvm-18/lib/libclang-cpp.so.18.1+0x25e1f5e)
#18 0x00007f42555bb4d1 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/usr/lib/llvm-18/lib/libclang-cpp.so.18.1+0x25aa4d1)
#19 0x00007f42555bb71e clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/usr/lib/llvm-18/lib/libclang-cpp.so.18.1+0x25aa71e)
#20 0x00007f42555d7d2d clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/usr/lib/llvm-18/lib/libclang-cpp.so.18.1+0x25c6d2d)
#21 0x000055b024c74caa vast::cc::driver::execute() /home/bpappas/github.com/trailofbits/vast/include/vast/Frontend/Driver.hpp:180:30
#22 0x000055b024c73ca8 main /home/bpappas/github.com/trailofbits/vast/tools/vast-front/driver.cpp:161:19
#23 0x00007f424b44bd90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#24 0x00007f424b44be40 call_init ./csu/../csu/libc-start.c:128:20
#25 0x00007f424b44be40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#26 0x000055b024c6d8e5 _start (./builds/default/tools/vast-front/Debug/vast-front+0xe498e5)
vast-front: error: clang frontend command failed with exit code 132 (use -v to see invocation)

Steps to Reproduce

Create a file test_subscript_enum_verify.c with the following contents:

enum FOO { BAR };

int main(void) {
    int a[1]   = { 0 };
    enum FOO b = BAR;
    return a[b];
}

Run vast-front on the file like so:

vast-front -x c -vast-emit-mlir=hl test_subscript_enum_verify.c

Note that this issue only occurs if the enum value used for the index is declared using the enum keyword (i.e., its type is an elaborated type). This means that the following two similar programs do not raise errors:

enum FOO { BAR };

int main(void) {
    int a[1]   = { 0 };
    return a[BAR];
}
typedef enum FOO { BAR } FOO;

int main(void) {
    int a[1] = { 0 };
    FOO b    = BAR;
    return a[b];
}
PappasBrent commented 1 month ago

This issue is still occurring for me if I wrap the name of the enum variable in parentheses at its declaration site:

enum FOO { BAR };

int main(void) {
    int a[1]    = { 0 };
    enum FOO(b) = BAR;
    return a[b];
}