Skip to content

[-Wunsafe-buffer-usage] Fix a bug and suppress libc warnings for C files #109496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

ziqingluo-90
Copy link
Contributor

  • Fix a bug in UnsafeBufferUsage.cpp related to casting to PointerType (report by @hnrklssn here)
  • Suppress -Wunsafe-buffer-usage-in-libc-call for C files

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:analysis labels Sep 20, 2024
@ziqingluo-90 ziqingluo-90 requested a review from haoNoQ September 20, 2024 23:37
@llvmbot
Copy link
Member

llvmbot commented Sep 20, 2024

@llvm/pr-subscribers-clang-analysis

Author: Ziqing Luo (ziqingluo-90)

Changes
  • Fix a bug in UnsafeBufferUsage.cpp related to casting to PointerType (report by @hnrklssn here)
  • Suppress -Wunsafe-buffer-usage-in-libc-call for C files

Full diff: https://github.com/llvm/llvm-project/pull/109496.diff

3 Files Affected:

  • (modified) clang/lib/Analysis/UnsafeBufferUsage.cpp (+5-3)
  • (modified) clang/lib/Sema/AnalysisBasedWarnings.cpp (+4-2)
  • (added) clang/test/SemaCXX/warn-unsafe-buffer-usage-no-libc-functions-in-c.c (+9)
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index a16762244b1766..110a121e71a7d2 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -250,7 +250,9 @@ AST_MATCHER_P(Stmt, ignoreUnsafeBufferInContainer,
 
 AST_MATCHER_P(Stmt, ignoreUnsafeLibcCall, const UnsafeBufferUsageHandler *,
               Handler) {
-  return Handler->ignoreUnsafeBufferInLibcCall(Node.getBeginLoc());
+  if (Finder->getASTContext().getLangOpts().CPlusPlus)
+    return Handler->ignoreUnsafeBufferInLibcCall(Node.getBeginLoc());
+  return true; /* Only warn about libc calls for C++ */
 }
 
 AST_MATCHER_P(CastExpr, castSubExpr, internal::Matcher<Expr>, innerMatcher) {
@@ -789,7 +791,7 @@ AST_MATCHER_P(CallExpr, hasUnsafePrintfStringArg,
   if (!FristParmTy->isPointerType())
     return false; // possibly some user-defined printf function
 
-  QualType FirstPteTy = (cast<PointerType>(FristParmTy))->getPointeeType();
+  QualType FirstPteTy = FristParmTy->getAs<PointerType>()->getPointeeType();
 
   if (!Ctx.getFILEType()
            .isNull() && //`FILE *` must be in the context if it is fprintf
@@ -865,7 +867,7 @@ AST_MATCHER(CallExpr, hasUnsafeSnprintfBuffer) {
   if (!FirstParmTy->isPointerType())
     return false; // Not an snprint
 
-  QualType FirstPteTy = cast<PointerType>(FirstParmTy)->getPointeeType();
+  QualType FirstPteTy = FirstParmTy->getAs<PointerType>()->getPointeeType();
   const Expr *Buf = Node.getArg(0), *Size = Node.getArg(1);
 
   if (FirstPteTy.isConstQualified() || !Buf->getType()->isPointerType() ||
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 117b2c8bc57935..724b543cdf882c 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2549,6 +2549,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   DiagnosticOptions &DiagOpts = Diags.getDiagnosticOptions();
 
   // UnsafeBufferUsage analysis settings.
+  bool IsCXXLang = S.getLangOpts().CPlusPlus;
   bool UnsafeBufferUsageCanEmitSuggestions = S.getLangOpts().CPlusPlus20;
   bool UnsafeBufferUsageShouldEmitSuggestions =  // Should != Can.
       UnsafeBufferUsageCanEmitSuggestions &&
@@ -2567,8 +2568,9 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
                          Node->getBeginLoc()) ||
         !Diags.isIgnored(diag::warn_unsafe_buffer_usage_in_container,
                          Node->getBeginLoc()) ||
-        !Diags.isIgnored(diag::warn_unsafe_buffer_libc_call,
-                         Node->getBeginLoc())) {
+        (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call,
+                          Node->getBeginLoc()) &&
+         IsCXXLang /* we only warn about libc calls in C++ files */)) {
       clang::checkUnsafeBufferUsage(Node, R,
                                     UnsafeBufferUsageShouldEmitSuggestions);
     }
diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-no-libc-functions-in-c.c b/clang/test/SemaCXX/warn-unsafe-buffer-usage-no-libc-functions-in-c.c
new file mode 100644
index 00000000000000..e305c3e140dff9
--- /dev/null
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-no-libc-functions-in-c.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -Wunsafe-buffer-usage %s -verify %s
+
+void* memcpy(void *dst,const void *src, unsigned long size);
+
+void f(int *p, int *q) {
+
+  memcpy(p, q, 10); // no libc warn in C
+  ++p[5];           // expected-warning{{unsafe buffer access}}
+}

@llvmbot
Copy link
Member

llvmbot commented Sep 20, 2024

@llvm/pr-subscribers-clang

Author: Ziqing Luo (ziqingluo-90)

Changes
  • Fix a bug in UnsafeBufferUsage.cpp related to casting to PointerType (report by @hnrklssn here)
  • Suppress -Wunsafe-buffer-usage-in-libc-call for C files

Full diff: https://github.com/llvm/llvm-project/pull/109496.diff

3 Files Affected:

  • (modified) clang/lib/Analysis/UnsafeBufferUsage.cpp (+5-3)
  • (modified) clang/lib/Sema/AnalysisBasedWarnings.cpp (+4-2)
  • (added) clang/test/SemaCXX/warn-unsafe-buffer-usage-no-libc-functions-in-c.c (+9)
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index a16762244b1766..110a121e71a7d2 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -250,7 +250,9 @@ AST_MATCHER_P(Stmt, ignoreUnsafeBufferInContainer,
 
 AST_MATCHER_P(Stmt, ignoreUnsafeLibcCall, const UnsafeBufferUsageHandler *,
               Handler) {
-  return Handler->ignoreUnsafeBufferInLibcCall(Node.getBeginLoc());
+  if (Finder->getASTContext().getLangOpts().CPlusPlus)
+    return Handler->ignoreUnsafeBufferInLibcCall(Node.getBeginLoc());
+  return true; /* Only warn about libc calls for C++ */
 }
 
 AST_MATCHER_P(CastExpr, castSubExpr, internal::Matcher<Expr>, innerMatcher) {
@@ -789,7 +791,7 @@ AST_MATCHER_P(CallExpr, hasUnsafePrintfStringArg,
   if (!FristParmTy->isPointerType())
     return false; // possibly some user-defined printf function
 
-  QualType FirstPteTy = (cast<PointerType>(FristParmTy))->getPointeeType();
+  QualType FirstPteTy = FristParmTy->getAs<PointerType>()->getPointeeType();
 
   if (!Ctx.getFILEType()
            .isNull() && //`FILE *` must be in the context if it is fprintf
@@ -865,7 +867,7 @@ AST_MATCHER(CallExpr, hasUnsafeSnprintfBuffer) {
   if (!FirstParmTy->isPointerType())
     return false; // Not an snprint
 
-  QualType FirstPteTy = cast<PointerType>(FirstParmTy)->getPointeeType();
+  QualType FirstPteTy = FirstParmTy->getAs<PointerType>()->getPointeeType();
   const Expr *Buf = Node.getArg(0), *Size = Node.getArg(1);
 
   if (FirstPteTy.isConstQualified() || !Buf->getType()->isPointerType() ||
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 117b2c8bc57935..724b543cdf882c 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2549,6 +2549,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   DiagnosticOptions &DiagOpts = Diags.getDiagnosticOptions();
 
   // UnsafeBufferUsage analysis settings.
+  bool IsCXXLang = S.getLangOpts().CPlusPlus;
   bool UnsafeBufferUsageCanEmitSuggestions = S.getLangOpts().CPlusPlus20;
   bool UnsafeBufferUsageShouldEmitSuggestions =  // Should != Can.
       UnsafeBufferUsageCanEmitSuggestions &&
@@ -2567,8 +2568,9 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
                          Node->getBeginLoc()) ||
         !Diags.isIgnored(diag::warn_unsafe_buffer_usage_in_container,
                          Node->getBeginLoc()) ||
-        !Diags.isIgnored(diag::warn_unsafe_buffer_libc_call,
-                         Node->getBeginLoc())) {
+        (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call,
+                          Node->getBeginLoc()) &&
+         IsCXXLang /* we only warn about libc calls in C++ files */)) {
       clang::checkUnsafeBufferUsage(Node, R,
                                     UnsafeBufferUsageShouldEmitSuggestions);
     }
diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-no-libc-functions-in-c.c b/clang/test/SemaCXX/warn-unsafe-buffer-usage-no-libc-functions-in-c.c
new file mode 100644
index 00000000000000..e305c3e140dff9
--- /dev/null
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-no-libc-functions-in-c.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -Wunsafe-buffer-usage %s -verify %s
+
+void* memcpy(void *dst,const void *src, unsigned long size);
+
+void f(int *p, int *q) {
+
+  memcpy(p, q, 10); // no libc warn in C
+  ++p[5];           // expected-warning{{unsafe buffer access}}
+}

- Fix a bug in UnsafeBufferUsage.cpp related to casting to PointerType
- Suppress -Wunsafe-buffer-usage-in-libc-call for C files

(rdar://117182250)
@ziqingluo-90 ziqingluo-90 force-pushed the dev/ziqing/warn-libc-funcs-bug-fix branch from e261352 to e7f7f82 Compare September 20, 2024 23:59
Copy link
Member

@hnrklssn hnrklssn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to add some tests with annotated pointers to verify that you treat them correctly, e.g. _Nullable

@@ -789,7 +791,7 @@ AST_MATCHER_P(CallExpr, hasUnsafePrintfStringArg,
if (!FristParmTy->isPointerType())
return false; // possibly some user-defined printf function

QualType FirstPteTy = (cast<PointerType>(FristParmTy))->getPointeeType();
QualType FirstPteTy = FristParmTy->getAs<PointerType>()->getPointeeType();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: FristParmTy -> FirstParmTy

@@ -0,0 +1,9 @@
// RUN: %clang_cc1 -Wunsafe-buffer-usage %s -verify %s
Copy link
Contributor

@jkorous-apple jkorous-apple Sep 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW the language mode is set via -x command line option. It is only inferred from the file extension if -x is missing.

return Handler->ignoreUnsafeBufferInLibcCall(Node.getBeginLoc());
if (Finder->getASTContext().getLangOpts().CPlusPlus)
return Handler->ignoreUnsafeBufferInLibcCall(Node.getBeginLoc());
return true; /* Only warn about libc calls for C++ */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation should warn in Obj-C++ too and it should not in Obj-C but you might want to test that.

@@ -2549,6 +2549,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
DiagnosticOptions &DiagOpts = Diags.getDiagnosticOptions();

// UnsafeBufferUsage analysis settings.
bool IsCXXLang = S.getLangOpts().CPlusPlus;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: it doesn't feel like we need a variable for that.

Copy link
Contributor

@jkorous-apple jkorous-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments but LGTM.

Copy link
Collaborator

@haoNoQ haoNoQ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

return false; // possibly some user-defined printf function

QualType FirstPteTy = (cast<PointerType>(FristParmTy))->getPointeeType();
QualType FirstPteTy = FirstParmTy->getAs<PointerType>()->getPointeeType();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

castAs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference between castAs and getAs is that castAs asserts the canonical type is PointerType while getAs returns null if not. I think castAs is more suitable for our case.

@ziqingluo-90 ziqingluo-90 merged commit 090dc77 into llvm:main Sep 22, 2024
8 checks passed
ziqingluo-90 added a commit to ziqingluo-90/apple-llvm-project that referenced this pull request Oct 14, 2024
…les (llvm#109496)

- Fix a bug in UnsafeBufferUsage.cpp related to casting to PointerType
- Suppress -Wunsafe-buffer-usage-in-libc-call for C files

(rdar://117182250)

(cherry picked from commit 090dc77)
@ziqingluo-90 ziqingluo-90 deleted the dev/ziqing/warn-libc-funcs-bug-fix branch December 19, 2024 23:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:analysis clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants