1668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu//=== UndefResultChecker.cpp ------------------------------------*- C++ -*-===// 2668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu// 3668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu// The LLVM Compiler Infrastructure 4668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu// 5668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu// This file is distributed under the University of Illinois Open Source 6668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu// License. See LICENSE.TXT for details. 7668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu// 8668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu//===----------------------------------------------------------------------===// 9668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu// 10d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis// This defines UndefResultChecker, a builtin check in ExprEngine that 11668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu// performs checks for undefined results of non-assignment binary operators. 12668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu// 13668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu//===----------------------------------------------------------------------===// 14668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu 15180e03f9761aa55b5adca430706595e1bbb79c4dArgyrios Kyrtzidis#include "ClangSACheckers.h" 1655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 17ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 18180e03f9761aa55b5adca430706595e1bbb79c4dArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 19180e03f9761aa55b5adca430706595e1bbb79c4dArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 209b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 218fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h" 22a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "llvm/Support/raw_ostream.h" 23668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu 24668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xuusing namespace clang; 259ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 26668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu 27668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xunamespace { 28ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass UndefResultChecker 29ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis : public Checker< check::PostStmt<BinaryOperator> > { 30668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu 31651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines mutable std::unique_ptr<BugType> BT; 32651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 33668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xupublic: 34180e03f9761aa55b5adca430706595e1bbb79c4dArgyrios Kyrtzidis void checkPostStmt(const BinaryOperator *B, CheckerContext &C) const; 35668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu}; 36668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu} // end anonymous namespace 37668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu 38180e03f9761aa55b5adca430706595e1bbb79c4dArgyrios Kyrtzidisvoid UndefResultChecker::checkPostStmt(const BinaryOperator *B, 39180e03f9761aa55b5adca430706595e1bbb79c4dArgyrios Kyrtzidis CheckerContext &C) const { 408bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 415eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = C.getLocationContext(); 425eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (state->getSVal(B, LCtx).isUndef()) { 4352810c51afaa10b30319d236d353d70534cf9356Anna Zaks 4452810c51afaa10b30319d236d353d70534cf9356Anna Zaks // Do not report assignments of uninitialized values inside swap functions. 4552810c51afaa10b30319d236d353d70534cf9356Anna Zaks // This should allow to swap partially uninitialized structs 4652810c51afaa10b30319d236d353d70534cf9356Anna Zaks // (radar://14129997) 4752810c51afaa10b30319d236d353d70534cf9356Anna Zaks if (const FunctionDecl *EnclosingFunctionDecl = 4852810c51afaa10b30319d236d353d70534cf9356Anna Zaks dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl())) 4952810c51afaa10b30319d236d353d70534cf9356Anna Zaks if (C.getCalleeName(EnclosingFunctionDecl) == "swap") 5052810c51afaa10b30319d236d353d70534cf9356Anna Zaks return; 5152810c51afaa10b30319d236d353d70534cf9356Anna Zaks 52668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu // Generate an error node. 53d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(); 54668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu if (!N) 55668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu return; 56668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu 57668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu if (!BT) 58651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BT.reset( 59651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines new BuiltinBug(this, "Result of operation is garbage or undefined")); 60668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu 61f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<256> sbuf; 62668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu llvm::raw_svector_ostream OS(sbuf); 636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Expr *Ex = nullptr; 64668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu bool isLeft = true; 65668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu 665eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (state->getSVal(B->getLHS(), LCtx).isUndef()) { 67668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu Ex = B->getLHS()->IgnoreParenCasts(); 68668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu isLeft = true; 69668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu } 705eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek else if (state->getSVal(B->getRHS(), LCtx).isUndef()) { 71668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu Ex = B->getRHS()->IgnoreParenCasts(); 72668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu isLeft = false; 73668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu } 74668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu 75668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu if (Ex) { 76668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu OS << "The " << (isLeft ? "left" : "right") 77668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu << " operand of '" 78668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu << BinaryOperator::getOpcodeStr(B->getOpcode()) 79668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu << "' is a garbage value"; 80668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu } 81668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu else { 82668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu // Neither operand was undefined, but the result is undefined. 83668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu OS << "The result of the '" 84668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu << BinaryOperator::getOpcodeStr(B->getOpcode()) 85668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu << "' expression is undefined"; 86668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu } 87e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report = new BugReport(*BT, OS.str(), N); 88d4daa7cbd40807cf72ca83900e2c00ab3e1d7d6fTed Kremenek if (Ex) { 89d4daa7cbd40807cf72ca83900e2c00ab3e1d7d6fTed Kremenek report->addRange(Ex->getSourceRange()); 90a1f81bb0e55749a1414b1b5124bb83b9052ff2acJordan Rose bugreporter::trackNullOrUndefValue(N, Ex, *report); 91d4daa7cbd40807cf72ca83900e2c00ab3e1d7d6fTed Kremenek } 92668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu else 93a1f81bb0e55749a1414b1b5124bb83b9052ff2acJordan Rose bugreporter::trackNullOrUndefValue(N, B, *report); 94ce56fd3d6ddf3f1b7ae1a3ca3dd4a8768222594cTed Kremenek 95785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose C.emitReport(report); 96668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu } 97668399b23cf18124c8c8c41a14a7712212f6fa45Zhongxing Xu} 98180e03f9761aa55b5adca430706595e1bbb79c4dArgyrios Kyrtzidis 99180e03f9761aa55b5adca430706595e1bbb79c4dArgyrios Kyrtzidisvoid ento::registerUndefResultChecker(CheckerManager &mgr) { 100180e03f9761aa55b5adca430706595e1bbb79c4dArgyrios Kyrtzidis mgr.registerChecker<UndefResultChecker>(); 101180e03f9761aa55b5adca430706595e1bbb79c4dArgyrios Kyrtzidis} 102