[pushed] analyzer: fix ICE on infoleak with poisoned size

Message ID 20231208210256.2705893-1-dmalcolm@redhat.com
State Accepted
Headers
Series [pushed] analyzer: fix ICE on infoleak with poisoned size |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

David Malcolm Dec. 8, 2023, 9:02 p.m. UTC
  Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r14-6348-g08262e78209ed4.

gcc/analyzer/ChangeLog:
	* region-model.cc (contains_uninit_p): Only check for
	svalues that the infoleak warning can handle.

gcc/testsuite/ChangeLog:
	* gcc.dg/plugin/infoleak-uninit-size-1.c: New test.
	* gcc.dg/plugin/infoleak-uninit-size-2.c: New test.
	* gcc.dg/plugin/plugin.exp: Add the new tests.
---
 gcc/analyzer/region-model.cc                  | 37 ++++++++++++-------
 .../gcc.dg/plugin/infoleak-uninit-size-1.c    | 20 ++++++++++
 .../gcc.dg/plugin/infoleak-uninit-size-2.c    | 20 ++++++++++
 gcc/testsuite/gcc.dg/plugin/plugin.exp        |  2 +
 4 files changed, 66 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/plugin/infoleak-uninit-size-1.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/infoleak-uninit-size-2.c
  

Patch

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 2157ad2578b..9b970d7a3e3 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -6557,22 +6557,33 @@  private:
 static bool
 contains_uninit_p (const svalue *sval)
 {
-  struct uninit_finder : public visitor
-  {
-  public:
-    uninit_finder () : m_found_uninit (false) {}
-    void visit_poisoned_svalue (const poisoned_svalue *sval)
+  switch (sval->get_kind ())
     {
-      if (sval->get_poison_kind () == POISON_KIND_UNINIT)
-	m_found_uninit = true;
-    }
-    bool m_found_uninit;
-  };
+    default:
+      return false;
+    case SK_POISONED:
+      {
+	const poisoned_svalue *psval
+	  = as_a <const poisoned_svalue *> (sval);
+	return psval->get_poison_kind () == POISON_KIND_UNINIT;
+      }
+    case SK_COMPOUND:
+      {
+	const compound_svalue *compound_sval
+	  = as_a <const compound_svalue *> (sval);
 
-  uninit_finder v;
-  sval->accept (&v);
+	for (auto iter : *compound_sval)
+	  {
+	    const svalue *sval = iter.second;
+	    if (const poisoned_svalue *psval
+		= sval->dyn_cast_poisoned_svalue ())
+	      if (psval->get_poison_kind () == POISON_KIND_UNINIT)
+		return true;
+	  }
 
-  return v.m_found_uninit;
+	return false;
+      }
+    }
 }
 
 /* Function for use by plugins when simulating writing data through a
diff --git a/gcc/testsuite/gcc.dg/plugin/infoleak-uninit-size-1.c b/gcc/testsuite/gcc.dg/plugin/infoleak-uninit-size-1.c
new file mode 100644
index 00000000000..7466112fe14
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/infoleak-uninit-size-1.c
@@ -0,0 +1,20 @@ 
+/* Reduced from infoleak ICE seen on Linux kernel with
+   -Wno-analyzer-use-of-uninitialized-value.
+
+   Verify that we don't ICE when complaining about an infoleak
+   when the size is uninitialized.  */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer -Wno-analyzer-use-of-uninitialized-value" } */
+/* { dg-require-effective-target analyzer } */
+
+extern unsigned long
+copy_to_user(void* to, const void* from, unsigned long n);
+
+unsigned long
+test_uninit_size (void *to, void *from)
+{
+  unsigned long n;
+  char buf[16];
+  return copy_to_user(to, from, n);
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/infoleak-uninit-size-2.c b/gcc/testsuite/gcc.dg/plugin/infoleak-uninit-size-2.c
new file mode 100644
index 00000000000..a8a383f4b2d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/infoleak-uninit-size-2.c
@@ -0,0 +1,20 @@ 
+/* Reduced from infoleak ICE seen on Linux kernel with
+   -Wno-analyzer-use-of-uninitialized-value.
+
+   Verify that we complain about the uninit value when
+   -Wno-analyzer-use-of-uninitialized-value isn't supplied.  */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer" } */
+/* { dg-require-effective-target analyzer } */
+
+extern unsigned long
+copy_to_user(void* to, const void* from, unsigned long n);
+
+unsigned long
+test_uninit_size (void *to, void *from)
+{
+  unsigned long n;
+  char buf[16];
+  return copy_to_user(to, from, n); /* { dg-warning "use of uninitialized value 'n'" } */
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index f0b4bb7a051..d6cccb269df 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -150,6 +150,8 @@  set plugin_test_list [list \
 	  infoleak-CVE-2017-18550-1.c \
 	  infoleak-antipatterns-1.c \
 	  infoleak-fixit-1.c \
+	  infoleak-uninit-size-1.c \
+	  infoleak-uninit-size-2.c \
 	  infoleak-net-ethtool-ioctl.c \
 	  infoleak-vfio_iommu_type1.c \
 	  taint-CVE-2011-0521-1-fixed.c \