[clang] [Webkit Checkers] Introduce a Webkit checker for memory unsafe casts (PR #114606)
Devin Coughlin via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 19 09:50:10 PST 2024
================
@@ -0,0 +1,132 @@
+//=======- MemoryUnsafeCastChecker.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 MemoryUnsafeCast checker, which checks for casts from a
+// base type to a derived type.
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;
+
+namespace {
+static constexpr const char *const BaseNode = "BaseNode";
+static constexpr const char *const DerivedNode = "DerivedNode";
+static constexpr const char *const WarnRecordDecl = "WarnRecordDecl";
+
+class MemoryUnsafeCastChecker : public Checker<check::ASTCodeBody> {
+ BugType BT{this, "Unsafe cast", "WebKit coding guidelines"};
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
+ BugReporter &BR) const;
+};
+} // end namespace
+
+static void emitDiagnostics(const BoundNodes &Nodes, BugReporter &BR,
+ AnalysisDeclContext *ADC,
+ const MemoryUnsafeCastChecker *Checker) {
+ const auto *CE = Nodes.getNodeAs<CastExpr>(WarnRecordDecl);
+ const NamedDecl *Base = Nodes.getNodeAs<NamedDecl>(BaseNode);
+ const NamedDecl *Derived = Nodes.getNodeAs<NamedDecl>(DerivedNode);
+ assert(CE && Base && Derived);
+
+ std::string Diagnostics;
+ llvm::raw_string_ostream OS(Diagnostics);
+ OS << "Unsafe cast from base type '" << Base->getNameAsString()
+ << "' to derived type '" << Derived->getNameAsString() << "'";
+
+ BR.EmitBasicReport(
+ ADC->getDecl(), Checker,
+ /*Name=*/"OSObject C-Style Cast", categories::SecurityError,
+ Diagnostics,
+ PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), ADC),
+ CE->getSourceRange());
+}
+
+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 decltype(auto) hasTypePointingTo(DeclarationMatcher DeclM) {
+ return hasType(pointerType(pointee(hasDeclaration(DeclM))));
+}
+
+void MemoryUnsafeCastChecker::checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const {
+
+ AnalysisDeclContext *ADC = AM.getAnalysisDeclContext(D);
+
+ auto MatchExprPtr = allOf(
+ hasSourceExpression(hasTypePointingTo(cxxRecordDecl().bind(BaseNode))),
+ hasTypePointingTo(cxxRecordDecl(isDerivedFrom(equalsBoundNode(BaseNode)))
----------------
devincoughlin wrote:
Does this also catch cross casts? For example, if A and B both derive from D and A is cast to B, do we want to reject that? (And similarly if A and B don't have a common base?)
https://github.com/llvm/llvm-project/pull/114606
More information about the cfe-commits
mailing list