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();
+}
+


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to