llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.69k stars 11.87k forks source link

core assertion failure (`state' in void {anonymous}::VLASizeChecker::checkPreStmt()) #28824

Open llvmbot opened 8 years ago

llvmbot commented 8 years ago
Bugzilla Link 28450
Version trunk
OS Linux
Attachments Testcase (from GCC testsuite) allowing to reproduce the failure.
Reporter LLVM Bugzilla Contributor

Extended Description

$ ~/llvm-build/bin/clang -cc1 -analyze -analyzer-checker=core 20040811-1.c clang: /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp:176: void {anonymous}::VLASizeChecker::checkPreStmt(const clang::DeclStmt*, clang::ento::CheckerContext&) const: Assertion `state' failed.

​0 0x000000000304f1c1 llvm::sys::PrintStackTrace(llvm::raw_ostream&) /home/roberto/llvm/lib/Support/Unix/Signals.inc:402:0

​1 0x000000000304f51c PrintStackTraceSignalHandler(void*) /home/roberto/llvm/lib/Support/Unix/Signals.inc:470:0

​2 0x000000000304d7f2 llvm::sys::RunSignalHandlers() /home/roberto/llvm/lib/Support/Signals.cpp:44:0

​3 0x000000000304eb39 SignalHandler(int) /home/roberto/llvm/lib/Support/Unix/Signals.inc:256:0

​4 0x00007fdae9a72330 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x10330)

​5 0x00007fdae885ec37 gsignal /build/eglibc-oGUzwX/eglibc-2.19/signal/../nptl/sysdeps/unix/sysv/linux/raise.c:56:0

​6 0x00007fdae8862028 abort /build/eglibc-oGUzwX/eglibc-2.19/stdlib/abort.c:91:0

​7 0x00007fdae8857bf6 __assert_fail_base /build/eglibc-oGUzwX/eglibc-2.19/assert/assert.c:92:0

​8 0x00007fdae8857ca2 (/lib/x86_64-linux-gnu/libc.so.6+0x2fca2)

​9 0x0000000005110ef7 (anonymous namespace)::VLASizeChecker::checkPreStmt(clang::DeclStmt const*, clang::ento::CheckerContext&) const /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp:179:0

​10 0x000000000511125c void clang::ento::check::PreStmt::_checkStmt<(anonymous namespace)::VLASizeChecker>(void, clang::Stmt const, clang::ento::CheckerContext&) /home/roberto/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h:86:0

​11 0x00000000051b2696 clang::ento::CheckerFn<void (clang::Stmt const, clang::ento::CheckerContext&)>::operator()(clang::Stmt const, clang::ento::CheckerContext&) const /home/roberto/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h:60:0

​12 0x00000000051acc20 (anonymous namespace)::CheckStmtContext::runChecker(clang::ento::CheckerFn<void (clang::Stmt const, clang::ento::CheckerContext&)>, clang::ento::NodeBuilder&, clang::ento::ExplodedNode) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp:161:0

​13 0x00000000051af44f void expandGraphWithCheckers<(anonymous namespace)::CheckStmtContext>((anonymous namespace)::CheckStmtContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp:121:0

​14 0x00000000051accd0 clang::ento::CheckerManager::runCheckersForStmt(bool, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&, clang::Stmt const*, clang::ento::ExprEngine&, bool) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp:175:0

​15 0x00000000051e49c2 clang::ento::CheckerManager::runCheckersForPreStmt(clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&, clang::Stmt const*, clang::ento::ExprEngine&) /home/roberto/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h:192:0

​16 0x00000000051f8560 clang::ento::ExprEngine::VisitDeclStmt(clang::DeclStmt const, clang::ento::ExplodedNode, clang::ento::ExplodedNodeSet&) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp:489:0

​17 0x00000000051dca18 clang::ento::ExprEngine::Visit(clang::Stmt const, clang::ento::ExplodedNode, clang::ento::ExplodedNodeSet&) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp:1200:0

​18 0x00000000051d9034 clang::ento::ExprEngine::ProcessStmt(clang::CFGStmt, clang::ento::ExplodedNode*) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp:449:0

​19 0x00000000051d8382 clang::ento::ExprEngine::processCFGElement(clang::CFGElement, clang::ento::ExplodedNode, unsigned int, clang::ento::NodeBuilderContext) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp:297:0

​20 0x00000000051c74d1 clang::ento::CoreEngine::HandlePostStmt(clang::CFGBlock const, unsigned int, clang::ento::ExplodedNode) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:522:0

​21 0x00000000051c64be clang::ento::CoreEngine::dispatchWorkItem(clang::ento::ExplodedNode*, clang::ProgramPoint, clang::ento::WorkListUnit const&) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:280:0

​22 0x00000000051c609e clang::ento::CoreEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int, llvm::IntrusiveRefCntPtr) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:217:0

​23 0x00000000043f22c2 clang::ento::ExprEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int) /home/roberto/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h:109:0

​24 0x00000000043bb65c (anonymous namespace)::AnalysisConsumer::ActionExprEngine(clang::Decl, bool, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const, llvm::DenseMapInfo<clang::Decl const> >) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:668:0

​25 0x00000000043bb77c (anonymous namespace)::AnalysisConsumer::RunPathSensitiveChecks(clang::Decl, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const, llvm::DenseMapInfo<clang::Decl const> >) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:685:0

​26 0x00000000043bb43e (anonymous namespace)::AnalysisConsumer::HandleCode(clang::Decl, unsigned int, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const, llvm::DenseMapInfo<clang::Decl const> >) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:632:0

​27 0x00000000043baaae (anonymous namespace)::AnalysisConsumer::HandleDeclsCallGraph(unsigned int) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:498:0

​28 0x00000000043bae71 (anonymous namespace)::AnalysisConsumer::HandleTranslationUnit(clang::ASTContext&) /home/roberto/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:549:0

​29 0x00000000044413f6 clang::ParseAST(clang::Sema&, bool, bool) /home/roberto/llvm/tools/clang/lib/Parse/ParseAST.cpp:169:0

​30 0x00000000037712d2 clang::ASTFrontendAction::ExecuteAction() /home/roberto/llvm/tools/clang/lib/Frontend/FrontendAction.cpp:558:0

​31 0x0000000003770d97 clang::FrontendAction::Execute() /home/roberto/llvm/tools/clang/lib/Frontend/FrontendAction.cpp:461:0

​32 0x0000000003722802 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /home/roberto/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp:877:0

​33 0x000000000386cffb clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /home/roberto/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:241:0

​34 0x00000000017f3d8b cc1_main(llvm::ArrayRef<char const>, char const, void*) /home/roberto/llvm/tools/clang/tools/driver/cc1_main.cpp:116:0

​35 0x00000000017ea400 ExecuteCC1Tool(llvm::ArrayRef<char const*>, llvm::StringRef) /home/roberto/llvm/tools/clang/tools/driver/driver.cpp:301:0

​36 0x00000000017eaef9 main /home/roberto/llvm/tools/clang/tools/driver/driver.cpp:382:0

​37 0x00007fdae8849f45 __libc_start_main /build/eglibc-oGUzwX/eglibc-2.19/csu/libc-start.c:321:0

​38 0x00000000017e7de9 _start (/home/roberto/llvm-build/bin/clang+0x17e7de9)

Stack dump:

  1. Program arguments: /home/roberto/llvm-build/bin/clang -cc1 -analyze -analyzer-checker=core 20040811-1.c
  2. parser at end of file
  3. While analyzing stack:

    0 int main()

  4. 20040811-1.c:11:3: Error evaluating statement
  5. 20040811-1.c:11:3: Error evaluating statement Aborted
haoNoQ commented 4 years ago

https://reviews.llvm.org/D69726

haoNoQ commented 5 years ago

Yeah, i remember this one. I guess i could just remove the assertion and replace it with coverage loss. Let me summarize my thoughts real quick.

The Analyzer has a model of "extents" of memory regions, i.e. the distance, in bytes, from the start of the region to the end of the region. The extent of the region is an arbitrary SVal. Concrete regions usually have concrete extents. Symbolic regions typically have unknown extents, which are represented with SymbolExtent that's designed specifically for that purpose.

Heap-allocated memory and alloca/VLA regions are supposed to have extents based on the run-time value of their argument. They are represented by SymbolExtent that is constrained to be equal to the run-time extent.

One reason this is bad is that our constraint solver often fails to solve these constraints. It would have been easier for it to handle this if extents were represented by the run-time sizes directly, rather than via an equality constraint.

The other reason this is bad is shown by this test. Extents are in fact mutable, extent of the same memory region may change in run-time if it's a VLA.

As for proper solutions,

(1) It'd probably be great to teach the analyzer that in fact it's not the same region; it just accidentally has the same name (and moreover, the same declaration in the source code). This would involve hacking over the MemRegion hierarchy. This has something to do with the problem of Scope Contexts, i.e. ideally we'd keep our VarRegions but have them be sub-regions of different "StackScopeSpaceRegion"s, see also llvm/llvm-bugzilla-archive#32163

(2) But apart from that, it'd probably be great to replace the existing extent modeling with an inter-checker state trait (similarly to what we just did to taint). This would allow us store extents directly and avoid constrains of our constraint solver (pun accidental) and make extent values more immediately-expressive (i.e., while debugging, by looking at the value we can instantly say "oh it's 5" instead of "uhm, yeah, it's some extent indeed, why did i even bother asking") and also allow extents to be mutable.

llvmbot commented 5 years ago

Just checked this with clang from today's sources. It still crashes the same way.

Reassigning to Artem.

llvmbot commented 8 years ago

assigned to @haoNoQ