]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
analyzer: fix defaults in compound assignments from non-zero offsets [PR112969]
authorDavid Malcolm <dmalcolm@redhat.com>
Thu, 25 Jan 2024 15:06:12 +0000 (10:06 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Thu, 25 Jan 2024 15:06:12 +0000 (10:06 -0500)
Confusion in binding_cluster::maybe_get_compound_binding about whether
offsets are relative to the start of the region or to the start of the
cluster was leading to incorrect handling of default values, leading
to false positives from -Wanalyzer-use-of-uninitialized-value, from
-Wanalyzer-exposure-through-uninit-copy, and other logic errors.

Fixed thusly.

gcc/analyzer/ChangeLog:
PR analyzer/112969
* store.cc (binding_cluster::maybe_get_compound_binding): When
populating default_map, express the bit-range of the default key
for REG relative to REG, rather than to the base region.

gcc/testsuite/ChangeLog:
PR analyzer/112969
* c-c++-common/analyzer/compound-assignment-5.c (test_3): Remove
xfails, reorder tests.
* c-c++-common/analyzer/compound-assignment-pr112969.c: New test.
* gcc.dg/plugin/infoleak-pr112969.c: New test.
* gcc.dg/plugin/plugin.exp: Add infoleak-pr112969.c to
analyzer_kernel_plugin.c tests.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
gcc/analyzer/store.cc
gcc/testsuite/c-c++-common/analyzer/compound-assignment-5.c
gcc/testsuite/c-c++-common/analyzer/compound-assignment-pr112969.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/plugin/infoleak-pr112969.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/plugin/plugin.exp

index 67c90b7fce4a002445c1ca76eb7d4caada384557..e85a19647f7eaf7375dfd861b87639a45bf8cffd 100644 (file)
@@ -1759,7 +1759,16 @@ binding_cluster::maybe_get_compound_binding (store_manager *mgr,
   else
     default_sval = sval_mgr->get_or_create_initial_value (reg);
   const binding_key *default_key = binding_key::make (mgr, reg);
-  default_map.put (default_key, default_sval);
+
+  /* Express the bit-range of the default key for REG relative to REG,
+     rather than to the base region.  */
+  const concrete_binding *concrete_default_key
+    = default_key->dyn_cast_concrete_binding ();
+  if (!concrete_default_key)
+    return nullptr;
+  const concrete_binding *default_key_relative_to_reg
+     = mgr->get_concrete_binding (0, concrete_default_key->get_size_in_bits ());
+  default_map.put (default_key_relative_to_reg, default_sval);
 
   for (map_t::iterator iter = m_map.begin (); iter != m_map.end (); ++iter)
     {
index 3ce2b72c8ff3b503103b852fedfb6f29a6b2e044..08f10606d91f096fa3c218fdac7beb45cfd71d4c 100644 (file)
@@ -48,9 +48,8 @@ void test_3 (void)
 
   glob_arr3[7] = arr[3]; // or should the uninit warning be here?
 
-  __analyzer_eval (glob_arr3[7].x); /* { dg-warning "uninitialized" "uninit" { xfail *-*-* } } */
-  /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */
   __analyzer_eval (glob_arr3[7].y == 6); /* { dg-warning "TRUE" } */
+  __analyzer_eval (glob_arr3[7].x); /* { dg-warning "uninitialized" "uninit" } */
 }
 
 /* Symbolic bindings: copying from one array to another.  */
diff --git a/gcc/testsuite/c-c++-common/analyzer/compound-assignment-pr112969.c b/gcc/testsuite/c-c++-common/analyzer/compound-assignment-pr112969.c
new file mode 100644 (file)
index 0000000..4bc037c
--- /dev/null
@@ -0,0 +1,35 @@
+/* Reduced from -Wanalyzer-exposure-through-uninit-copy false positives
+   seen in Linux kernel in drivers/net/ethernet/intel/ice/ice_ptp.c  */
+
+#include "analyzer-decls.h"
+
+/* { dg-do compile } */
+
+struct hwtstamp_config
+{
+  int flags;
+  int tx_type;
+  int rx_filter;
+};
+
+struct ice_ptp
+{
+  long placeholder;
+  struct hwtstamp_config tstamp_config;
+};
+
+struct ice_pf
+{
+  struct ice_ptp ptp;
+};
+
+void
+ice_ptp_set_ts_config(struct ice_pf* pf)
+{
+  struct hwtstamp_config config;
+  pf->ptp.tstamp_config.tx_type = 1;
+  pf->ptp.tstamp_config.rx_filter = 2;
+  config = pf->ptp.tstamp_config;
+  __analyzer_eval (config.flags == pf->ptp.tstamp_config.flags); /* { dg-warning "TRUE" } */
+  /* { dg-bogus "use of uninitialized value 'config.flags'" "PR analyzer/112969" { target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/infoleak-pr112969.c b/gcc/testsuite/gcc.dg/plugin/infoleak-pr112969.c
new file mode 100644 (file)
index 0000000..e78fe36
--- /dev/null
@@ -0,0 +1,52 @@
+/* Reduced from -Wanalyzer-exposure-through-uninit-copy false positives
+   seen in Linux kernel in drivers/net/ethernet/intel/ice/ice_ptp.c  */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer" } */
+/* { dg-require-effective-target analyzer } */
+
+extern unsigned long
+copy_from_user(void* to, const void* from, unsigned long n);
+
+extern unsigned long
+copy_to_user(void* to, const void* from, unsigned long n);
+
+struct ifreq
+{
+  union
+  {
+    void* ifru_data;
+  } ifr_ifru;
+};
+
+struct hwtstamp_config
+{
+  int flags;
+  int tx_type;
+  int rx_filter;
+};
+
+struct ice_ptp
+{
+  long placeholder;
+  struct hwtstamp_config tstamp_config;
+};
+
+struct ice_pf
+{
+  struct ice_ptp ptp;
+};
+int
+ice_ptp_set_ts_config(struct ice_pf* pf, struct ifreq* ifr)
+{
+  struct hwtstamp_config config;
+  int err;
+  if (copy_from_user(&config, ifr->ifr_ifru.ifru_data, sizeof(config)))
+    return -14;
+  pf->ptp.tstamp_config.tx_type = 0;
+  pf->ptp.tstamp_config.rx_filter = 0;
+  config = pf->ptp.tstamp_config;
+  if (copy_to_user(ifr->ifr_ifru.ifru_data, &config, sizeof(config))) /* { dg-bogus "-Wanalyzer-exposure-through-uninit-copy" "PR analyzer/112969" } */
+    return -14;
+  return 0;
+}
index 8141cc2aa46d1a522715cde4acf9c65aa5bfbb7f..c26dda1f324baa0b6f302f532b008fd04165f12f 100644 (file)
@@ -150,6 +150,7 @@ set plugin_test_list [list \
          infoleak-CVE-2017-18550-1.c \
          infoleak-antipatterns-1.c \
          infoleak-fixit-1.c \
+         infoleak-pr112969.c \
          infoleak-uninit-size-1.c \
          infoleak-uninit-size-2.c \
          infoleak-net-ethtool-ioctl.c \