From 07d83aa220567bef263ef76cfc9b0159320bb640 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Mon, 25 Feb 2008 17:51:31 +0000 Subject: [PATCH] Added transfer function support for checking for divide-by-zero errors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47547 91177308-0d34-0410-b5e6-96231b3b80d8 --- Analysis/GRExprEngine.cpp | 56 ++++++++++++++++++- .../Analysis/PathSensitive/GRExprEngine.h | 18 +++++- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/Analysis/GRExprEngine.cpp b/Analysis/GRExprEngine.cpp index 2931d2aa6d..74fadcc9e3 100644 --- a/Analysis/GRExprEngine.cpp +++ b/Analysis/GRExprEngine.cpp @@ -850,6 +850,33 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, BinaryOperator::Opcode Op = B->getOpcode(); + if (Op == BinaryOperator::Div) { // Check for divide-by-zero. + + // First, "assume" that the denominator is 0. + + bool isFeasible = false; + StateTy ZeroSt = Assume(St, RightV, false, isFeasible); + + if (isFeasible) { + NodeTy* DivZeroNode = Builder->generateNode(B, ZeroSt, N2); + + if (DivZeroNode) { + DivZeroNode->markAsSink(); + DivZeroes.insert(DivZeroNode); + } + } + + // Second, "assume" that the denominator cannot be 0. + + isFeasible = false; + St = Assume(St, RightV, true, isFeasible); + + if (!isFeasible) + continue; + + // Fall-through. The logic below processes the divide. + } + if (Op <= BinaryOperator::Or) { // Process non-assignements except commas or short-circuited @@ -964,8 +991,35 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, RightV = EvalCast(RightV, CTy); // Evaluate operands and promote to result type. + + if (Op == BinaryOperator::Div) { // Check for divide-by-zero. + + // First, "assume" that the denominator is 0. + + bool isFeasible = false; + StateTy ZeroSt = Assume(St, RightV, false, isFeasible); + + if (isFeasible) { + NodeTy* DivZeroNode = Builder->generateNode(B, ZeroSt, N2); + + if (DivZeroNode) { + DivZeroNode->markAsSink(); + DivZeroes.insert(DivZeroNode); + } + } + + // Second, "assume" that the denominator cannot be 0. + + isFeasible = false; + St = Assume(St, RightV, true, isFeasible); + + if (!isFeasible) + continue; + + // Fall-through. The logic below processes the divide. + } + RVal Result = EvalCast(EvalBinOp(Op, V, RightV), B->getType()); - St = SetRVal(SetRVal(St, B, Result), LeftLV, Result); } } diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 7fa5297daa..bc8bec78e1 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -114,18 +114,30 @@ protected: /// taking a branch based on an uninitialized value. typedef llvm::SmallPtrSet UninitBranchesTy; UninitBranchesTy UninitBranches; + + typedef llvm::SmallPtrSet UninitStoresTy; + typedef llvm::SmallPtrSet BadDerefTy; + typedef llvm::SmallPtrSet DivZerosTy; /// UninitStores - Sinks in the ExplodedGraph that result from /// making a store to an uninitialized lvalue. - typedef llvm::SmallPtrSet UninitStoresTy; UninitStoresTy UninitStores; /// ImplicitNullDeref - Nodes in the ExplodedGraph that result from - /// taking a dereference on a symbolic pointer that may be NULL. - typedef llvm::SmallPtrSet BadDerefTy; + /// taking a dereference on a symbolic pointer that MAY be NULL. BadDerefTy ImplicitNullDeref; + + /// ExplicitNullDeref - Nodes in the ExplodedGraph that result from + /// taking a dereference on a symbolic pointer that MUST be NULL. BadDerefTy ExplicitNullDeref; + + /// UnitDeref - Nodes in the ExplodedGraph that result from + /// taking a dereference on an uninitialized value. BadDerefTy UninitDeref; + + /// DivZeroes - Nodes in the ExplodedGraph that result from evaluating + /// a divide-by-zero. + DivZerosTy DivZeroes; bool StateCleaned; -- 2.40.0