diff options
author | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/clang14/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp | |
parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff) | |
download | ydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz |
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/clang14/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp')
-rw-r--r-- | contrib/libs/clang14/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/contrib/libs/clang14/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp b/contrib/libs/clang14/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp new file mode 100644 index 0000000000..0a8379d9ab --- /dev/null +++ b/contrib/libs/clang14/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp @@ -0,0 +1,125 @@ +//===- OSObjectCStyleCast.cpp ------------------------------------*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines OSObjectCStyleCast checker, which checks for C-style casts +// of OSObjects. Such casts almost always indicate a code smell, +// as an explicit static or dynamic cast should be used instead. +//===----------------------------------------------------------------------===// + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" +#include "llvm/Support/Debug.h" + +using namespace clang; +using namespace ento; +using namespace ast_matchers; + +namespace { +static constexpr const char *const WarnAtNode = "WarnAtNode"; +static constexpr const char *const WarnRecordDecl = "WarnRecordDecl"; + +class OSObjectCStyleCastChecker : public Checker<check::ASTCodeBody> { +public: + void checkASTCodeBody(const Decl *D, AnalysisManager &AM, + BugReporter &BR) const; +}; +} // namespace + +namespace clang { +namespace ast_matchers { +AST_MATCHER_P(StringLiteral, mentionsBoundType, std::string, BindingID) { + return Builder->removeBindings([this, &Node](const BoundNodesMap &Nodes) { + const auto &BN = Nodes.getNode(this->BindingID); + if (const auto *ND = BN.get<NamedDecl>()) { + return ND->getName() != Node.getString(); + } + return true; + }); +} +} // end namespace ast_matchers +} // end namespace clang + +static void emitDiagnostics(const BoundNodes &Nodes, + BugReporter &BR, + AnalysisDeclContext *ADC, + const OSObjectCStyleCastChecker *Checker) { + const auto *CE = Nodes.getNodeAs<CastExpr>(WarnAtNode); + const CXXRecordDecl *RD = Nodes.getNodeAs<CXXRecordDecl>(WarnRecordDecl); + assert(CE && RD); + + std::string Diagnostics; + llvm::raw_string_ostream OS(Diagnostics); + OS << "C-style cast of an OSObject is prone to type confusion attacks; " + << "use 'OSRequiredCast' if the object is definitely of type '" + << RD->getNameAsString() << "', or 'OSDynamicCast' followed by " + << "a null check if unsure", + + BR.EmitBasicReport( + ADC->getDecl(), + Checker, + /*Name=*/"OSObject C-Style Cast", + categories::SecurityError, + OS.str(), + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), ADC), + CE->getSourceRange()); +} + +static decltype(auto) hasTypePointingTo(DeclarationMatcher DeclM) { + return hasType(pointerType(pointee(hasDeclaration(DeclM)))); +} + +void OSObjectCStyleCastChecker::checkASTCodeBody(const Decl *D, + AnalysisManager &AM, + BugReporter &BR) const { + + AnalysisDeclContext *ADC = AM.getAnalysisDeclContext(D); + + auto DynamicCastM = callExpr(callee(functionDecl(hasName("safeMetaCast")))); + // 'allocClassWithName' allocates an object with the given type. + // The type is actually provided as a string argument (type's name). + // This makes the following pattern possible: + // + // Foo *object = (Foo *)allocClassWithName("Foo"); + // + // While OSRequiredCast can be used here, it is still not a useful warning. + auto AllocClassWithNameM = callExpr( + callee(functionDecl(hasName("allocClassWithName"))), + // Here we want to make sure that the string argument matches the + // type in the cast expression. + hasArgument(0, stringLiteral(mentionsBoundType(WarnRecordDecl)))); + + auto OSObjTypeM = + hasTypePointingTo(cxxRecordDecl(isDerivedFrom("OSMetaClassBase"))); + auto OSObjSubclassM = hasTypePointingTo( + cxxRecordDecl(isDerivedFrom("OSObject")).bind(WarnRecordDecl)); + + auto CastM = + cStyleCastExpr( + allOf(OSObjSubclassM, + hasSourceExpression( + allOf(OSObjTypeM, + unless(anyOf(DynamicCastM, AllocClassWithNameM)))))) + .bind(WarnAtNode); + + auto Matches = + match(stmt(forEachDescendant(CastM)), *D->getBody(), AM.getASTContext()); + for (BoundNodes Match : Matches) + emitDiagnostics(Match, BR, ADC, this); +} + +void ento::registerOSObjectCStyleCast(CheckerManager &Mgr) { + Mgr.registerChecker<OSObjectCStyleCastChecker>(); +} + +bool ento::shouldRegisterOSObjectCStyleCast(const CheckerManager &mgr) { + return true; +} |