r353566 - [analyzer] Opt-in C Style Cast Checker for OSObject pointers
George Karpenkov via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 8 13:09:00 PST 2019
Author: george.karpenkov
Date: Fri Feb 8 13:09:00 2019
New Revision: 353566
URL: http://llvm.org/viewvc/llvm-project?rev=353566&view=rev
Log:
[analyzer] Opt-in C Style Cast Checker for OSObject pointers
Differential Revision: https://reviews.llvm.org/D57261
Added:
cfe/trunk/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp
cfe/trunk/test/Analysis/osobjectcstylecastchecker_test.cpp
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt
Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=353566&r1=353565&r2=353566&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Fri Feb 8 13:09:00 2019
@@ -812,6 +812,14 @@ def GCDAntipattern : Checker<"GCDAntipat
Documentation<NotDocumented>;
} // end "optin.performance"
+let ParentPackage = OSXOptIn in {
+
+def OSObjectCStyleCast : Checker<"OSObjectCStyleCast">,
+ HelpText<"Checker for C-style casts of OSObjects">,
+ Documentation<NotDocumented>;
+
+} // end "optin.osx"
+
let ParentPackage = CocoaAlpha in {
def IvarInvalidationModeling : Checker<"IvarInvalidationModeling">,
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=353566&r1=353565&r2=353566&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Fri Feb 8 13:09:00 2019
@@ -71,6 +71,7 @@ add_clang_library(clangStaticAnalyzerChe
ObjCSelfInitChecker.cpp
ObjCSuperDeallocChecker.cpp
ObjCUnusedIVarsChecker.cpp
+ OSObjectCStyleCast.cpp
PaddingChecker.cpp
PointerArithChecker.cpp
PointerSubChecker.cpp
Added: cfe/trunk/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp?rev=353566&view=auto
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp (added)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp Fri Feb 8 13:09:00 2019
@@ -0,0 +1,90 @@
+//===- 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 {
+
+const char *WarnAtNode = "OSObjCast";
+
+class OSObjectCStyleCastChecker : public Checker<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const;
+};
+
+static void emitDiagnostics(const BoundNodes &Nodes,
+ BugReporter &BR,
+ AnalysisDeclContext *ADC,
+ const OSObjectCStyleCastChecker *Checker) {
+ const auto *CE = Nodes.getNodeAs<CastExpr>(WarnAtNode);
+ assert(CE);
+
+ std::string Diagnostics;
+ llvm::raw_string_ostream OS(Diagnostics);
+ OS << "C-style cast of OSObject. Use OSDynamicCast instead.";
+
+ BR.EmitBasicReport(
+ ADC->getDecl(),
+ Checker,
+ /*Name=*/"OSObject C-Style Cast",
+ /*Category=*/"Security",
+ OS.str(),
+ PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), ADC),
+ CE->getSourceRange());
+}
+
+static auto hasTypePointingTo(DeclarationMatcher DeclM)
+ -> decltype(hasType(pointerType())) {
+ 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"))));
+
+ auto OSObjTypeM = hasTypePointingTo(cxxRecordDecl(isDerivedFrom("OSMetaClassBase")));
+ auto OSObjSubclassM = hasTypePointingTo(
+ cxxRecordDecl(isDerivedFrom("OSObject")));
+
+ auto CastM = cStyleCastExpr(
+ allOf(hasSourceExpression(allOf(OSObjTypeM, unless(DynamicCastM))),
+ OSObjSubclassM)).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 LangOptions &LO) {
+ return true;
+}
Added: cfe/trunk/test/Analysis/osobjectcstylecastchecker_test.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/osobjectcstylecastchecker_test.cpp?rev=353566&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/osobjectcstylecastchecker_test.cpp (added)
+++ cfe/trunk/test/Analysis/osobjectcstylecastchecker_test.cpp Fri Feb 8 13:09:00 2019
@@ -0,0 +1,39 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=optin.osx.OSObjectCStyleCast %s -verify
+#include "os_object_base.h"
+
+struct OSArray : public OSObject {
+ unsigned getCount();
+};
+
+struct A {
+ int x;
+};
+struct B : public A {
+ unsigned getCount();
+};
+
+unsigned warn_on_explicit_downcast(OSObject * obj) {
+ OSArray *a = (OSArray *) obj; // expected-warning{{C-style cast of OSObject. Use OSDynamicCast instead}}
+ return a->getCount();
+}
+
+void no_warn_on_upcast(OSArray *arr) {
+ OSObject *obj = (OSObject *) arr;
+ obj->retain();
+ obj->release();
+}
+
+unsigned no_warn_on_dynamic_cast(OSObject *obj) {
+ OSArray *a = OSDynamicCast(OSArray, obj);
+ return a->getCount();
+}
+
+unsigned long no_warn_on_primitive_conversion(OSArray *arr) {
+ return (unsigned long) arr;
+}
+
+unsigned no_warn_on_other_type_cast(A *a) {
+ B *b = (B *) a;
+ return b->getCount();
+}
+
More information about the cfe-commits
mailing list