Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@ -0,0 +1,90 @@
//===--- CERTTidyModule.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 "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "../google/UnnamedNamespaceInHeaderCheck.h"
#include "../misc/NewDeleteOverloadsCheck.h"
#include "../misc/NonCopyableObjects.h"
#include "../misc/StaticAssertCheck.h"
#include "../misc/ThrowByValueCatchByReferenceCheck.h"
#include "../performance/MoveConstructorInitCheck.h"
#include "CommandProcessorCheck.h"
#include "DontModifyStdNamespaceCheck.h"
#include "FloatLoopCounter.h"
#include "LimitedRandomnessCheck.h"
#include "PostfixOperatorCheck.h"
#include "SetLongJmpCheck.h"
#include "StaticObjectExceptionCheck.h"
#include "StrToNumCheck.h"
#include "ThrownExceptionTypeCheck.h"
#include "VariadicFunctionDefCheck.h"
namespace clang {
namespace tidy {
namespace cert {
class CERTModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
// C++ checkers
// DCL
CheckFactories.registerCheck<PostfixOperatorCheck>(
"cert-dcl21-cpp");
CheckFactories.registerCheck<VariadicFunctionDefCheck>("cert-dcl50-cpp");
CheckFactories.registerCheck<misc::NewDeleteOverloadsCheck>(
"cert-dcl54-cpp");
CheckFactories.registerCheck<DontModifyStdNamespaceCheck>(
"cert-dcl58-cpp");
CheckFactories.registerCheck<google::build::UnnamedNamespaceInHeaderCheck>(
"cert-dcl59-cpp");
// OOP
CheckFactories.registerCheck<performance::MoveConstructorInitCheck>(
"cert-oop11-cpp");
// ERR
CheckFactories.registerCheck<misc::ThrowByValueCatchByReferenceCheck>(
"cert-err09-cpp");
CheckFactories.registerCheck<SetLongJmpCheck>("cert-err52-cpp");
CheckFactories.registerCheck<StaticObjectExceptionCheck>("cert-err58-cpp");
CheckFactories.registerCheck<ThrownExceptionTypeCheck>("cert-err60-cpp");
CheckFactories.registerCheck<misc::ThrowByValueCatchByReferenceCheck>(
"cert-err61-cpp");
// MSC
CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc50-cpp");
// C checkers
// DCL
CheckFactories.registerCheck<misc::StaticAssertCheck>("cert-dcl03-c");
// ENV
CheckFactories.registerCheck<CommandProcessorCheck>("cert-env33-c");
// FLP
CheckFactories.registerCheck<FloatLoopCounter>("cert-flp30-c");
// FIO
CheckFactories.registerCheck<misc::NonCopyableObjectsCheck>("cert-fio38-c");
// ERR
CheckFactories.registerCheck<StrToNumCheck>("cert-err34-c");
// MSC
CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc30-c");
}
};
} // namespace cert
// Register the MiscTidyModule using this statically initialized variable.
static ClangTidyModuleRegistry::Add<cert::CERTModule>
X("cert-module",
"Adds lint checks corresponding to CERT secure coding guidelines.");
// This anchor is used to force the linker to link in the generated object file
// and thus register the CERTModule.
volatile int CERTModuleAnchorSource = 0;
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,27 @@
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyCERTModule
CERTTidyModule.cpp
CommandProcessorCheck.cpp
DontModifyStdNamespaceCheck.cpp
FloatLoopCounter.cpp
LimitedRandomnessCheck.cpp
PostfixOperatorCheck.cpp
SetLongJmpCheck.cpp
StaticObjectExceptionCheck.cpp
StrToNumCheck.cpp
ThrownExceptionTypeCheck.cpp
VariadicFunctionDefCheck.cpp
LINK_LIBS
clangAnalysis
clangAST
clangASTMatchers
clangBasic
clangLex
clangTidy
clangTidyGoogleModule
clangTidyMiscModule
clangTidyPerformanceModule
clangTidyUtils
)

View File

@ -0,0 +1,45 @@
//===--- Env33CCheck.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 "CommandProcessorCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace cert {
void CommandProcessorCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
callExpr(
callee(functionDecl(anyOf(hasName("::system"), hasName("::popen"),
hasName("::_popen")))
.bind("func")),
// Do not diagnose when the call expression passes a null pointer
// constant to system(); that only checks for the presence of a
// command processor, which is not a security risk by itself.
unless(callExpr(callee(functionDecl(hasName("::system"))),
argumentCountIs(1),
hasArgument(0, nullPointerConstant()))))
.bind("expr"),
this);
}
void CommandProcessorCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Fn = Result.Nodes.getNodeAs<FunctionDecl>("func");
const auto *E = Result.Nodes.getNodeAs<CallExpr>("expr");
diag(E->getExprLoc(), "calling %0 uses a command processor") << Fn;
}
} // namespace cert
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,38 @@
//===--- CommandInterpreterCheck.h - clang-tidy------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_COMMAND_PROCESSOR_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_COMMAND_PROCESSOR_CHECK_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace cert {
/// Execution of a command processor can lead to security vulnerabilities,
/// and is generally not required. Instead, prefer to launch executables
/// directly via mechanisms that give you more control over what executable is
/// actually launched.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/cert-env33-c.html
class CommandProcessorCheck : public ClangTidyCheck {
public:
CommandProcessorCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace cert
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_COMMAND_PROCESSOR_CHECK_H

View File

@ -0,0 +1,49 @@
//===--- DontModifyStdNamespaceCheck.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 "DontModifyStdNamespaceCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace cert {
void DontModifyStdNamespaceCheck::registerMatchers(MatchFinder *Finder) {
if (!getLangOpts().CPlusPlus)
return;
Finder->addMatcher(
namespaceDecl(unless(isExpansionInSystemHeader()),
anyOf(hasName("std"), hasName("posix")),
has(decl(unless(anyOf(
functionDecl(isExplicitTemplateSpecialization()),
cxxRecordDecl(isExplicitTemplateSpecialization()))))))
.bind("nmspc"),
this);
}
void DontModifyStdNamespaceCheck::check(
const MatchFinder::MatchResult &Result) {
const auto *N = Result.Nodes.getNodeAs<NamespaceDecl>("nmspc");
// Only consider top level namespaces.
if (N->getParent() != Result.Context->getTranslationUnitDecl())
return;
diag(N->getLocation(),
"modification of %0 namespace can result in undefined behavior")
<< N;
}
} // namespace cert
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,36 @@
//===--- DontModifyStdNamespaceCheck.h - clang-tidy--------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DONT_MODIFY_STD_NAMESPACE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DONT_MODIFY_STD_NAMESPACE_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace cert {
/// Modification of the std or posix namespace can result in undefined behavior.
/// This check warns for such modifications.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/cert-msc53-cpp.html
class DontModifyStdNamespaceCheck : public ClangTidyCheck {
public:
DontModifyStdNamespaceCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace cert
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DONT_MODIFY_STD_NAMESPACE_H

View File

@ -0,0 +1,35 @@
//===--- FloatLoopCounter.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 "FloatLoopCounter.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace cert {
void FloatLoopCounter::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
forStmt(hasIncrement(expr(hasType(realFloatingPointType())))).bind("for"),
this);
}
void FloatLoopCounter::check(const MatchFinder::MatchResult &Result) {
const auto *FS = Result.Nodes.getNodeAs<ForStmt>("for");
diag(FS->getInc()->getExprLoc(), "loop induction expression should not have "
"floating-point type");
}
} // namespace cert
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,37 @@
//===--- FloatLoopCounter.h - clang-tidy-------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_FLOAT_LOOP_COUNTER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_FLOAT_LOOP_COUNTER_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace cert {
/// This check diagnoses when the loop induction expression of a for loop has
/// floating-point type. The check corresponds to:
/// https://www.securecoding.cert.org/confluence/display/c/FLP30-C.+Do+not+use+floating-point+variables+as+loop+counters
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/cert-flp30-c.html
class FloatLoopCounter : public ClangTidyCheck {
public:
FloatLoopCounter(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace cert
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_FLOAT_LOOP_COUNTER_H

View File

@ -0,0 +1,22 @@
------------------------------------------------------------------------------
clang-tidy CERT Files
------------------------------------------------------------------------------
All clang-tidy files are licensed under the LLVM license with the following
additions:
Any file referencing a CERT Secure Coding guideline:
Please allow this letter to serve as confirmation that open source projects on
http://llvm.org are permitted to link via hypertext to the CERT(R) secure coding
guidelines available at https://www.securecoding.cert.org.
The foregoing is permitted by the Terms of Use as follows:
"Linking to the Service
Because we update many of our Web documents regularly, we would prefer that you
link to our Web pages whenever possible rather than reproduce them. It is not
necessary to request permission to make referential hypertext links to The
Service."
http://www.sei.cmu.edu/legal/ip/index.cfm.
Please allow this letter to also confirm that no formal permission is required
to reproduce the title of the content being linked to, nor to reproduce any
de Minimis description of such content.

View File

@ -0,0 +1,38 @@
//===--- LimitedRandomnessCheck.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 "LimitedRandomnessCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace cert {
void LimitedRandomnessCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(callExpr(callee(functionDecl(namedDecl(hasName("::rand")),
parameterCountIs(0))))
.bind("randomGenerator"),
this);
}
void LimitedRandomnessCheck::check(const MatchFinder::MatchResult &Result) {
std::string msg = "";
if (getLangOpts().CPlusPlus)
msg = "; use C++11 random library instead";
const auto *MatchedDecl = Result.Nodes.getNodeAs<CallExpr>("randomGenerator");
diag(MatchedDecl->getLocStart(), "rand() has limited randomness" + msg);
}
} // namespace cert
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,38 @@
//===--- LimitedRandomnessCheck.h - clang-tidy-------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_LIMITED_RANDOMNESS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_LIMITED_RANDOMNESS_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace cert {
/// Pseudorandom number generators are not genuinely random. The result of the
/// std::rand() function makes no guarantees as to the quality of the random
/// sequence produced.
/// This check warns for the usage of std::rand() function.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/cert-msc50-cpp.html
class LimitedRandomnessCheck : public ClangTidyCheck {
public:
LimitedRandomnessCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace cert
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_LIMITED_RANDOMNESS_H

View File

@ -0,0 +1,88 @@
//===--- PostfixOperatorCheck.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 "PostfixOperatorCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace cert {
void PostfixOperatorCheck::registerMatchers(MatchFinder *Finder) {
if (!getLangOpts().CPlusPlus)
return;
Finder->addMatcher(functionDecl(anyOf(hasOverloadedOperatorName("++"),
hasOverloadedOperatorName("--")))
.bind("decl"),
this);
}
void PostfixOperatorCheck::check(const MatchFinder::MatchResult &Result) {
const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("decl");
bool HasThis = false;
if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl))
HasThis = MethodDecl->isInstance();
// Check if the operator is a postfix one.
if (FuncDecl->getNumParams() != (HasThis ? 1 : 2))
return;
SourceRange ReturnRange = FuncDecl->getReturnTypeSourceRange();
SourceLocation Location = ReturnRange.getBegin();
if (!Location.isValid())
return;
QualType ReturnType = FuncDecl->getReturnType();
// Warn when the operators return a reference.
if (const auto *RefType = ReturnType->getAs<ReferenceType>()) {
auto Diag = diag(Location, "overloaded %0 returns a reference instead of a "
"constant object type")
<< FuncDecl;
if (Location.isMacroID() || ReturnType->getAs<TypedefType>() ||
RefType->getPointeeTypeAsWritten()->getAs<TypedefType>())
return;
QualType ReplaceType =
ReturnType.getNonReferenceType().getLocalUnqualifiedType();
// The getReturnTypeSourceRange omits the qualifiers. We do not want to
// duplicate the const.
if (!ReturnType->getPointeeType().isConstQualified())
ReplaceType.addConst();
Diag << FixItHint::CreateReplacement(
ReturnRange,
ReplaceType.getAsString(Result.Context->getPrintingPolicy()) + " ");
return;
}
if (ReturnType.isConstQualified() || ReturnType->isBuiltinType() ||
ReturnType->isPointerType())
return;
auto Diag =
diag(Location, "overloaded %0 returns a non-constant object instead of a "
"constant object type")
<< FuncDecl;
if (!Location.isMacroID() && !ReturnType->getAs<TypedefType>())
Diag << FixItHint::CreateInsertion(Location, "const ");
}
} // namespace cert
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,36 @@
//===--- PostfixOperatorCheck.h - clang-tidy---------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_POSTFIX_OPERATOR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_POSTFIX_OPERATOR_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace cert {
/// Checks if the overloaded postfix ++ and -- operator return a constant
/// object.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/cert-postfix-operator.html
class PostfixOperatorCheck : public ClangTidyCheck {
public:
PostfixOperatorCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace cert
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_POSTFIX_OPERATOR_H

View File

@ -0,0 +1,79 @@
//===--- 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 {
namespace cert {
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 cert
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,38 @@
//===--- SetLongJmpCheck.h - clang-tidy--------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SETLONGJMPCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SETLONGJMPCHECK_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace cert {
/// Guards against use of setjmp/longjmp in C++ code
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/cert-err52-cpp.html
class SetLongJmpCheck : public ClangTidyCheck {
public:
SetLongJmpCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
void registerPPCallbacks(CompilerInstance &Compiler) override;
static const char DiagWording[];
};
} // namespace cert
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SETLONGJMPCHECK_H

View File

@ -0,0 +1,60 @@
//===--- StaticObjectExceptionCheck.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 "StaticObjectExceptionCheck.h"
#include "../utils/Matchers.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace cert {
void StaticObjectExceptionCheck::registerMatchers(MatchFinder *Finder) {
if ((!getLangOpts().CPlusPlus) || (!getLangOpts().CXXExceptions))
return;
// Match any static or thread_local variable declaration that has an
// initializer that can throw.
Finder->addMatcher(
varDecl(anyOf(hasThreadStorageDuration(), hasStaticStorageDuration()),
unless(hasAncestor(functionDecl())),
anyOf(hasDescendant(cxxConstructExpr(hasDeclaration(
cxxConstructorDecl(unless(isNoThrow())).bind("func")))),
hasDescendant(cxxNewExpr(hasDeclaration(
functionDecl(unless(isNoThrow())).bind("func")))),
hasDescendant(callExpr(hasDeclaration(
functionDecl(unless(isNoThrow())).bind("func"))))))
.bind("var"),
this);
}
void StaticObjectExceptionCheck::check(const MatchFinder::MatchResult &Result) {
const auto *VD = Result.Nodes.getNodeAs<VarDecl>("var");
const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");
diag(VD->getLocation(),
"initialization of %0 with %select{static|thread_local}1 storage "
"duration may throw an exception that cannot be caught")
<< VD << (VD->getStorageDuration() == SD_Static ? 0 : 1);
SourceLocation FuncLocation = Func->getLocation();
if (FuncLocation.isValid()) {
diag(FuncLocation,
"possibly throwing %select{constructor|function}0 declared here",
DiagnosticIDs::Note)
<< (isa<CXXConstructorDecl>(Func) ? 0 : 1);
}
}
} // namespace cert
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,36 @@
//===--- StaticObjectExceptionCheck.h - clang-tidy---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_ERR58_CPP_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_ERR58_CPP_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace cert {
/// Checks whether the constructor for a static or thread_local object will
/// throw.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/cert-err58-cpp.html
class StaticObjectExceptionCheck : public ClangTidyCheck {
public:
StaticObjectExceptionCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace cert
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_ERR58_CPP_H

View File

@ -0,0 +1,235 @@
//===--- Err34CCheck.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 "StrToNumCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Analysis/Analyses/FormatString.h"
#include "llvm/ADT/StringSwitch.h"
#include <cassert>
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace cert {
void StrToNumCheck::registerMatchers(MatchFinder *Finder) {
// Match any function call to the C standard library string conversion
// functions that do no error checking.
Finder->addMatcher(
callExpr(
callee(functionDecl(anyOf(
functionDecl(hasAnyName("::atoi", "::atof", "::atol", "::atoll"))
.bind("converter"),
functionDecl(hasAnyName("::scanf", "::sscanf", "::fscanf",
"::vfscanf", "::vscanf", "::vsscanf"))
.bind("formatted")))))
.bind("expr"),
this);
}
namespace {
enum class ConversionKind {
None,
ToInt,
ToUInt,
ToLongInt,
ToLongUInt,
ToIntMax,
ToUIntMax,
ToFloat,
ToDouble,
ToLongDouble
};
ConversionKind ClassifyConversionFunc(const FunctionDecl *FD) {
return llvm::StringSwitch<ConversionKind>(FD->getName())
.Cases("atoi", "atol", ConversionKind::ToInt)
.Case("atoll", ConversionKind::ToLongInt)
.Case("atof", ConversionKind::ToDouble)
.Default(ConversionKind::None);
}
ConversionKind ClassifyFormatString(StringRef Fmt, const LangOptions &LO,
const TargetInfo &TI) {
// Scan the format string for the first problematic format specifier, then
// report that as the conversion type. This will miss additional conversion
// specifiers, but that is acceptable behavior.
class Handler : public analyze_format_string::FormatStringHandler {
ConversionKind CK;
bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) override {
// If we just consume the argument without assignment, we don't care
// about it having conversion errors.
if (!FS.consumesDataArgument())
return true;
// Get the conversion specifier and use it to determine the conversion
// kind.
analyze_scanf::ScanfConversionSpecifier SCS = FS.getConversionSpecifier();
if (SCS.isIntArg()) {
switch (FS.getLengthModifier().getKind()) {
case analyze_scanf::LengthModifier::AsLongLong:
CK = ConversionKind::ToLongInt;
break;
case analyze_scanf::LengthModifier::AsIntMax:
CK = ConversionKind::ToIntMax;
break;
default:
CK = ConversionKind::ToInt;
break;
}
} else if (SCS.isUIntArg()) {
switch (FS.getLengthModifier().getKind()) {
case analyze_scanf::LengthModifier::AsLongLong:
CK = ConversionKind::ToLongUInt;
break;
case analyze_scanf::LengthModifier::AsIntMax:
CK = ConversionKind::ToUIntMax;
break;
default:
CK = ConversionKind::ToUInt;
break;
}
} else if (SCS.isDoubleArg()) {
switch (FS.getLengthModifier().getKind()) {
case analyze_scanf::LengthModifier::AsLongDouble:
CK = ConversionKind::ToLongDouble;
break;
case analyze_scanf::LengthModifier::AsLong:
CK = ConversionKind::ToDouble;
break;
default:
CK = ConversionKind::ToFloat;
break;
}
}
// Continue if we have yet to find a conversion kind that we care about.
return CK == ConversionKind::None;
}
public:
Handler() : CK(ConversionKind::None) {}
ConversionKind get() const { return CK; }
};
Handler H;
analyze_format_string::ParseScanfString(H, Fmt.begin(), Fmt.end(), LO, TI);
return H.get();
}
StringRef ClassifyConversionType(ConversionKind K) {
switch (K) {
case ConversionKind::None:
assert(false && "Unexpected conversion kind");
case ConversionKind::ToInt:
case ConversionKind::ToLongInt:
case ConversionKind::ToIntMax:
return "an integer value";
case ConversionKind::ToUInt:
case ConversionKind::ToLongUInt:
case ConversionKind::ToUIntMax:
return "an unsigned integer value";
case ConversionKind::ToFloat:
case ConversionKind::ToDouble:
case ConversionKind::ToLongDouble:
return "a floating-point value";
}
llvm_unreachable("Unknown conversion kind");
}
StringRef ClassifyReplacement(ConversionKind K) {
switch (K) {
case ConversionKind::None:
assert(false && "Unexpected conversion kind");
case ConversionKind::ToInt:
return "strtol";
case ConversionKind::ToUInt:
return "strtoul";
case ConversionKind::ToIntMax:
return "strtoimax";
case ConversionKind::ToLongInt:
return "strtoll";
case ConversionKind::ToLongUInt:
return "strtoull";
case ConversionKind::ToUIntMax:
return "strtoumax";
case ConversionKind::ToFloat:
return "strtof";
case ConversionKind::ToDouble:
return "strtod";
case ConversionKind::ToLongDouble:
return "strtold";
}
llvm_unreachable("Unknown conversion kind");
}
} // unnamed namespace
void StrToNumCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Call = Result.Nodes.getNodeAs<CallExpr>("expr");
const FunctionDecl *FuncDecl = nullptr;
ConversionKind Conversion;
if (const auto *ConverterFunc =
Result.Nodes.getNodeAs<FunctionDecl>("converter")) {
// Converter functions are always incorrect to use.
FuncDecl = ConverterFunc;
Conversion = ClassifyConversionFunc(ConverterFunc);
} else if (const auto *FFD =
Result.Nodes.getNodeAs<FunctionDecl>("formatted")) {
StringRef FmtStr;
// The format string comes from the call expression and depends on which
// flavor of scanf is called.
// Index 0: scanf, vscanf, Index 1: fscanf, sscanf, vfscanf, vsscanf.
unsigned Idx =
(FFD->getName() == "scanf" || FFD->getName() == "vscanf") ? 0 : 1;
// Given the index, see if the call expression argument at that index is
// a string literal.
if (Call->getNumArgs() < Idx)
return;
if (const Expr *Arg = Call->getArg(Idx)->IgnoreParenImpCasts()) {
if (const auto *SL = dyn_cast<StringLiteral>(Arg)) {
FmtStr = SL->getString();
}
}
// If we could not get the format string, bail out.
if (FmtStr.empty())
return;
// Formatted input functions need further checking of the format string to
// determine whether a problematic conversion may be happening.
Conversion = ClassifyFormatString(FmtStr, getLangOpts(),
Result.Context->getTargetInfo());
if (Conversion != ConversionKind::None)
FuncDecl = FFD;
}
if (!FuncDecl)
return;
diag(Call->getExprLoc(),
"%0 used to convert a string to %1, but function will not report "
"conversion errors; consider using '%2' instead")
<< FuncDecl << ClassifyConversionType(Conversion)
<< ClassifyReplacement(Conversion);
}
} // namespace cert
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,36 @@
//===--- StrToNumCheck.h - clang-tidy----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_STRTONUMCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_STRTONUMCHECK_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace cert {
/// Guards against use of string conversion functions that do not have
/// reasonable error handling for conversion errors.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/cert-err34-c.html
class StrToNumCheck : public ClangTidyCheck {
public:
StrToNumCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace cert
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_STRTONUMCHECK_H

View File

@ -0,0 +1,41 @@
//===--- ThrownExceptionTypeCheck.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 "ThrownExceptionTypeCheck.h"
#include "../utils/Matchers.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace cert {
void ThrownExceptionTypeCheck::registerMatchers(MatchFinder *Finder) {
if (!getLangOpts().CPlusPlus)
return;
Finder->addMatcher(
cxxThrowExpr(has(ignoringParenImpCasts(
cxxConstructExpr(hasDeclaration(cxxConstructorDecl(
isCopyConstructor(), unless(isNoThrow()))))
.bind("expr")))),
this);
}
void ThrownExceptionTypeCheck::check(const MatchFinder::MatchResult &Result) {
const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
diag(E->getExprLoc(),
"thrown exception type is not nothrow copy constructible");
}
} // namespace cert
} // namespace tidy
} // namespace clang

Some files were not shown because too many files have changed in this diff Show More