diff options
author | Ted Kremenek <kremenek@apple.com> | 2007-09-28 00:09:38 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2007-09-28 00:09:38 +0000 |
commit | a1de8c784a574a89a8a828331a8ce6b1aa57bed1 (patch) | |
tree | 2a54c55e2383d9c9236262da59ea5017cfbdf1c1 /Analysis/UninitializedValues.cpp | |
parent | d064951b0dcc95f8604d0d69ae82d9ecbd38c796 (diff) |
Fixed several bugs in the propagation of "uninitialized value"
taintness across expressions.
Made "smart-culling" of taint propagation (for error reporting)
correctly handle conditional expressions and a few other edge cases.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42421 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'Analysis/UninitializedValues.cpp')
-rw-r--r-- | Analysis/UninitializedValues.cpp | 98 |
1 files changed, 44 insertions, 54 deletions
diff --git a/Analysis/UninitializedValues.cpp b/Analysis/UninitializedValues.cpp index 7598a0e168..a7c7ccbc1d 100644 --- a/Analysis/UninitializedValues.cpp +++ b/Analysis/UninitializedValues.cpp @@ -53,11 +53,8 @@ namespace { class TransferFuncs : public CFGStmtVisitor<TransferFuncs,bool> { UninitializedValues::ValTy V; UninitializedValues::AnalysisDataTy& AD; - bool InitWithAssigns; public: - TransferFuncs(UninitializedValues::AnalysisDataTy& ad, - bool init_with_assigns=true) : - AD(ad), InitWithAssigns(init_with_assigns) { + TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) { V.resetValues(AD); } @@ -68,8 +65,11 @@ public: bool VisitUnaryOperator(UnaryOperator* U); bool VisitStmt(Stmt* S); bool VisitCallExpr(CallExpr* C); - bool BlockStmt_VisitExpr(Expr* E); bool VisitDeclStmt(DeclStmt* D); + bool VisitConditionalOperator(ConditionalOperator* C); + + bool Visit(Stmt *S); + bool BlockStmt_VisitExpr(Expr* E); BlockVarDecl* FindBlockVarDecl(Stmt* S); }; @@ -81,64 +81,47 @@ static const bool Uninitialized = false; bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) { if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(DR->getDecl())) { if (AD.Observer) AD.Observer->ObserveDeclRefExpr(V,AD,DR,VD); - - return V(VD,AD); + + // Pseudo-hack to prevent cascade of warnings. If an accessed variable + // is uninitialized, then we are already going to flag a warning for + // this variable, which a "source" of uninitialized values. + // We can otherwise do a full "taint" of uninitialized values. The + // client has both options by toggling AD.FullUninitTaint. + + return AD.FullUninitTaint ? V(VD,AD) : Initialized; } else return Initialized; } BlockVarDecl* TransferFuncs::FindBlockVarDecl(Stmt *S) { - for (;;) { + for (;;) if (ParenExpr* P = dyn_cast<ParenExpr>(S)) { - S = P->getSubExpr(); - continue; + S = P->getSubExpr(); continue; } - else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) + else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) { if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(DR->getDecl())) return VD; - - return NULL; - } + } + else return NULL; } bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) { - - if (CFG::hasImplicitControlFlow(B)) - return V(B,AD); - if (B->isAssignmentOp()) - // Get the Decl for the LHS (if any). if (BlockVarDecl* VD = FindBlockVarDecl(B->getLHS())) - if(InitWithAssigns) { - // Pseudo-hack to prevent cascade of warnings. If the RHS uses - // an uninitialized value, then we are already going to flag a warning - // for the RHS, or for the root "source" of the unintialized values. - // Thus, propogating uninitialized doesn't make sense, since we are - // just adding extra messages that don't - // contribute to diagnosing the bug. In InitWithAssigns mode - // we unconditionally set the assigned variable to Initialized to - // prevent Uninitialized propagation. - return V(VD,AD) = Initialized; - } - else return V(VD,AD) = Visit(B->getRHS()); + return V(VD,AD) = AD.FullUninitTaint ? Visit(B->getRHS()) : Initialized; return VisitStmt(B); } bool TransferFuncs::VisitDeclStmt(DeclStmt* S) { - bool x = Initialized; - for (ScopedDecl* D = S->getDecl(); D != NULL; D = D->getNextDeclarator()) if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(D)) { - if (Stmt* I = VD->getInit()) - x = InitWithAssigns ? Initialized : V(cast<Expr>(I),AD); - else - x = Uninitialized; - - V(VD,AD) = x; + if (Stmt* I = VD->getInit()) + V(VD,AD) = AD.FullUninitTaint ? V(cast<Expr>(I),AD) : Initialized; + else V(VD,AD) = Uninitialized; } - return x; + return Uninitialized; // Value is never consumed. } bool TransferFuncs::VisitCallExpr(CallExpr* C) { @@ -147,17 +130,16 @@ bool TransferFuncs::VisitCallExpr(CallExpr* C) { } bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) { - switch (U->getOpcode()) { - case UnaryOperator::AddrOf: - // For "&x", treat "x" as now being initialized. - if (BlockVarDecl* VD = FindBlockVarDecl(U->getSubExpr())) - V(VD,AD) = Initialized; - else - return Visit(U->getSubExpr()); - - default: - return Visit(U->getSubExpr()); - } + if (U->getOpcode() == UnaryOperator::AddrOf) + if (BlockVarDecl* VD = FindBlockVarDecl(U->getSubExpr())) + return V(VD,AD) = Initialized; + + return Visit(U->getSubExpr()); +} + +bool TransferFuncs::VisitConditionalOperator(ConditionalOperator* C) { + Visit(C->getCond()); + return Visit(C->getLHS()) & Visit(C->getRHS()); // Yes: we want &, not &&. } bool TransferFuncs::VisitStmt(Stmt* S) { @@ -167,14 +149,20 @@ bool TransferFuncs::VisitStmt(Stmt* S) { // evaluating some subexpressions may result in propogating "Uninitialized" // or "Initialized" to variables referenced in the other subexpressions. for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) - if (Visit(*I) == Uninitialized) x = Uninitialized; + if (*I && Visit(*I) == Uninitialized) x = Uninitialized; return x; } + +bool TransferFuncs::Visit(Stmt *S) { + if (AD.isTracked(static_cast<Expr*>(S))) return V(static_cast<Expr*>(S),AD); + else return static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(S); +} bool TransferFuncs::BlockStmt_VisitExpr(Expr* E) { assert (AD.isTracked(E)); - return V(E,AD) = Visit(E); + return V(E,AD) = + static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(E); } } // end anonymous namespace @@ -228,10 +216,12 @@ public: } // end anonymous namespace namespace clang { -void CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags) { +void CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags, + bool FullUninitTaint) { // Compute the unitialized values information. UninitializedValues U; + U.getAnalysisData().FullUninitTaint = FullUninitTaint; Solver S(U); S.runOnCFG(cfg); |