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