[clang] [clang-tools-extra] Add function check for windows platform (PR #106581)

via cfe-commits cfe-commits at lists.llvm.org
Sun Sep 1 09:20:37 PDT 2024


https://github.com/fawdlstty updated https://github.com/llvm/llvm-project/pull/106581

>From f169f3c57a0a55c1a0dbb8f965bc17a87ceb98d7 Mon Sep 17 00:00:00 2001
From: fawdlstty <f at fawdlstty.com>
Date: Fri, 30 Aug 2024 00:23:39 +0800
Subject: [PATCH 1/6] add check for windows platforms api

---
 .../bugprone/NotNullTerminatedResultCheck.cpp |  2 +-
 clang/docs/analyzer/checkers.rst              |  2 +-
 clang/include/clang/Basic/Builtins.td         | 22 +++++++++++++++++++
 .../Checkers/CStringChecker.cpp               |  6 +++++
 4 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp
index 977241e91b9a93..e2cf96c88b90bd 100644
--- a/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp
@@ -106,7 +106,7 @@ static const CallExpr *getStrlenExpr(const MatchFinder::MatchResult &Result) {
     if (const Decl *D = StrlenExpr->getCalleeDecl())
       if (const FunctionDecl *FD = D->getAsFunction())
         if (const IdentifierInfo *II = FD->getIdentifier())
-          if (II->isStr("strlen") || II->isStr("wcslen"))
+          if (II->isStr("strlen") || II->isStr("lstrlen") || II->isStr("wcslen"))
             return StrlenExpr;
 
   return nullptr;
diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 89a1018e14c0e6..ca675ae37929fe 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -1582,7 +1582,7 @@ Check the size argument passed into C string functions for common erroneous patt
 unix.cstring.NullArg (C)
 """"""""""""""""""""""""
 Check for null pointers being passed as arguments to C string functions:
-``strlen, strnlen, strcpy, strncpy, strcat, strncat, strcmp, strncmp, strcasecmp, strncasecmp, wcslen, wcsnlen``.
+``strlen, lstrlen, strnlen, strcpy, lstrcpy, strncpy, strcat, lstrcat, strncat, strcmp, strncmp, strcasecmp, strncasecmp, wcslen, wcsnlen``.
 
 .. code-block:: c
 
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 8668b25661dec8..cbc5fc52326ad2 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4788,3 +4788,25 @@ def ArithmeticFence : LangBuiltin<"ALL_LANGUAGES"> {
   let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
+
+// Windows - WinBase.h
+def LStrLen : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrlen"];
+  let Attributes = [NoThrow, Constexpr];
+  let Prototype = "int(LPCTSTR)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def LStrCpy : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrcpy"];
+  let Attributes = [NoThrow];
+  let Prototype = "LPCTSTR(LPTSTR, LPCTSTR)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def LStrCat : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrcat"];
+  let Attributes = [NoThrow];
+  let Prototype = "LPTSTR(LPTSTR, LPCTSTR)";
+  let AddBuiltinPrefixedAlias = 1;
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 8dd08f14b2728b..2adf538486176d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -150,6 +150,8 @@ class CStringChecker : public Checker< eval::Call,
       // FIXME: C23 introduces 'memset_explicit', maybe also model that
       {{CDM::CLibraryMaybeHardened, {"strcpy"}, 2},
        &CStringChecker::evalStrcpy},
+      {{CDM::CLibraryMaybeHardened, {"lstrcpy"}, 2},
+       &CStringChecker::evalStrcpy},
       {{CDM::CLibraryMaybeHardened, {"strncpy"}, 3},
        &CStringChecker::evalStrncpy},
       {{CDM::CLibraryMaybeHardened, {"stpcpy"}, 2},
@@ -158,12 +160,16 @@ class CStringChecker : public Checker< eval::Call,
        &CStringChecker::evalStrlcpy},
       {{CDM::CLibraryMaybeHardened, {"strcat"}, 2},
        &CStringChecker::evalStrcat},
+      {{CDM::CLibraryMaybeHardened, {"lstrcat"}, 2},
+       &CStringChecker::evalStrcat},
       {{CDM::CLibraryMaybeHardened, {"strncat"}, 3},
        &CStringChecker::evalStrncat},
       {{CDM::CLibraryMaybeHardened, {"strlcat"}, 3},
        &CStringChecker::evalStrlcat},
       {{CDM::CLibraryMaybeHardened, {"strlen"}, 1},
        &CStringChecker::evalstrLength},
+      {{CDM::CLibraryMaybeHardened, {"lstrlen"}, 1},
+       &CStringChecker::evalstrLength},
       {{CDM::CLibrary, {"wcslen"}, 1}, &CStringChecker::evalstrLength},
       {{CDM::CLibraryMaybeHardened, {"strnlen"}, 2},
        &CStringChecker::evalstrnLength},

>From 52d40b558e14948c38c8c5f75245c5ba08bd3fea Mon Sep 17 00:00:00 2001
From: fawdlstty <f at fawdlstty.com>
Date: Fri, 30 Aug 2024 00:33:22 +0800
Subject: [PATCH 2/6] add to insecureAPI

---
 clang/docs/analyzer/checkers.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index ca675ae37929fe..7a7b1926da17b4 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -1256,7 +1256,7 @@ Warn on uses of inferior random number generating functions (only if arc4random
 
 security.insecureAPI.strcpy (C)
 """""""""""""""""""""""""""""""
-Warn on uses of the ``strcpy`` and ``strcat`` functions.
+Warn on uses of the ``strcpy, lstrcpy, strcat, lstrcat`` functions.
 
 .. code-block:: c
 

>From 807316cf3819405db68d0400f005ca8a47b83b11 Mon Sep 17 00:00:00 2001
From: fawdlstty <f at fawdlstty.com>
Date: Sat, 31 Aug 2024 22:08:09 +0800
Subject: [PATCH 3/6] fix check for using CLibraryMaybeHardened

---
 .../bugprone/NotNullTerminatedResultCheck.cpp |  2 +-
 clang/include/clang/Basic/Builtins.td         | 39 ++++++++++++++-----
 .../Checkers/CStringChecker.cpp               | 12 +++---
 3 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp
index e2cf96c88b90bd..c7bcaac5712dd1 100644
--- a/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp
@@ -106,7 +106,7 @@ static const CallExpr *getStrlenExpr(const MatchFinder::MatchResult &Result) {
     if (const Decl *D = StrlenExpr->getCalleeDecl())
       if (const FunctionDecl *FD = D->getAsFunction())
         if (const IdentifierInfo *II = FD->getIdentifier())
-          if (II->isStr("strlen") || II->isStr("lstrlen") || II->isStr("wcslen"))
+          if (II->isStr("strlen") || II->isStr("lstrlenA") || II->isStr("lstrlenW") || II->isStr("wcslen"))
             return StrlenExpr;
 
   return nullptr;
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index cbc5fc52326ad2..7420abbc6a6717 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4790,23 +4790,44 @@ def ArithmeticFence : LangBuiltin<"ALL_LANGUAGES"> {
 }
 
 // Windows - WinBase.h
-def LStrLen : LibBuiltin<"WinBase.h"> {
-  let Spellings = ["lstrlen"];
+def LStrLenA : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrlenA"];
   let Attributes = [NoThrow, Constexpr];
-  let Prototype = "int(LPCTSTR)";
+  let Prototype = "int(const char*)";
   let AddBuiltinPrefixedAlias = 1;
 }
 
-def LStrCpy : LibBuiltin<"WinBase.h"> {
-  let Spellings = ["lstrcpy"];
+def LStrLenW : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrlenW"];
+  let Attributes = [NoThrow, Constexpr];
+  let Prototype = "int(const wchar_t*)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def LStrCpyA : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrcpyA"];
+  let Attributes = [NoThrow];
+  let Prototype = "char*(char*, const char*)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def LStrCpyW : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrcpyW"];
+  let Attributes = [NoThrow];
+  let Prototype = "wchar_t*(wchar_t*, const wchar_t*)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def LStrCatA : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrcatA"];
   let Attributes = [NoThrow];
-  let Prototype = "LPCTSTR(LPTSTR, LPCTSTR)";
+  let Prototype = "char*(char*, const char*)";
   let AddBuiltinPrefixedAlias = 1;
 }
 
-def LStrCat : LibBuiltin<"WinBase.h"> {
-  let Spellings = ["lstrcat"];
+def LStrCatW : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrcatW"];
   let Attributes = [NoThrow];
-  let Prototype = "LPTSTR(LPTSTR, LPCTSTR)";
+  let Prototype = "wchar_t*(wchar_t*, const wchar_t*)";
   let AddBuiltinPrefixedAlias = 1;
 }
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 2adf538486176d..ff9baff22c2d86 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -150,8 +150,8 @@ class CStringChecker : public Checker< eval::Call,
       // FIXME: C23 introduces 'memset_explicit', maybe also model that
       {{CDM::CLibraryMaybeHardened, {"strcpy"}, 2},
        &CStringChecker::evalStrcpy},
-      {{CDM::CLibraryMaybeHardened, {"lstrcpy"}, 2},
-       &CStringChecker::evalStrcpy},
+      {{CDM::CLibrary, {"lstrcpyA"}, 2}, &CStringChecker::evalStrcpy},
+      {{CDM::CLibrary, {"lstrcpyW"}, 2}, &CStringChecker::evalStrcpy},
       {{CDM::CLibraryMaybeHardened, {"strncpy"}, 3},
        &CStringChecker::evalStrncpy},
       {{CDM::CLibraryMaybeHardened, {"stpcpy"}, 2},
@@ -160,16 +160,16 @@ class CStringChecker : public Checker< eval::Call,
        &CStringChecker::evalStrlcpy},
       {{CDM::CLibraryMaybeHardened, {"strcat"}, 2},
        &CStringChecker::evalStrcat},
-      {{CDM::CLibraryMaybeHardened, {"lstrcat"}, 2},
-       &CStringChecker::evalStrcat},
+      {{CDM::CLibrary, {"lstrcatA"}, 2}, &CStringChecker::evalStrcat},
+      {{CDM::CLibrary, {"lstrcatW"}, 2}, &CStringChecker::evalStrcat},
       {{CDM::CLibraryMaybeHardened, {"strncat"}, 3},
        &CStringChecker::evalStrncat},
       {{CDM::CLibraryMaybeHardened, {"strlcat"}, 3},
        &CStringChecker::evalStrlcat},
       {{CDM::CLibraryMaybeHardened, {"strlen"}, 1},
        &CStringChecker::evalstrLength},
-      {{CDM::CLibraryMaybeHardened, {"lstrlen"}, 1},
-       &CStringChecker::evalstrLength},
+      {{CDM::CLibrary, {"lstrlenA"}, 1}, &CStringChecker::evalstrLength},
+      {{CDM::CLibrary, {"lstrlenW"}, 1}, &CStringChecker::evalstrLength},
       {{CDM::CLibrary, {"wcslen"}, 1}, &CStringChecker::evalstrLength},
       {{CDM::CLibraryMaybeHardened, {"strnlen"}, 2},
        &CStringChecker::evalstrnLength},

>From d794e48fae5beb0ec9e2a0c8d6dd734b69efb9f0 Mon Sep 17 00:00:00 2001
From: fawdlstty <f at fawdlstty.com>
Date: Sat, 31 Aug 2024 22:40:16 +0800
Subject: [PATCH 4/6] modify type to char const*

---
 clang/include/clang/Basic/Builtins.td | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 7420abbc6a6717..1bdcb9a84eb421 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4793,41 +4793,41 @@ def ArithmeticFence : LangBuiltin<"ALL_LANGUAGES"> {
 def LStrLenA : LibBuiltin<"WinBase.h"> {
   let Spellings = ["lstrlenA"];
   let Attributes = [NoThrow, Constexpr];
-  let Prototype = "int(const char*)";
+  let Prototype = "int(char const*)";
   let AddBuiltinPrefixedAlias = 1;
 }
 
 def LStrLenW : LibBuiltin<"WinBase.h"> {
   let Spellings = ["lstrlenW"];
   let Attributes = [NoThrow, Constexpr];
-  let Prototype = "int(const wchar_t*)";
+  let Prototype = "int(wchar_t const*)";
   let AddBuiltinPrefixedAlias = 1;
 }
 
 def LStrCpyA : LibBuiltin<"WinBase.h"> {
   let Spellings = ["lstrcpyA"];
   let Attributes = [NoThrow];
-  let Prototype = "char*(char*, const char*)";
+  let Prototype = "char*(char*, char const*)";
   let AddBuiltinPrefixedAlias = 1;
 }
 
 def LStrCpyW : LibBuiltin<"WinBase.h"> {
   let Spellings = ["lstrcpyW"];
   let Attributes = [NoThrow];
-  let Prototype = "wchar_t*(wchar_t*, const wchar_t*)";
+  let Prototype = "wchar_t*(wchar_t*, wchar_t const*)";
   let AddBuiltinPrefixedAlias = 1;
 }
 
 def LStrCatA : LibBuiltin<"WinBase.h"> {
   let Spellings = ["lstrcatA"];
   let Attributes = [NoThrow];
-  let Prototype = "char*(char*, const char*)";
+  let Prototype = "char*(char*, char const*)";
   let AddBuiltinPrefixedAlias = 1;
 }
 
 def LStrCatW : LibBuiltin<"WinBase.h"> {
   let Spellings = ["lstrcatW"];
   let Attributes = [NoThrow];
-  let Prototype = "wchar_t*(wchar_t*, const wchar_t*)";
+  let Prototype = "wchar_t*(wchar_t*, wchar_t const*)";
   let AddBuiltinPrefixedAlias = 1;
 }

>From f3057ada6c0225b7807fdc9e901730c1562189e2 Mon Sep 17 00:00:00 2001
From: fawdlstty <f at fawdlstty.com>
Date: Sat, 31 Aug 2024 23:15:35 +0800
Subject: [PATCH 5/6] remove from builtins

---
 clang/include/clang/Basic/Builtins.td | 43 ---------------------------
 1 file changed, 43 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 1bdcb9a84eb421..8668b25661dec8 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4788,46 +4788,3 @@ def ArithmeticFence : LangBuiltin<"ALL_LANGUAGES"> {
   let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
-
-// Windows - WinBase.h
-def LStrLenA : LibBuiltin<"WinBase.h"> {
-  let Spellings = ["lstrlenA"];
-  let Attributes = [NoThrow, Constexpr];
-  let Prototype = "int(char const*)";
-  let AddBuiltinPrefixedAlias = 1;
-}
-
-def LStrLenW : LibBuiltin<"WinBase.h"> {
-  let Spellings = ["lstrlenW"];
-  let Attributes = [NoThrow, Constexpr];
-  let Prototype = "int(wchar_t const*)";
-  let AddBuiltinPrefixedAlias = 1;
-}
-
-def LStrCpyA : LibBuiltin<"WinBase.h"> {
-  let Spellings = ["lstrcpyA"];
-  let Attributes = [NoThrow];
-  let Prototype = "char*(char*, char const*)";
-  let AddBuiltinPrefixedAlias = 1;
-}
-
-def LStrCpyW : LibBuiltin<"WinBase.h"> {
-  let Spellings = ["lstrcpyW"];
-  let Attributes = [NoThrow];
-  let Prototype = "wchar_t*(wchar_t*, wchar_t const*)";
-  let AddBuiltinPrefixedAlias = 1;
-}
-
-def LStrCatA : LibBuiltin<"WinBase.h"> {
-  let Spellings = ["lstrcatA"];
-  let Attributes = [NoThrow];
-  let Prototype = "char*(char*, char const*)";
-  let AddBuiltinPrefixedAlias = 1;
-}
-
-def LStrCatW : LibBuiltin<"WinBase.h"> {
-  let Spellings = ["lstrcatW"];
-  let Attributes = [NoThrow];
-  let Prototype = "wchar_t*(wchar_t*, wchar_t const*)";
-  let AddBuiltinPrefixedAlias = 1;
-}

>From 294c3a36600bcf12487949bad2dc3362adb355f6 Mon Sep 17 00:00:00 2001
From: fawdlstty <f at fawdlstty.com>
Date: Mon, 2 Sep 2024 00:20:17 +0800
Subject: [PATCH 6/6] fix builtin headers

---
 clang/include/clang/Basic/BuiltinHeaders.def  |  1 +
 clang/include/clang/Basic/Builtins.td         | 43 +++++++++++++++++++
 clang/utils/TableGen/ClangBuiltinsEmitter.cpp |  2 +
 3 files changed, 46 insertions(+)

diff --git a/clang/include/clang/Basic/BuiltinHeaders.def b/clang/include/clang/Basic/BuiltinHeaders.def
index 8e4a2f9bee9aa0..45fb67d1fde4ee 100644
--- a/clang/include/clang/Basic/BuiltinHeaders.def
+++ b/clang/include/clang/Basic/BuiltinHeaders.def
@@ -38,6 +38,7 @@ HEADER(STRING_H, "string.h")
 HEADER(UNISTD_H, "unistd.h")
 HEADER(UTILITY, "utility")
 HEADER(WCHAR_H, "wchar.h")
+HEADER(WINBASE_H, "winbase.h")
 HEADER(XMMINTRIN_H, "xmmintrin.h")
 
 #undef HEADER
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 8668b25661dec8..b677bac01fed29 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4788,3 +4788,46 @@ def ArithmeticFence : LangBuiltin<"ALL_LANGUAGES"> {
   let Attributes = [CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
+
+// Windows - WinBase.h
+def LStrLenA : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrlenA"];
+  let Attributes = [NoThrow, Constexpr];
+  let Prototype = "int(char const*)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def LStrLenW : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrlenW"];
+  let Attributes = [NoThrow, Constexpr];
+  let Prototype = "int(wchar_t const*)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def LStrCpyA : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrcpyA"];
+  let Attributes = [NoThrow];
+  let Prototype = "char*(char*, char const*)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def LStrCpyW : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrcpyW"];
+  let Attributes = [NoThrow];
+  let Prototype = "wchar_t*(wchar_t*, wchar_t const*)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def LStrCatA : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrcatA"];
+  let Attributes = [NoThrow];
+  let Prototype = "char*(char*, char const*)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def LStrCatW : LibBuiltin<"WinBase.h"> {
+  let Spellings = ["lstrcatW"];
+  let Attributes = [NoThrow];
+  let Prototype = "wchar_t*(wchar_t*, wchar_t const*)";
+  let AddBuiltinPrefixedAlias = 1;
+}
\ No newline at end of file
diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
index 94f12a08164fdc..912e9f0612f9cc 100644
--- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
@@ -201,6 +201,8 @@ class HeaderNameParser {
     for (char c : Builtin->getValueAsString("Header")) {
       if (std::islower(c))
         HeaderName += static_cast<char>(std::toupper(c));
+      else if (std::isupper(c))
+        HeaderName += c;
       else if (c == '.' || c == '_' || c == '/' || c == '-')
         HeaderName += '_';
       else



More information about the cfe-commits mailing list