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