UndefResultChecker.cpp revision 9b663716449b618ba0390b1dbebc54fa8e971124
183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek//=== UndefResultChecker.cpp ------------------------------------*- C++ -*-===// 2eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek// 3eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek// The LLVM Compiler Infrastructure 4eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 7eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek// 8eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek//===----------------------------------------------------------------------===// 9eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek// 1083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek// This defines UndefResultChecker, a builtin check in ExprEngine that 1183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek// performs checks for undefined results of non-assignment binary operators. 12eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek// 13eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek//===----------------------------------------------------------------------===// 14eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek 1583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek#include "InternalChecks.h" 1683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 17eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" 1805e14cd46ef44c07385aae96ec2fdcb9bf7e9467Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 19eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek 204c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenekusing namespace clang; 215226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenekusing namespace ento; 224c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek 23eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremeneknamespace { 24eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekclass UndefResultChecker 2505e14cd46ef44c07385aae96ec2fdcb9bf7e9467Ted Kremenek : public CheckerVisitor<UndefResultChecker> { 2683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 27eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek BugType *BT; 28f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek 29f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenekpublic: 30f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek UndefResultChecker() : BT(0) {} 3182bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek static void *getTag() { static int tag = 0; return &tag; } 32f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); 33f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek}; 34f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek} // end anonymous namespace 35f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek 36f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenekvoid ento::RegisterUndefResultChecker(ExprEngine &Eng) { 37f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek Eng.registerCheck(new UndefResultChecker()); 38f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek} 39f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek 40f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenekvoid UndefResultChecker::PostVisitBinaryOperator(CheckerContext &C, 41f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek const BinaryOperator *B) { 42f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek const GRState *state = C.getState(); 434c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek if (state->getSVal(B).isUndef()) { 44d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek // Generate an error node. 45f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek ExplodedNode *N = C.generateSink(); 46f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek if (!N) 47d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek return; 48d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek 49d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek if (!BT) 50d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek BT = new BuiltinBug("Result of operation is garbage or undefined"); 51f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek 52f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek llvm::SmallString<256> sbuf; 53d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek llvm::raw_svector_ostream OS(sbuf); 54d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek const Expr *Ex = NULL; 55f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek bool isLeft = true; 56d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek 57f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek if (state->getSVal(B->getLHS()).isUndef()) { 58f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek Ex = B->getLHS()->IgnoreParenCasts(); 59f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek isLeft = true; 60f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek } 61f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek else if (state->getSVal(B->getRHS()).isUndef()) { 62d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek Ex = B->getRHS()->IgnoreParenCasts(); 63d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek isLeft = false; 64f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek } 65f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek 66d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek if (Ex) { 676e5977f0a8a680191fb4b4d8f32bc2c629faf0c2Argyrios Kyrtzidis OS << "The " << (isLeft ? "left" : "right") 686e5977f0a8a680191fb4b4d8f32bc2c629faf0c2Argyrios Kyrtzidis << " operand of '" 69d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek << BinaryOperator::getOpcodeStr(B->getOpcode()) 70f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek << "' is a garbage value"; 71f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek } 72f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek else { 73d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek // Neither operand was undefined, but the result is undefined. 746e5977f0a8a680191fb4b4d8f32bc2c629faf0c2Argyrios Kyrtzidis OS << "The result of the '" 75d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek << BinaryOperator::getOpcodeStr(B->getOpcode()) 76f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek << "' expression is undefined"; 77f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek } 78d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek EnhancedBugReport *report = new EnhancedBugReport(*BT, OS.str(), N); 794c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek if (Ex) { 80f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek report->addRange(Ex->getSourceRange()); 8183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex); 82f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek } 83f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek else 84f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, B); 85f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek C.EmitReport(report); 86f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek } 87f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek} 88d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek