summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.cpp
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2015-10-08 19:54:43 +0000
committerAaron Ballman <aaron@aaronballman.com>2015-10-08 19:54:43 +0000
commite4b1765a0f3254038ef998cfe99efb17dc47f514 (patch)
treee192cf032005598bec81a555e941728f5323397c /clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.cpp
parent1cbf51a41b8fa17825d8329c4c0f9779a6c056f4 (diff)
downloadbcm5719-llvm-e4b1765a0f3254038ef998cfe99efb17dc47f514.tar.gz
bcm5719-llvm-e4b1765a0f3254038ef998cfe99efb17dc47f514.zip
Adding a checker (cert-err52-cpp) that detects use of setjmp or longjmp in C++ code. Corresponds to the CERT C++ secure coding rule: https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=1834
llvm-svn: 249727
Diffstat (limited to 'clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.cpp77
1 files changed, 77 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.cpp b/clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.cpp
new file mode 100644
index 00000000000..bc5b35341f2
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cert/SetLongJmpCheck.cpp
@@ -0,0 +1,77 @@
+//===--- SetLongJmpCheck.cpp - clang-tidy----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SetLongJmpCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+
+const char SetLongJmpCheck::DiagWording[] =
+ "do not call %0; consider using exception handling instead";
+
+namespace {
+class SetJmpMacroCallbacks : public PPCallbacks {
+ SetLongJmpCheck &Check;
+
+public:
+ explicit SetJmpMacroCallbacks(SetLongJmpCheck &Check) : Check(Check) {}
+
+ void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range, const MacroArgs *Args) override {
+ const auto *II = MacroNameTok.getIdentifierInfo();
+ if (!II)
+ return;
+
+ if (II->getName() == "setjmp")
+ Check.diag(Range.getBegin(), Check.DiagWording) << II;
+ }
+};
+} // namespace
+
+void SetLongJmpCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+ // This checker only applies to C++, where exception handling is a superior
+ // solution to setjmp/longjmp calls.
+ if (!getLangOpts().CPlusPlus)
+ return;
+
+ // Per [headers]p5, setjmp must be exposed as a macro instead of a function,
+ // despite the allowance in C for setjmp to also be an extern function.
+ Compiler.getPreprocessor().addPPCallbacks(
+ llvm::make_unique<SetJmpMacroCallbacks>(*this));
+}
+
+void SetLongJmpCheck::registerMatchers(MatchFinder *Finder) {
+ // This checker only applies to C++, where exception handling is a superior
+ // solution to setjmp/longjmp calls.
+ if (!getLangOpts().CPlusPlus)
+ return;
+
+ // In case there is an implementation that happens to define setjmp as a
+ // function instead of a macro, this will also catch use of it. However, we
+ // are primarily searching for uses of longjmp.
+ Finder->addMatcher(callExpr(callee(functionDecl(anyOf(hasName("setjmp"),
+ hasName("longjmp")))))
+ .bind("expr"),
+ this);
+}
+
+void SetLongJmpCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *E = Result.Nodes.getNodeAs<CallExpr>("expr");
+ diag(E->getExprLoc(), DiagWording) << cast<NamedDecl>(E->getCalleeDecl());
+}
+
+} // namespace tidy
+} // namespace clang
OpenPOWER on IntegriCloud