|
@@ -37,6 +37,9 @@ static bool isArc4RandomAvailable(const ASTContext &Ctx) {
|
|
|
|
|
|
namespace {
|
|
namespace {
|
|
struct ChecksFilter {
|
|
struct ChecksFilter {
|
|
|
|
+ DefaultBool check_bcmp;
|
|
|
|
+ DefaultBool check_bcopy;
|
|
|
|
+ DefaultBool check_bzero;
|
|
DefaultBool check_gets;
|
|
DefaultBool check_gets;
|
|
DefaultBool check_getpw;
|
|
DefaultBool check_getpw;
|
|
DefaultBool check_mktemp;
|
|
DefaultBool check_mktemp;
|
|
@@ -47,6 +50,9 @@ struct ChecksFilter {
|
|
DefaultBool check_FloatLoopCounter;
|
|
DefaultBool check_FloatLoopCounter;
|
|
DefaultBool check_UncheckedReturn;
|
|
DefaultBool check_UncheckedReturn;
|
|
|
|
|
|
|
|
+ CheckName checkName_bcmp;
|
|
|
|
+ CheckName checkName_bcopy;
|
|
|
|
+ CheckName checkName_bzero;
|
|
CheckName checkName_gets;
|
|
CheckName checkName_gets;
|
|
CheckName checkName_getpw;
|
|
CheckName checkName_getpw;
|
|
CheckName checkName_mktemp;
|
|
CheckName checkName_mktemp;
|
|
@@ -89,6 +95,9 @@ public:
|
|
|
|
|
|
// Checker-specific methods.
|
|
// Checker-specific methods.
|
|
void checkLoopConditionForFloat(const ForStmt *FS);
|
|
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_gets(const CallExpr *CE, const FunctionDecl *FD);
|
|
void checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD);
|
|
void checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD);
|
|
void checkCall_mktemp(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.
|
|
// Set the evaluation function by switching on the callee name.
|
|
FnCheck evalFunction = llvm::StringSwitch<FnCheck>(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("gets", &WalkAST::checkCall_gets)
|
|
.Case("getpw", &WalkAST::checkCall_getpw)
|
|
.Case("getpw", &WalkAST::checkCall_getpw)
|
|
.Case("mktemp", &WalkAST::checkCall_mktemp)
|
|
.Case("mktemp", &WalkAST::checkCall_mktemp)
|
|
@@ -295,6 +307,132 @@ void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) {
|
|
FSLoc, ranges);
|
|
FSLoc, ranges);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+//===----------------------------------------------------------------------===//
|
|
|
|
+// 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.
|
|
// Check: Any use of 'gets' is insecure.
|
|
// Originally: <rdar://problem/6335715>
|
|
// Originally: <rdar://problem/6335715>
|
|
@@ -775,6 +913,9 @@ public:
|
|
checker->filter.checkName_##name = mgr.getCurrentCheckName(); \
|
|
checker->filter.checkName_##name = mgr.getCurrentCheckName(); \
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+REGISTER_CHECKER(bcmp)
|
|
|
|
+REGISTER_CHECKER(bcopy)
|
|
|
|
+REGISTER_CHECKER(bzero)
|
|
REGISTER_CHECKER(gets)
|
|
REGISTER_CHECKER(gets)
|
|
REGISTER_CHECKER(getpw)
|
|
REGISTER_CHECKER(getpw)
|
|
REGISTER_CHECKER(mkstemp)
|
|
REGISTER_CHECKER(mkstemp)
|