diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2018-05-26 00:04:26 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2018-05-26 00:04:26 +0000 |
commit | 8419cf307eeb9d44f686da280fdb789ba0d0506d (patch) | |
tree | bfd9e5276e4ee812c481e14310a22a1d2824e952 /clang/lib | |
parent | 1be7517aa9d860461cd986a85ef659d43d1d74b6 (diff) | |
download | bcm5719-llvm-8419cf307eeb9d44f686da280fdb789ba0d0506d.tar.gz bcm5719-llvm-8419cf307eeb9d44f686da280fdb789ba0d0506d.zip |
[analyzer] Add security checks for bcmp(), bcopy(), bzero().
These functions are obsolete. The analyzer would advice to replace them with
memcmp(), memcpy() or memmove(), or memset().
Patch by Tom Rix!
Differential Revision: https://reviews.llvm.org/D41881
llvm-svn: 333326
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp index 62831be26eb..15a13d8ac99 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp @@ -37,6 +37,9 @@ static bool isArc4RandomAvailable(const ASTContext &Ctx) { namespace { struct ChecksFilter { + DefaultBool check_bcmp; + DefaultBool check_bcopy; + DefaultBool check_bzero; DefaultBool check_gets; DefaultBool check_getpw; DefaultBool check_mktemp; @@ -47,6 +50,9 @@ struct ChecksFilter { DefaultBool check_FloatLoopCounter; DefaultBool check_UncheckedReturn; + CheckName checkName_bcmp; + CheckName checkName_bcopy; + CheckName checkName_bzero; CheckName checkName_gets; CheckName checkName_getpw; CheckName checkName_mktemp; @@ -89,6 +95,9 @@ public: // Checker-specific methods. void checkLoopConditionForFloat(const ForStmt *FS); + void checkCall_bcmp(const CallExpr *CE, const FunctionDecl *FD); + void checkCall_bcopy(const CallExpr *CE, const FunctionDecl *FD); + void checkCall_bzero(const CallExpr *CE, const FunctionDecl *FD); void checkCall_gets(const CallExpr *CE, const FunctionDecl *FD); void checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD); void checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD); @@ -129,6 +138,9 @@ void WalkAST::VisitCallExpr(CallExpr *CE) { // Set the evaluation function by switching on the callee name. FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name) + .Case("bcmp", &WalkAST::checkCall_bcmp) + .Case("bcopy", &WalkAST::checkCall_bcopy) + .Case("bzero", &WalkAST::checkCall_bzero) .Case("gets", &WalkAST::checkCall_gets) .Case("getpw", &WalkAST::checkCall_getpw) .Case("mktemp", &WalkAST::checkCall_mktemp) @@ -296,6 +308,132 @@ void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) { } //===----------------------------------------------------------------------===// +// Check: Any use of bcmp. +// CWE-477: Use of Obsolete Functions +// bcmp was deprecated in POSIX.1-2008 +//===----------------------------------------------------------------------===// + +void WalkAST::checkCall_bcmp(const CallExpr *CE, const FunctionDecl *FD) { + if (!filter.check_bcmp) + return; + + const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>(); + if (!FPT) + return; + + // Verify that the function takes three arguments. + if (FPT->getNumParams() != 3) + return; + + for (int i = 0; i < 2; i++) { + // Verify the first and second argument type is void*. + const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>(); + if (!PT) + return; + + if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy) + return; + } + + // Verify the third argument type is integer. + if (!FPT->getParamType(2)->isIntegralOrUnscopedEnumerationType()) + return; + + // Issue a warning. + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); + BR.EmitBasicReport(AC->getDecl(), filter.checkName_bcmp, + "Use of deprecated function in call to 'bcmp()'", + "Security", + "The bcmp() function is obsoleted by memcmp().", + CELoc, CE->getCallee()->getSourceRange()); +} + +//===----------------------------------------------------------------------===// +// Check: Any use of bcopy. +// CWE-477: Use of Obsolete Functions +// bcopy was deprecated in POSIX.1-2008 +//===----------------------------------------------------------------------===// + +void WalkAST::checkCall_bcopy(const CallExpr *CE, const FunctionDecl *FD) { + if (!filter.check_bcopy) + return; + + const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>(); + if (!FPT) + return; + + // Verify that the function takes three arguments. + if (FPT->getNumParams() != 3) + return; + + for (int i = 0; i < 2; i++) { + // Verify the first and second argument type is void*. + const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>(); + if (!PT) + return; + + if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy) + return; + } + + // Verify the third argument type is integer. + if (!FPT->getParamType(2)->isIntegralOrUnscopedEnumerationType()) + return; + + // Issue a warning. + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); + BR.EmitBasicReport(AC->getDecl(), filter.checkName_bcopy, + "Use of deprecated function in call to 'bcopy()'", + "Security", + "The bcopy() function is obsoleted by memcpy() " + "or memmove().", + CELoc, CE->getCallee()->getSourceRange()); +} + +//===----------------------------------------------------------------------===// +// Check: Any use of bzero. +// CWE-477: Use of Obsolete Functions +// bzero was deprecated in POSIX.1-2008 +//===----------------------------------------------------------------------===// + +void WalkAST::checkCall_bzero(const CallExpr *CE, const FunctionDecl *FD) { + if (!filter.check_bzero) + return; + + const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>(); + if (!FPT) + return; + + // Verify that the function takes two arguments. + if (FPT->getNumParams() != 2) + return; + + // Verify the first argument type is void*. + const PointerType *PT = FPT->getParamType(0)->getAs<PointerType>(); + if (!PT) + return; + + if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy) + return; + + // Verify the second argument type is integer. + if (!FPT->getParamType(1)->isIntegralOrUnscopedEnumerationType()) + return; + + // Issue a warning. + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); + BR.EmitBasicReport(AC->getDecl(), filter.checkName_bzero, + "Use of deprecated function in call to 'bzero()'", + "Security", + "The bzero() function is obsoleted by memset().", + CELoc, CE->getCallee()->getSourceRange()); +} + + +//===----------------------------------------------------------------------===// // Check: Any use of 'gets' is insecure. // Originally: <rdar://problem/6335715> // Implements (part of): 300-BSI (buildsecurityin.us-cert.gov) @@ -775,6 +913,9 @@ public: checker->filter.checkName_##name = mgr.getCurrentCheckName(); \ } +REGISTER_CHECKER(bcmp) +REGISTER_CHECKER(bcopy) +REGISTER_CHECKER(bzero) REGISTER_CHECKER(gets) REGISTER_CHECKER(getpw) REGISTER_CHECKER(mkstemp) |