vabridgers created this revision. vabridgers added reviewers: martong, steakhal, NoQ. Herald added subscribers: manas, ASDenysPetrov, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun. Herald added a project: All. vabridgers requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
A crash was seen in CastValueChecker due to a null pointer dereference when analyzing proprietary source code. A suitably small and obfuscated reproducer cannot be provided at this time, but a description of the problem seen can be provided. The crash seen is as follows, with debug information dump following. The fix seeks to simply avoid the null pointer dereference, thus preventing the crash. Program received signal SIGSEGV, Segmentation fault. 0x0000000009c2d380 in clang::DeclarationName::getAsString[abi:cxx11]() const (this=0x28) at ../../clang/lib/AST/DeclarationName.cpp:238 238 OS << *this; (gdb) bt clang::DeclarationName::getAsString[abi:cxx11]() const (this=0x28) at ../../clang/lib/AST/DeclarationName.cpp:238 const (this=0x0) at ../../clang/include/clang/AST/Decl.h:290 Object=0x1c11af18, CastSucceeds=true, IsKnownCast=false) at ../../clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp:111 State=..., C=..., IsInstanceOf=true) at ../../clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp:319 namespace)::CastValueChecker::evalIsa (this=0x10cdf140, Call=..., DV=..., C=...) at ../../clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp:437 ... (gdb) frame 2 Object=0x1c11af18, CastSucceeds=true, IsKnownCast=false) at ../../clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp:111 111 : CastToTy->getPointeeCXXRecordDecl()->getNameAsString(); (gdb) p CastToTy $1 = {Value = {Value = 312725088}} (gdb) p CastToTy->getPointeeCXXRecordDecl() $2 = (const clang::CXXRecordDecl *) 0x0 (gdb) p CastToTy.dump() LValueReferenceType 0x12a3ce60 'class llvm::ReplaceableMetadataImpl *&' `-PointerType 0x129971b0 'class llvm::ReplaceableMetadataImpl *' `-RecordType 0x128afce0 'class llvm::ReplaceableMetadataImpl' `-CXXRecord 0x128ff160 'ReplaceableMetadataImpl' (gdb) frame 16 (this=0x7fffffff9208, currStmt=0x1f026978, Pred=0x22cf76f0) at ../../clang/lib/StaticAnalyzer/Core/ExprEngine.cpp:783 783 Visit(currStmt, I, DstI); (gdb) p currStmt $1 = (const clang::Stmt *) 0x1f026978 (gdb) p currStmt->dump() CallExpr 0x1f026978 '_Bool' | -ImplicitCastExpr 0x1f026960 '_Bool (*)(const class | | llvm::PointerUnion<const class clang::Type *, const class clang::ExtQuals *> &)' <FunctionToPointerDecay> | `-DeclRefExpr 0x1f026908 '_Bool (const class llvm::PointerUnion<const | | class clang::Type *, const class clang::ExtQuals *> &)' lvalue Function 0x1f007e58 'isa' '_Bool (const class llvm::PointerUnion<const class clang::Type *, const class clang::ExtQuals *> &)' (FunctionTemplate 0x11c5df38 'isa') `-UnaryOperator 0x1f026738 'const class llvm::PointerUnion<const class clang::Type *, const class clang::ExtQuals *>' lvalue prefix '*' cannot overflow `-CXXThisExpr 0x1f026728 'const class llvm::PointerUnion<const class clang::Type *, const class clang::ExtQuals *> *' this $2 = void Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D127105 Files: clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp Index: clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp @@ -108,7 +108,9 @@ bool CastSucceeds, bool IsKnownCast) { std::string CastToName = CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString() - : CastToTy->getPointeeCXXRecordDecl()->getNameAsString(); + : (CastToTy->getPointeeCXXRecordDecl() != nullptr) + ? CastToTy->getPointeeCXXRecordDecl()->getNameAsString() + : "(nil)"; Object = Object->IgnoreParenImpCasts(); return C.getNoteTag( @@ -163,9 +165,11 @@ bool First = true; for (QualType CastToTy: CastToTyVec) { std::string CastToName = - CastToTy->getAsCXXRecordDecl() ? - CastToTy->getAsCXXRecordDecl()->getNameAsString() : - CastToTy->getPointeeCXXRecordDecl()->getNameAsString(); + CastToTy->getAsCXXRecordDecl() + ? CastToTy->getAsCXXRecordDecl()->getNameAsString() + : (CastToTy->getPointeeCXXRecordDecl() != nullptr) + ? CastToTy->getPointeeCXXRecordDecl()->getNameAsString() + : "(nil)"; Out << ' ' << ((CastToTyVec.size() == 1) ? "not" : (First ? "neither" : "nor")) << " a '" << CastToName << '\'';
Index: clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp @@ -108,7 +108,9 @@ bool CastSucceeds, bool IsKnownCast) { std::string CastToName = CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString() - : CastToTy->getPointeeCXXRecordDecl()->getNameAsString(); + : (CastToTy->getPointeeCXXRecordDecl() != nullptr) + ? CastToTy->getPointeeCXXRecordDecl()->getNameAsString() + : "(nil)"; Object = Object->IgnoreParenImpCasts(); return C.getNoteTag( @@ -163,9 +165,11 @@ bool First = true; for (QualType CastToTy: CastToTyVec) { std::string CastToName = - CastToTy->getAsCXXRecordDecl() ? - CastToTy->getAsCXXRecordDecl()->getNameAsString() : - CastToTy->getPointeeCXXRecordDecl()->getNameAsString(); + CastToTy->getAsCXXRecordDecl() + ? CastToTy->getAsCXXRecordDecl()->getNameAsString() + : (CastToTy->getPointeeCXXRecordDecl() != nullptr) + ? CastToTy->getPointeeCXXRecordDecl()->getNameAsString() + : "(nil)"; Out << ' ' << ((CastToTyVec.size() == 1) ? "not" : (First ? "neither" : "nor")) << " a '" << CastToName << '\'';
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits