Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: Fix an issue for windows. Differential Revision: https://reviews.llvm.org/D35372 llvm-svn: 310669
- Loading branch information
1 parent
8d719a2
commit b21739f
Showing
10 changed files
with
360 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
//===--- CloexecCheck.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 "CloexecCheck.h" | ||
#include "../utils/ASTUtils.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 android { | ||
|
||
namespace { | ||
|
||
const char *const FuncDeclBindingStr = "funcDecl"; | ||
const char *const FuncBindingStr = "func"; | ||
|
||
// Helper function to form the correct string mode for Type3. | ||
// Build the replace text. If it's string constant, add <Mode> directly in the | ||
// end of the string. Else, add <Mode>. | ||
std::string buildFixMsgForStringFlag(const Expr *Arg, const SourceManager &SM, | ||
const LangOptions &LangOpts, char Mode) { | ||
if (Arg->getLocStart().isMacroID()) | ||
return (Lexer::getSourceText( | ||
CharSourceRange::getTokenRange(Arg->getSourceRange()), SM, | ||
LangOpts) + | ||
" \"" + Twine(Mode) + "\"") | ||
.str(); | ||
|
||
StringRef SR = cast<StringLiteral>(Arg->IgnoreParenCasts())->getString(); | ||
return ("\"" + SR + Twine(Mode) + "\"").str(); | ||
} | ||
} // namespace | ||
|
||
void CloexecCheck::registerMatchersImpl( | ||
MatchFinder *Finder, internal::Matcher<FunctionDecl> Function) { | ||
// We assume all the checked APIs are C functions. | ||
Finder->addMatcher( | ||
callExpr( | ||
callee(functionDecl(isExternC(), Function).bind(FuncDeclBindingStr))) | ||
.bind(FuncBindingStr), | ||
this); | ||
} | ||
|
||
void CloexecCheck::insertMacroFlag(const MatchFinder::MatchResult &Result, | ||
StringRef MacroFlag, int ArgPos) { | ||
const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(FuncBindingStr); | ||
const auto *FlagArg = MatchedCall->getArg(ArgPos); | ||
const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>(FuncDeclBindingStr); | ||
SourceManager &SM = *Result.SourceManager; | ||
|
||
if (utils::exprHasBitFlagWithSpelling(FlagArg->IgnoreParenCasts(), SM, | ||
Result.Context->getLangOpts(), | ||
MacroFlag)) | ||
return; | ||
|
||
SourceLocation EndLoc = | ||
Lexer::getLocForEndOfToken(SM.getFileLoc(FlagArg->getLocEnd()), 0, SM, | ||
Result.Context->getLangOpts()); | ||
|
||
diag(EndLoc, "%0 should use %1 where possible") | ||
<< FD << MacroFlag | ||
<< FixItHint::CreateInsertion(EndLoc, (Twine(" | ") + MacroFlag).str()); | ||
} | ||
|
||
void CloexecCheck::replaceFunc(const MatchFinder::MatchResult &Result, | ||
StringRef WarningMsg, StringRef FixMsg) { | ||
const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(FuncBindingStr); | ||
diag(MatchedCall->getLocStart(), WarningMsg) | ||
<< FixItHint::CreateReplacement(MatchedCall->getSourceRange(), FixMsg); | ||
} | ||
|
||
void CloexecCheck::insertStringFlag( | ||
const ast_matchers::MatchFinder::MatchResult &Result, const char Mode, | ||
const int ArgPos) { | ||
const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(FuncBindingStr); | ||
const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>(FuncDeclBindingStr); | ||
const auto *ModeArg = MatchedCall->getArg(ArgPos); | ||
|
||
// Check if the <Mode> may be in the mode string. | ||
const auto *ModeStr = dyn_cast<StringLiteral>(ModeArg->IgnoreParenCasts()); | ||
if (!ModeStr || (ModeStr->getString().find(Mode) != StringRef::npos)) | ||
return; | ||
|
||
const std::string &ReplacementText = buildFixMsgForStringFlag( | ||
ModeArg, *Result.SourceManager, Result.Context->getLangOpts(), Mode); | ||
|
||
diag(ModeArg->getLocStart(), "use %0 mode '%1' to set O_CLOEXEC") | ||
<< FD << std::string(1, Mode) | ||
<< FixItHint::CreateReplacement(ModeArg->getSourceRange(), | ||
ReplacementText); | ||
} | ||
|
||
} // namespace android | ||
} // namespace tidy | ||
} // namespace clang |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
//===--- CloexecCheck.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. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
/// | ||
/// \file | ||
/// This file contains the declaration of the CloexecCheck class, which is the | ||
/// base class for all of the close-on-exec checks in Android module. | ||
/// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_H | ||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_H | ||
|
||
#include "../ClangTidy.h" | ||
|
||
namespace clang { | ||
namespace tidy { | ||
namespace android { | ||
|
||
/// \brief The base class for all close-on-exec checks in Android module. | ||
/// To be specific, there are some functions that need the close-on-exec flag to | ||
/// prevent the file descriptor leakage on fork+exec and this class provides | ||
/// utilities to identify and fix these C functions. | ||
class CloexecCheck : public ClangTidyCheck { | ||
public: | ||
CloexecCheck(StringRef Name, ClangTidyContext *Context) | ||
: ClangTidyCheck(Name, Context) {} | ||
|
||
protected: | ||
void | ||
registerMatchersImpl(ast_matchers::MatchFinder *Finder, | ||
ast_matchers::internal::Matcher<FunctionDecl> Function); | ||
|
||
/// Currently, we have three types of fixes. | ||
/// | ||
/// Type1 is to insert the necessary macro flag in the flag argument. For | ||
/// example, 'O_CLOEXEC' is required in function 'open()', so | ||
/// \code | ||
/// open(file, O_RDONLY); | ||
/// \endcode | ||
/// should be | ||
/// \code | ||
/// open(file, O_RDONLY | O_CLOEXE); | ||
/// \endcode | ||
/// | ||
/// \param [out] Result MatchResult from AST matcher. | ||
/// \param MacroFlag The macro name of the flag. | ||
/// \param ArgPos The 0-based position of the flag argument. | ||
void insertMacroFlag(const ast_matchers::MatchFinder::MatchResult &Result, | ||
StringRef MarcoFlag, int ArgPos); | ||
|
||
/// Type2 is to replace the API to another function that has required the | ||
/// ability. For example: | ||
/// \code | ||
/// creat(path, mode); | ||
/// \endcode | ||
/// should be | ||
/// \code | ||
/// open(path, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, mode) | ||
/// \endcode | ||
/// | ||
/// \param [out] Result MatchResult from AST matcher. | ||
/// \param WarningMsg The warning message. | ||
/// \param FixMsg The fix message. | ||
void replaceFunc(const ast_matchers::MatchFinder::MatchResult &Result, | ||
StringRef WarningMsg, StringRef FixMsg); | ||
|
||
/// Type3 is also to add a flag to the corresponding argument, but this time, | ||
/// the flag is some string and each char represents a mode rather than a | ||
/// macro. For example, 'fopen' needs char 'e' in its mode argument string, so | ||
/// \code | ||
/// fopen(in_file, "r"); | ||
/// \endcode | ||
/// should be | ||
/// \code | ||
/// fopen(in_file, "re"); | ||
/// \endcode | ||
/// | ||
/// \param [out] Result MatchResult from AST matcher. | ||
/// \param Mode The required mode char. | ||
/// \param ArgPos The 0-based position of the flag argument. | ||
void insertStringFlag(const ast_matchers::MatchFinder::MatchResult &Result, | ||
const char Mode, const int ArgPos); | ||
}; | ||
|
||
} // namespace android | ||
} // namespace tidy | ||
} // namespace clang | ||
|
||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_H |
32 changes: 32 additions & 0 deletions
32
clang-tools-extra/clang-tidy/android/CloexecMemfdCreateCheck.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
//===--- CloexecMemfdCreateCheck.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 "CloexecMemfdCreateCheck.h" | ||
|
||
using namespace clang::ast_matchers; | ||
|
||
namespace clang { | ||
namespace tidy { | ||
namespace android { | ||
|
||
void CloexecMemfdCreateCheck::registerMatchers(MatchFinder *Finder) { | ||
auto CharPointerType = hasType(pointerType(pointee(isAnyCharacter()))); | ||
registerMatchersImpl( | ||
Finder, functionDecl(returns(isInteger()), hasName("memfd_create"), | ||
hasParameter(0, CharPointerType), | ||
hasParameter(1, hasType(isInteger())))); | ||
} | ||
|
||
void CloexecMemfdCreateCheck::check(const MatchFinder::MatchResult &Result) { | ||
insertMacroFlag(Result, "MFD_CLOEXEC", /*ArgPos=*/1); | ||
} | ||
|
||
} // namespace android | ||
} // namespace tidy | ||
} // namespace clang |
35 changes: 35 additions & 0 deletions
35
clang-tools-extra/clang-tidy/android/CloexecMemfdCreateCheck.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
//===--- CloexecMemfdCreateCheck.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_ANDROID_CLOEXEC_MEMFD_CREATE_H | ||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_MEMFD_CREATE_H | ||
|
||
#include "CloexecCheck.h" | ||
|
||
namespace clang { | ||
namespace tidy { | ||
namespace android { | ||
|
||
/// Finds code that uses memfd_create() without using the MFD_CLOEXEC flag. | ||
/// | ||
/// For the user-facing documentation see: | ||
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-memfd-create.html | ||
class CloexecMemfdCreateCheck : public CloexecCheck { | ||
public: | ||
CloexecMemfdCreateCheck(StringRef Name, ClangTidyContext *Context) | ||
: CloexecCheck(Name, Context) {} | ||
void registerMatchers(ast_matchers::MatchFinder *Finder) override; | ||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override; | ||
}; | ||
|
||
} // namespace android | ||
} // namespace tidy | ||
} // namespace clang | ||
|
||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_MEMFD_CREATE_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
clang-tools-extra/docs/clang-tidy/checks/android-cloexec-memfd-create.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
.. title:: clang-tidy - android-cloexec-memfd-create | ||
|
||
android-cloexec-memfd-create | ||
============================ | ||
|
||
``memfd_create()`` should include ``MFD_CLOEXEC`` in its type argument to avoid | ||
the file descriptor leakage. Without this flag, an opened sensitive file would | ||
remain open across a fork+exec to a lower-privileged SELinux domain. | ||
|
||
Examples: | ||
|
||
.. code-block:: c++ | ||
|
||
memfd_create(name, MFD_ALLOW_SEALING); | ||
|
||
// becomes | ||
|
||
memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.