blob: f29a8cc3b19e45febe77ed6d619b47aeaf79db61 [file] [log] [blame]
Ted Kremenek076d84e2009-07-23 01:07:19 +00001//==- CheckSecuritySyntaxOnly.cpp - Basic security checks --------*- 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 file defines a set of flow-insensitive security checks.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Analysis/PathSensitive/BugReporter.h"
15#include "clang/Analysis/LocalCheckers.h"
16#include "clang/AST/StmtVisitor.h"
17#include "llvm/Support/Compiler.h"
18
19using namespace clang;
20
21namespace {
22class VISIBILITY_HIDDEN WalkAST : public StmtVisitor<WalkAST> {
23 BugReporter &BR;
24public:
25 WalkAST(BugReporter &br) : BR(br) {}
26
27 // Statement visitor methods.
28 void VisitDoStmt(DoStmt *S);
29 void VisitWhileStmt(WhileStmt *S);
30 void VisitForStmt(ForStmt *S);
31
32 void VisitChildren(Stmt *S);
33 void VisitStmt(Stmt *S) { VisitChildren(S); }
34
35 // Checker-specific methods.
36 void CheckLoopConditionForFloat(Stmt *Loop, Expr *Condition);
37};
38} // end anonymous namespace
39
40//===----------------------------------------------------------------------===//
41// AST walking.
42//===----------------------------------------------------------------------===//
43
44void WalkAST::VisitChildren(Stmt *S) {
45 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
46 if (Stmt *child = *I)
47 Visit(child);
48}
49
50void WalkAST::VisitDoStmt(DoStmt *S) {
51 CheckLoopConditionForFloat(S, S->getCond());
52 VisitChildren(S);
53}
54
55void WalkAST::VisitForStmt(ForStmt *S) {
56 if (Expr *Cond = S->getCond())
57 CheckLoopConditionForFloat(S, Cond);
58
59 VisitChildren(S);
60}
61
62void WalkAST::VisitWhileStmt(WhileStmt *S) {
63 CheckLoopConditionForFloat(S, S->getCond());
64 VisitChildren(S);
65}
66
67//===----------------------------------------------------------------------===//
68// Checking logic.
69//===----------------------------------------------------------------------===//
70
71static Expr* IsFloatCondition(Expr *Condition) {
72 while (Condition) {
73 Condition = Condition->IgnoreParenCasts();
74
75 if (Condition->getType()->isFloatingType())
76 return Condition;
77
78 switch (Condition->getStmtClass()) {
79 case Stmt::BinaryOperatorClass: {
80 BinaryOperator *B = cast<BinaryOperator>(Condition);
81
82 Expr *LHS = B->getLHS();
83 if (LHS->getType()->isFloatingType())
84 return LHS;
85
86 Expr *RHS = B->getRHS();
87 if (RHS->getType()->isFloatingType())
88 return RHS;
89
90 return NULL;
91 }
92 case Stmt::UnaryOperatorClass: {
93 UnaryOperator *U = cast<UnaryOperator>(Condition);
94 if (U->isArithmeticOp()) {
95 Condition = U->getSubExpr();
96 continue;
97 }
98 return NULL;
99 }
100 default:
101 break;
102 }
103 }
104 return NULL;
105}
106
107void WalkAST::CheckLoopConditionForFloat(Stmt *Loop, Expr *Condition) {
108 if ((Condition = IsFloatCondition(Condition))) {
109 const char *bugType = "Floating point value used in loop condition";
110 SourceRange R = Condition->getSourceRange();
111 BR.EmitBasicReport(bugType, "Security", bugType, Loop->getLocStart(),&R, 1);
112 }
113}
114
115//===----------------------------------------------------------------------===//
116// Entry point for check.
117//===----------------------------------------------------------------------===//
118
119void clang::CheckSecuritySyntaxOnly(Decl *D, BugReporter &BR) {
120 WalkAST walker(BR);
121 walker.Visit(D->getBody());
122}