ktomi996 updated this revision to Diff 303633.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D91000/new/

https://reviews.llvm.org/D91000

Files:
  clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
  clang-tools-extra/clang-tidy/cert/CMakeLists.txt
  clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp
  clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-obsolescent-functions.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/cert-obsolescent-functions.cpp

Index: clang-tools-extra/test/clang-tidy/cert-obsolescent-functions.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/cert-obsolescent-functions.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s cert-obsolescent-functions %t --
+
+#define __STDC_LIB_EXT1__
+#define __STDC_WANT_LIB_EXT1__ 1
+void * memmove(void *, void *, unsigned int);
+void f1(const char *in) {
+  int i = 1;
+  int j = 2;
+  memmove(&i, &j, sizeof(int));
+    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Unsafe function memmove used. Safe memmove_s can be used instead. [cert-obsolescent-functions]
+}
+
+
+void f2(const char *in) {
+    void * (*func_ptr)(void *, void *, unsigned int) = memmove;
+// CHECK-MESSAGES: :[[@LINE-1]]:56: warning: Unsafe function memmove used. Safe memmove_s can be used instead. [cert-obsolescent-functions]
+}
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -100,6 +100,7 @@
    cert-msc32-c (redirects to cert-msc51-cpp) <cert-msc32-c>
    cert-msc50-cpp
    cert-msc51-cpp
+   cert-obsolescent-functions
    cert-oop11-cpp (redirects to performance-move-constructor-init) <cert-oop11-cpp>
    cert-oop54-cpp (redirects to bugprone-unhandled-self-assignment) <cert-oop54-cpp>
    cppcoreguidelines-avoid-c-arrays (redirects to modernize-avoid-c-arrays) <cppcoreguidelines-avoid-c-arrays>
Index: clang-tools-extra/docs/clang-tidy/checks/cert-obsolescent-functions.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cert-obsolescent-functions.rst
@@ -0,0 +1,23 @@
+..title::clang-tidy-cert-obsolescent-functions
+
+cert-obsolescent-functions
+==========================
+    
+Guards against using some unsafe function calls and function pointers which initialized with unsafe functions if __STDC_LIB_EXT1__ macro is defined and the value of __STDC_WANT_LIB_EXT1__ is 1. The usage of following functions are checked : bsearch,
+    fprintf, fscanf, fwprintf, fwscanf, getenv, gmtime, localtime, mbsrtowcs,
+    mbstowcs, memcpy, memmove, printf, qsort, setbuf, snprintf, sprintf, sscanf,
+    strcat, strcpy, strerror, strncat, strncpy, strtok, swprintf, swscanf,
+    vfprintf, vfscanf, vfwprintf, vfwscanf, vprintf, vscanf vsnprintf, vspr,
+    wcscpy, wcsncat, wcsncpy wcsrtombs, wcstok, wcstombs, wctomb, wmemcpy,
+    wmemmove, wprintf, wscanf,
+    strlen
+
+This is a CERT security rule:
+https://wiki.sei.cmu.edu/confluence/display/c/MSC24-C.+Do+not+use+deprecated+or+obsolescent+functions
+      Example :
+      .code-block::
+        #define __STDC_WANT_LIB_EXT1__ 1
+        int i = 2;
+        int j = 3;
+        memmove(&i, &j, sizeof(int)); // diagnosed if __STDC_LIB_EXT1__ is defined in a
+                                    // header, memmove_s usage is suggested instead.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -194,6 +194,13 @@
   against self-assignment either by checking self-assignment explicitly or
   using the copy-and-swap or the copy-and-move method.
 
+- New :doc:`cert-obsolescent-functions
+  <clang-tidy/checks/cert-obsolescent-functions>` check.
+
+  Guards against using some unsafe function calls and function pointers which
+  initialized with unsafe functions if some macros defined.
+
+
 - New :doc:`fuchsia-default-arguments-calls
   <clang-tidy/checks/fuchsia-default-arguments-calls>` check.
 
Index: clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.h
@@ -0,0 +1,36 @@
+//===--- ObsolescentFunctionsCheck.h - clang-tidy ---------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_OBSOLESCENTFUNCTIONSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_OBSOLESCENTFUNCTIONSCHECK_H
+
+#include "../ClangTidyCheck.h"
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Guards against using some unsafe function calls and function pointers which initialized with unsafe functions if some macros defined.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-obsolescent-functions.html
+class ObsolescentFunctionsCheck : public ClangTidyCheck {
+public:
+  ObsolescentFunctionsCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  const std::pair<bool, bool> UsingAnnexK();
+  void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+                           Preprocessor *ModuleExpandedPP) override;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_OBSOLESCENTFUNCTIONSCHECK_H
Index: clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp
@@ -0,0 +1,103 @@
+//===--- ObsolescentFunctionsCheck.cpp - clang-tidy -----------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "ObsolescentFunctionsCheck.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+namespace {
+static Preprocessor *PP;
+}
+
+void ObsolescentFunctionsCheck::registerMatchers(MatchFinder *Finder) {
+  const auto CheckedFunctions = functionDecl(hasAnyName(
+      "::bsearch", "::fprintf", "::fscanf", "::fwprintf", "::fwscanf",
+      "::getenv", "::gmtime", "::localtime", "::mbsrtowcs", "::mbstowcs",
+      "::memcpy", "::memmove", "::printf", "::qsort", "::setbuf", "::snprintf",
+      "::sprintf", "::sscanf", "::strcat", "::strcpy", "::strerror",
+      "::strncat", "::strncpy", "::strtok", "::swprintf", "::swscanf",
+      "::vfprintf", "::vfscanf", "vfwprintf", "vfwscanf", "vprintf", "::vscanf",
+      "::vsnprintf", "::vsprintf", "::vsscanf", "::vswprintf", "::vswcanf",
+      "::wcrtomb", "::wcscat", "::wcscpy", "::wcsncat", "::wcsncpy",
+      "::wcsrtombs", "::wcstok", "::wcstombs", "::wctomb", "::wmemcpy",
+      "::wmemmove", "::wprintf", "::wscanf", "::strlen"));
+  Finder->addMatcher(
+      callExpr(callee(CheckedFunctions.bind("fn"))).bind("callexpr"), this);
+
+  Finder->addMatcher(varDecl(hasInitializer(ignoringImpCasts(declRefExpr(
+                                 to(CheckedFunctions.bind("fnp"))))))
+                         .bind("fp"),
+                     this);
+}
+
+void ObsolescentFunctionsCheck::registerPPCallbacks(
+    const SourceManager &SM, Preprocessor *Preproc,
+    Preprocessor *ModuleExpandedPP) {
+  PP = Preproc;
+}
+
+const std::pair<bool, bool> ObsolescentFunctionsCheck::UsingAnnexK() {
+  bool AnnexKIsAvailable;
+  bool AnnexKIsWanted;
+  if (!PP->isMacroDefined("__STDC_LIB_EXT1__")) {
+    AnnexKIsAvailable = false;
+  } else {
+    AnnexKIsAvailable = true;
+  }
+  const IdentifierInfo *Id = PP->getIdentifierInfo("__STDC_WANT_LIB_EXT1__");
+  AnnexKIsWanted = false;
+  if (!Id) {
+    AnnexKIsWanted = false;
+  } else {
+    const auto *MI = PP->getMacroInfo(Id);
+    const auto &T = MI->tokens().back();
+    StringRef ValueStr = StringRef(T.getLiteralData(), T.getLength());
+    llvm::APInt IntValue;
+    ValueStr.getAsInteger(10, IntValue);
+    Optional<bool> AreSafeFunctionsWanted;
+    AreSafeFunctionsWanted = IntValue.getZExtValue();
+    if (AreSafeFunctionsWanted.hasValue()) {
+      AnnexKIsWanted = AreSafeFunctionsWanted.getValue();
+    }
+  }
+  return std::make_pair(AnnexKIsAvailable, AnnexKIsWanted);
+}
+
+void ObsolescentFunctionsCheck::check(const MatchFinder::MatchResult &Result) {
+  std::pair<bool, bool> AnnexKUsage = UsingAnnexK();
+  bool AnnexKIsAvailable = std::get<0>(AnnexKUsage);
+  bool AnnexKIsWanted = std::get<1>(AnnexKUsage);
+  if (!AnnexKIsWanted || !AnnexKIsAvailable) {
+    return;
+  }
+  if (const auto *Function = Result.Nodes.getNodeAs<CallExpr>("callexpr")) {
+    const FunctionDecl *FD = Result.Nodes.getNodeAs<FunctionDecl>("fn");
+    const NamedDecl *NFD = dyn_cast<NamedDecl>(FD);
+    std::string FunctionName = NFD->getNameAsString();
+    diag(Function->getExprLoc(), "Unsafe function " + FunctionName + " used. " +
+                                     "Safe " + FunctionName +
+                                     "_s can be used instead.");
+  }
+  if (const auto *FunctionPointer = Result.Nodes.getNodeAs<VarDecl>("fp")) {
+    if (const FunctionDecl *FD = Result.Nodes.getNodeAs<FunctionDecl>("fnp")) {
+      const NamedDecl *NFD = dyn_cast<NamedDecl>(FD);
+      std::string FunctionName = NFD->getNameAsString();
+      diag(FunctionPointer->getEndLoc(),
+           "Unsafe function " + FunctionName + " used. " + "Safe " +
+               FunctionName + "_s can be used instead.");
+    }
+  }
+}
+} // namespace cert
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/cert/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/cert/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/cert/CMakeLists.txt
@@ -6,6 +6,7 @@
   DontModifyStdNamespaceCheck.cpp
   FloatLoopCounter.cpp
   LimitedRandomnessCheck.cpp
+  ObsolescentFunctionsCheck.cpp
   PostfixOperatorCheck.cpp
   ProperlySeededRandomGeneratorCheck.cpp
   SetLongJmpCheck.cpp
Index: clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
+++ clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
@@ -21,6 +21,7 @@
 #include "DontModifyStdNamespaceCheck.h"
 #include "FloatLoopCounter.h"
 #include "LimitedRandomnessCheck.h"
+#include "ObsolescentFunctionsCheck.h"
 #include "PostfixOperatorCheck.h"
 #include "ProperlySeededRandomGeneratorCheck.h"
 #include "SetLongJmpCheck.h"
@@ -79,6 +80,8 @@
     // ERR
     CheckFactories.registerCheck<StrToNumCheck>("cert-err34-c");
     // MSC
+    CheckFactories.registerCheck<ObsolescentFunctionsCheck>(
+        "cert-obsolescent-functions");
     CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc30-c");
     CheckFactories.registerCheck<ProperlySeededRandomGeneratorCheck>(
         "cert-msc32-c");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to