UndefResultChecker.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. //=== UndefResultChecker.cpp ------------------------------------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This defines UndefResultChecker, a builtin check in ExprEngine that
  11. // performs checks for undefined results of non-assignment binary operators.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "InternalChecks.h"
  15. #include "clang/StaticAnalyzer/BugReporter/BugType.h"
  16. #include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h"
  17. #include "clang/StaticAnalyzer/PathSensitive/ExprEngine.h"
  18. using namespace clang;
  19. using namespace ento;
  20. namespace {
  21. class UndefResultChecker
  22. : public CheckerVisitor<UndefResultChecker> {
  23. BugType *BT;
  24. public:
  25. UndefResultChecker() : BT(0) {}
  26. static void *getTag() { static int tag = 0; return &tag; }
  27. void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
  28. };
  29. } // end anonymous namespace
  30. void ento::RegisterUndefResultChecker(ExprEngine &Eng) {
  31. Eng.registerCheck(new UndefResultChecker());
  32. }
  33. void UndefResultChecker::PostVisitBinaryOperator(CheckerContext &C,
  34. const BinaryOperator *B) {
  35. const GRState *state = C.getState();
  36. if (state->getSVal(B).isUndef()) {
  37. // Generate an error node.
  38. ExplodedNode *N = C.generateSink();
  39. if (!N)
  40. return;
  41. if (!BT)
  42. BT = new BuiltinBug("Result of operation is garbage or undefined");
  43. llvm::SmallString<256> sbuf;
  44. llvm::raw_svector_ostream OS(sbuf);
  45. const Expr *Ex = NULL;
  46. bool isLeft = true;
  47. if (state->getSVal(B->getLHS()).isUndef()) {
  48. Ex = B->getLHS()->IgnoreParenCasts();
  49. isLeft = true;
  50. }
  51. else if (state->getSVal(B->getRHS()).isUndef()) {
  52. Ex = B->getRHS()->IgnoreParenCasts();
  53. isLeft = false;
  54. }
  55. if (Ex) {
  56. OS << "The " << (isLeft ? "left" : "right")
  57. << " operand of '"
  58. << BinaryOperator::getOpcodeStr(B->getOpcode())
  59. << "' is a garbage value";
  60. }
  61. else {
  62. // Neither operand was undefined, but the result is undefined.
  63. OS << "The result of the '"
  64. << BinaryOperator::getOpcodeStr(B->getOpcode())
  65. << "' expression is undefined";
  66. }
  67. EnhancedBugReport *report = new EnhancedBugReport(*BT, OS.str(), N);
  68. if (Ex) {
  69. report->addRange(Ex->getSourceRange());
  70. report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
  71. }
  72. else
  73. report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, B);
  74. C.EmitReport(report);
  75. }
  76. }