Bug 1440886 - Implement a static analysis checker to detect usage of PR_LoadLibrary and LoadLibraryA/LoadLibraryExA/LoadLibrary/LoadLibraryEx. r=Nika

MozReview-Commit-ID: CUjfeBeOdsk

--HG--
extra : rebase_source : 633b900794cba24030c2b93d4d070d1447fff39b
This commit is contained in:
Andi-Bogdan Postelnicu 2018-03-07 14:36:44 +02:00
parent 87f933ff63
commit c523c8faa9
8 changed files with 93 additions and 2 deletions

View File

@ -11,6 +11,9 @@ CHECK(DanglingOnTemporaryChecker, "dangling-on-temporary")
CHECK(ExplicitImplicitChecker, "implicit-constructor")
CHECK(ExplicitOperatorBoolChecker, "explicit-operator-bool")
CHECK(KungFuDeathGripChecker, "kungfu-death-grip")
#ifdef _WIN32
CHECK(LoadLibraryUsageChecker, "load-library-usage")
#endif
CHECK(MustOverrideChecker, "must-override")
CHECK(MustReturnFromCallerChecker, "must-return-from-caller")
CHECK(MustUseChecker, "must-use")

View File

@ -11,6 +11,9 @@
#include "DanglingOnTemporaryChecker.h"
#include "ExplicitImplicitChecker.h"
#include "ExplicitOperatorBoolChecker.h"
#ifdef _WIN32
#include "LoadLibraryUsageChecker.h"
#endif
#include "KungFuDeathGripChecker.h"
#include "MustOverrideChecker.h"
#include "MustReturnFromCallerChecker.h"

View File

@ -0,0 +1,34 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "LoadLibraryUsageChecker.h"
#include "CustomMatchers.h"
// On MacOS the filesystem is UTF-8, on linux the canonical filename is 8-bit
// string. On Windows data loss conversion will occur. This checker restricts
// the use of ASCII file functions for loading libraries.
void LoadLibraryUsageChecker::registerMatchers(MatchFinder *AstMatcher) {
AstMatcher->addMatcher(
callExpr(
allOf(isFirstParty(),
callee(functionDecl(anyOf(
allOf(isInSystemHeader(), anyOf(hasName("LoadLibraryA"),
hasName("LoadLibraryExA"))),
hasName("PR_LoadLibrary")))),
unless(hasArgument(0, stringLiteral()))))
.bind("funcCall"),
this);
}
void LoadLibraryUsageChecker::check(const MatchFinder::MatchResult &Result) {
const CallExpr *FuncCall = Result.Nodes.getNodeAs<CallExpr>("funcCall");
if (FuncCall) {
diag(FuncCall->getLocStart(),
"Usage of ASCII file functions (such as %0) is forbidden.",
DiagnosticIDs::Error)
<< FuncCall->getDirectCallee()->getName();
}
}

View File

@ -0,0 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef LoadLibraryUsageChecker_h__
#define LoadLibraryUsageChecker_h__
#include "plugin.h"
class LoadLibraryUsageChecker : public BaseCheck {
public:
LoadLibraryUsageChecker(StringRef CheckName, ContextType *Context = nullptr)
: BaseCheck(CheckName, Context) {}
void registerMatchers(MatchFinder *AstMatcher) override;
void check(const MatchFinder::MatchResult &Result) override;
};
#endif // !defined(LoadLibraryUsageChecker_h__)

View File

@ -428,8 +428,11 @@ inline bool inThirdPartyPath(const Decl *D) {
inline bool inThirdPartyPath(const Stmt *S, ASTContext *context) {
SourceLocation Loc = S->getLocStart();
const SourceManager &SM = context->getSourceManager();
return inThirdPartyPath(Loc, SM);
auto ExpansionLoc = SM.getExpansionLoc(Loc);
if (ExpansionLoc.isInvalid()) {
return inThirdPartyPath(Loc, SM);
}
return inThirdPartyPath(ExpansionLoc, SM);
}
/// Polyfill for CXXOperatorCallExpr::isInfixBinaryOp()

View File

@ -42,6 +42,11 @@ UNIFIED_SOURCES += [
'VariableUsageHelpers.cpp',
]
if CONFIG['OS_ARCH'] == 'WINNT':
UNIFIED_SOURCES += [
'LoadLibraryUsageChecker.cpp',
]
if CONFIG['ENABLE_MOZSEARCH_PLUGIN']:
UNIFIED_SOURCES += [
'mozsearch-plugin/FileOperations.cpp',

View File

@ -0,0 +1,20 @@
#include <windows.h>
#include "prlink.h"
void Func() {
auto h1 = PR_LoadLibrary(nullptr); // expected-error {{Usage of ASCII file functions (such as PR_LoadLibrary) is forbidden.}}
auto h2 = PR_LoadLibrary("C:\\Some\\Path");
auto h3 = LoadLibraryA(nullptr); // expected-error {{Usage of ASCII file functions (such as LoadLibraryA) is forbidden.}}
auto h4 = LoadLibraryA("C:\\Some\\Path");
auto h5 = LoadLibraryExA(nullptr, nullptr, 0); // expected-error {{Usage of ASCII file functions (such as LoadLibraryExA) is forbidden.}}
auto h6 = LoadLibraryExA("C:\\Some\\Path", nullptr, 0);
#ifndef UNICODE
// LoadLibrary is a defnine for LoadLibraryA
auto h7 = LoadLibrary(nullptr); // expected-error {{Usage of ASCII file functions (such as LoadLibraryA) is forbidden.}}
auto h8 = LoadLibrary("C:\\Some\\Path");
// LoadLibraryEx is a define for LoadLibraryExA
auto h9 = LoadLibraryEx(nullptr, nullptr, 0); // expected-error {{Usage of ASCII file functions (such as LoadLibraryExA) is forbidden.}}
auto h10 = LoadLibraryEx("C:\\Some\\Path", nullptr, 0);
#endif
}

View File

@ -47,6 +47,11 @@ SOURCES += [
'TestTrivialCtorDtor.cpp',
]
if CONFIG['OS_ARCH'] == 'WINNT':
SOURCES += [
'TestLoadLibraryUsage.cpp',
]
DisableStlWrapping()
NoVisibilityFlags()