Skip to content
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

[clang][analyzer] use unqualified canonical type during merging equivalence class #95729

Conversation

HerrCai0907
Copy link
Contributor

Fixes: #95658
Unqualified canonical type should be used instead of normal QualType for type equality comparison

…alence class

Fixes: llvm#95658
Unqualified canonical type should be used instead of normal QualType for type equality comparison
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:static analyzer labels Jun 17, 2024
@llvmbot
Copy link
Member

llvmbot commented Jun 17, 2024

@llvm/pr-subscribers-clang

Author: Congcong Cai (HerrCai0907)

Changes

Fixes: #95658
Unqualified canonical type should be used instead of normal QualType for type equality comparison


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

2 Files Affected:

  • (modified) clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp (+2-1)
  • (modified) clang/test/Analysis/errno-stdlibraryfunctions.c (+24)
diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index c6f87b45ab887..d8c257dbd731e 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -2333,7 +2333,8 @@ inline ProgramStateRef EquivalenceClass::merge(RangeSet::Factory &F,
   //
   //        The moment we introduce symbolic casts, this restriction can be
   //        lifted.
-  if (getType() != Other.getType())
+  if (getType()->getCanonicalTypeUnqualified() !=
+      Other.getType()->getCanonicalTypeUnqualified())
     return State;
 
   SymbolSet Members = getClassMembers(State);
diff --git a/clang/test/Analysis/errno-stdlibraryfunctions.c b/clang/test/Analysis/errno-stdlibraryfunctions.c
index a28efb764edfd..657aa37a42670 100644
--- a/clang/test/Analysis/errno-stdlibraryfunctions.c
+++ b/clang/test/Analysis/errno-stdlibraryfunctions.c
@@ -75,6 +75,30 @@ void errno_mkdtemp(char *template) {
   }
 }
 
+typedef char* CHAR_PTR;
+void errno_mkdtemp2(CHAR_PTR template) {
+  CHAR_PTR Dir = mkdtemp(template);
+  if (Dir == NULL) {
+    clang_analyzer_eval(errno != 0);      // expected-warning{{TRUE}}
+    if (errno) {}                         // no warning
+  } else {
+    clang_analyzer_eval(Dir == template); // expected-warning{{TRUE}}
+    if (errno) {}                         // expected-warning{{An undefined value may be read from 'errno'}}
+  }
+}
+
+typedef char const* CONST_CHAR_PTR;
+void errno_mkdtemp3(CHAR_PTR template) {
+  CONST_CHAR_PTR Dir = mkdtemp(template);
+  if (Dir == NULL) {
+    clang_analyzer_eval(errno != 0);      // expected-warning{{TRUE}}
+    if (errno) {}                         // no warning
+  } else {
+    clang_analyzer_eval(Dir == template); // expected-warning{{TRUE}}
+    if (errno) {}                         // expected-warning{{An undefined value may be read from 'errno'}}
+  }
+}
+
 void errno_getcwd(char *Buf, size_t Sz) {
   char *Path = getcwd(Buf, Sz);
   if (Sz == 0) {

@llvmbot
Copy link
Member

llvmbot commented Jun 17, 2024

@llvm/pr-subscribers-clang-static-analyzer-1

Author: Congcong Cai (HerrCai0907)

Changes

Fixes: #95658
Unqualified canonical type should be used instead of normal QualType for type equality comparison


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

2 Files Affected:

  • (modified) clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp (+2-1)
  • (modified) clang/test/Analysis/errno-stdlibraryfunctions.c (+24)
diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index c6f87b45ab887..d8c257dbd731e 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -2333,7 +2333,8 @@ inline ProgramStateRef EquivalenceClass::merge(RangeSet::Factory &F,
   //
   //        The moment we introduce symbolic casts, this restriction can be
   //        lifted.
-  if (getType() != Other.getType())
+  if (getType()->getCanonicalTypeUnqualified() !=
+      Other.getType()->getCanonicalTypeUnqualified())
     return State;
 
   SymbolSet Members = getClassMembers(State);
diff --git a/clang/test/Analysis/errno-stdlibraryfunctions.c b/clang/test/Analysis/errno-stdlibraryfunctions.c
index a28efb764edfd..657aa37a42670 100644
--- a/clang/test/Analysis/errno-stdlibraryfunctions.c
+++ b/clang/test/Analysis/errno-stdlibraryfunctions.c
@@ -75,6 +75,30 @@ void errno_mkdtemp(char *template) {
   }
 }
 
+typedef char* CHAR_PTR;
+void errno_mkdtemp2(CHAR_PTR template) {
+  CHAR_PTR Dir = mkdtemp(template);
+  if (Dir == NULL) {
+    clang_analyzer_eval(errno != 0);      // expected-warning{{TRUE}}
+    if (errno) {}                         // no warning
+  } else {
+    clang_analyzer_eval(Dir == template); // expected-warning{{TRUE}}
+    if (errno) {}                         // expected-warning{{An undefined value may be read from 'errno'}}
+  }
+}
+
+typedef char const* CONST_CHAR_PTR;
+void errno_mkdtemp3(CHAR_PTR template) {
+  CONST_CHAR_PTR Dir = mkdtemp(template);
+  if (Dir == NULL) {
+    clang_analyzer_eval(errno != 0);      // expected-warning{{TRUE}}
+    if (errno) {}                         // no warning
+  } else {
+    clang_analyzer_eval(Dir == template); // expected-warning{{TRUE}}
+    if (errno) {}                         // expected-warning{{An undefined value may be read from 'errno'}}
+  }
+}
+
 void errno_getcwd(char *Buf, size_t Sz) {
   char *Path = getcwd(Buf, Sz);
   if (Sz == 0) {

Copy link
Contributor

@steakhal steakhal left a comment

Choose a reason for hiding this comment

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

Awesome. I have one remark though.
It would be nice to see tests that does not depend on the errno, as this eqclass merging is a major vore feature, unlike the errno modeling which is an optional feature. If have something in mind, you could add that test in addition you already propose.

Again, cool stuff!

@HerrCai0907 HerrCai0907 requested a review from steakhal June 17, 2024 12:44
Copy link
Contributor

@NagyDonat NagyDonat left a comment

Choose a reason for hiding this comment

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

Nice catch, thanks for fixing this bug!

Copy link
Contributor

@steakhal steakhal left a comment

Choose a reason for hiding this comment

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

Excellent quality. Thank for fixing this.
Do you need us to merge this, or you have merge rights?

@HerrCai0907
Copy link
Contributor Author

Do you need us to merge this, or you have merge rights?

Yes.

@HerrCai0907 HerrCai0907 merged commit 0851d7b into llvm:main Jun 17, 2024
7 checks passed
@HerrCai0907 HerrCai0907 deleted the 95658-static-analyzer-false-positive-in-unixerrno branch June 17, 2024 15:37
@HerrCai0907
Copy link
Contributor Author

Excellent quality. Thank for fixing this.

Should I fix the other type comparison in static analysis? It looks like not consider this case at lots of position.

@steakhal
Copy link
Contributor

Excellent quality. Thank for fixing this.

Should I fix the other type comparison in static analysis? It looks like not consider this case at lots of position.

I think you are right. And in most cases within CSA, we should usually compare canonical types.
If you wanna hunt for some, we would be happy to review your findings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:static analyzer clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[static-analyzer] false positive in unix.Errno
4 participants