diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-07-23 22:29:41 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-07-23 22:29:41 +0000 |
commit | efcbb1544109f0d07fda0c5f008c844f719e0ad6 (patch) | |
tree | 8d8d7b92cf197356d3c280d4a4ced99ec75ee867 /lib/Analysis/CheckSecuritySyntaxOnly.cpp | |
parent | 177d4d8700d66e80a874c3f609eede297118633d (diff) |
Implement: <rdar://problem/6335715> rule request: gets() buffer overflow
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76905 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CheckSecuritySyntaxOnly.cpp')
-rw-r--r-- | lib/Analysis/CheckSecuritySyntaxOnly.cpp | 66 |
1 files changed, 64 insertions, 2 deletions
diff --git a/lib/Analysis/CheckSecuritySyntaxOnly.cpp b/lib/Analysis/CheckSecuritySyntaxOnly.cpp index 36b729e219..5c98a526b7 100644 --- a/lib/Analysis/CheckSecuritySyntaxOnly.cpp +++ b/lib/Analysis/CheckSecuritySyntaxOnly.cpp @@ -21,22 +21,40 @@ using namespace clang; namespace { class VISIBILITY_HIDDEN WalkAST : public StmtVisitor<WalkAST> { - BugReporter &BR; + BugReporter &BR; + IdentifierInfo *II_gets; public: - WalkAST(BugReporter &br) : BR(br) {} + WalkAST(BugReporter &br) : BR(br), + II_gets(0) {} // Statement visitor methods. + void VisitCallExpr(CallExpr *CE); void VisitForStmt(ForStmt *S); void VisitStmt(Stmt *S) { VisitChildren(S); } void VisitChildren(Stmt *S); + // Helpers. + IdentifierInfo *GetIdentifier(IdentifierInfo *& II, const char *str); + // Checker-specific methods. void CheckLoopConditionForFloat(const ForStmt *FS); + void CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD); }; } // end anonymous namespace //===----------------------------------------------------------------------===// +// Helper methods. +//===----------------------------------------------------------------------===// + +IdentifierInfo *WalkAST::GetIdentifier(IdentifierInfo *& II, const char *str) { + if (!II) + II = &BR.getContext().Idents.get(str); + + return II; +} + +//===----------------------------------------------------------------------===// // AST walking. //===----------------------------------------------------------------------===// @@ -46,6 +64,15 @@ void WalkAST::VisitChildren(Stmt *S) { Visit(child); } +void WalkAST::VisitCallExpr(CallExpr *CE) { + if (const FunctionDecl *FD = CE->getDirectCallee()) { + CheckCall_gets(CE, FD); + } + + // Recurse and check children. + VisitChildren(CE); +} + void WalkAST::VisitForStmt(ForStmt *FS) { CheckLoopConditionForFloat(FS); @@ -162,6 +189,41 @@ void WalkAST::CheckLoopConditionForFloat(const ForStmt *FS) { } //===----------------------------------------------------------------------===// +// Check: Any use of 'gets' is insecure. +// Originally: <rdar://problem/6335715> +// Implements (part of): 300-BSI (buildsecurityin.us-cert.gov) +//===----------------------------------------------------------------------===// + +void WalkAST::CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD) { + if (FD->getIdentifier() != GetIdentifier(II_gets, "gets")) + return; + + const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FD->getType()); + if (!FTP) + return; + + // Verify that the function takes a single argument. + if (FTP->getNumArgs() != 1) + return; + + // Is the argument a 'char*'? + const PointerType *PT = dyn_cast<PointerType>(FTP->getArgType(0)); + if (!PT) + return; + + if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy) + return; + + // Issue a warning. + SourceRange R = CE->getCallee()->getSourceRange(); + BR.EmitBasicReport("Potential buffer overflow in call to 'gets'", + "Security", + "Call to function 'gets' is extremely insecure as it can " + "always result in a buffer overflow", + CE->getLocStart(), &R, 1); +} + +//===----------------------------------------------------------------------===// // Entry point for check. //===----------------------------------------------------------------------===// |