public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics)
@ 2024-05-09 17:42 David Malcolm
  2024-05-09 17:42 ` [PATCH 01/21] analyzer: add caching to globals with initializers [PR110112] David Malcolm
                   ` (21 more replies)
  0 siblings, 22 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

I've pushed the following changes to releases/gcc-13
as r13-8741-g89feb3557a0188 through r13-8761-gb7a2697733d19a.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Lightly manually tested for patches that didn't have automated test
coverage, and where the patches needing non-trivial changes.

* [pushed] analyzer: add caching to globals with initializers [PR110112]
  * https://gcc.gnu.org/pipermail/gcc-patches/2023-June/621205.html
    Trunk: r14-1664-gfe9771b59f576f.
    gcc 13: r13-8741-g89feb3557a0188

* analyzer: Fix allocation size false positive on conjured svalue [PR109577]
  Trunk: r14-1684-g1d57a2232575913ad1085bac0ba5e22b58185179
  gcc 13: r13-8742-gccf8d3e3d26c6b

* testsuite: Add more allocation size tests for conjured svalues [PR110014]
  Trunk: r14-1685-g39adc5eebd61fd276f3f1ef9d7228756a35bd0cb
  gcc 13: r13-8743-ge0c52905f666e3

* [pushed 1/2] jit: avoid using __vector in testcase [PR110466]
  * https://gcc.gnu.org/pipermail/gcc-patches/2023-June/623343.html
  Trunk: r14-2222-g6735d660839533
  gcc 13: r13-8744-gb38472ffc1e631
* [pushed 2/2] jit.exp: handle dwarf version mismatch in jit-check-debug-info [PR110466]
  * https://gcc.gnu.org/pipermail/gcc-patches/2023-June/623344.html
  Trunk: r14-2223-gc3c0ba5436170e.
  gcc 13: r13-8745-g60dcb710b6b4aa

* [pushed] analyzer: fix ICE on division of tainted floating-point values [PR110700]
  * https://gcc.gnu.org/pipermail/gcc-patches/2023-July/624972.html
  Trunk: r14-2658-gb86c0fe327a519.
  gcc 13: r13-8746-g0df1ee083434ac

* [committed] analyzer: fix ICE on zero-sized arrays [PR110882]
  * https://gcc.gnu.org/pipermail/gcc-patches/2023-August/626226.html
  Trunk: r14-2955-gc62f93d1e0383d.
  gcc 13: r13-8747-ga0b13d0860848d

* [committed] testsuite, analyzer: add test case [PR108171]
  * https://gcc.gnu.org/pipermail/gcc-patches/2023-August/626247.html
  Trunk: r14-2957-gf80efa49b7a163.
  gcc 13: r13-8748-g44968a0e00f656

* [PATCH] gcc/jit/jit-recording.cc: recording::global::write_to_dump: Avoid crashes when writing psuedo-C for globals with string initializers.
  * https://gcc.gnu.org/pipermail/gcc-patches/2023-October/634269.html
    * Trunk: r14-4923-gac66744d94226a
  gcc 13: r13-8749-gb8c772cae97b54

* [pushed] analyzer: fix ICE for 2 bits before the start of base region [PR112889]
  * https://gcc.gnu.org/pipermail/gcc-patches/2023-December/639853.html
    * (cherry picked from commit r14-6297-g775aeabcb870b7)
  gcc 13: r13-8750-ga1cb188cb2ca2a (test moved to gcc.dg)

* [pushed] analyzer: fix deref-before-check false positives due to inlining [PR112790]
  * https://gcc.gnu.org/pipermail/gcc-patches/2024-January/641817.html
    * (cherry picked from commit r14-6918-g5743e1899d5964)
  gcc 13: r13-8751-g994477c41049d4 (test moved to gcc.dg)

* [pushed] analyzer: casting all zeroes should give all zeroes [PR113333]
  * https://gcc.gnu.org/pipermail/gcc-patches/2024-January/643059.html
    * (backported from commit r14-7265-gd235bf2e807c5f)
  gcc 13: r13-8752-g132eb1a210bc78

* [pushed] analyzer: fix defaults in compound assignments from non-zero offsets [PR112969]
  * https://gcc.gnu.org/pipermail/gcc-patches/2024-January/643951.html
    * (backported from commit r14-8428-g6426d466779fa8)
  gcc 13: r13-8753-g0593151221ad21

* [pushed] analyzer: fix skipping of debug stmts [PR113253]
  * https://gcc.gnu.org/pipermail/gcc-patches/2024-January/644615.html
    * (cherry picked from commit r14-8670-gcc7aebff74d896)
  gcc 13: r13-8754-g2c688f6afce4cb

* [pushed] analyzer: fix -Wanalyzer-va-arg-type-mismatch false +ve on int types [PR111289]
  * https://gcc.gnu.org/pipermail/gcc-patches/2024-February/646010.html
    * (cherry picked from commit r14-9076-g5651ad62b08096)
  gcc 13: r13-8755-g67d104f3a032ee (tests moved to gcc.dg)

* [pushed] analyzer: fix -Wanalyzer-deref-before-check false positive seen in loop header macro [PR109251]
  * https://gcc.gnu.org/pipermail/gcc-patches/2024-March/648126.html
    * Backported from commit r14-9586-g9093f275e0a343 (moving tests from c-c++-common to gcc.dg)
  gcc 13: 13-8756-ged026106ce420c

* [pushed] analyzer: fix ICE due to type mismatch when replaying call summary [PR114473]
  * https://gcc.gnu.org/pipermail/gcc-patches/2024-March/648500.html
    * (cherry picked from commit r14-9697-gfdd59818e2abf6)
  gcc 13: r13-8757-g810d35a7e054bc

* [pushed] analyzer: fix ICE and false positive with -Wanalyzer-deref-before-check [PR114408]
  * https://gcc.gnu.org/pipermail/gcc-patches/2024-March/648285.html
    * (cherry picked from commit r14-9646-g80a0cb37456c49)
  gcc 13: r13-8758-g96f7a3694c3e4c

* [pushed] diagnostics: fix ICE on sarif output when source file is unreadable [PR111700]
  * https://gcc.gnu.org/pipermail/gcc-patches/2023-October/632266.html
  Trunk: r14-4474-g94caa6a6b4bd73.
  gcc 13: r13-8759-g230f672b3ed0f6

* [pushed] Fix ICE in -fdiagnostics-generate-patch [PR112684]
  * https://gcc.gnu.org/pipermail/gcc-patches/2024-January/643386.html
    * (cherry picked from commit r14-8255-ge254d1224df306)
  gcc 13: r13-8760-g2a6f99aef7c852

* [pushed] diagnostics: fix corrupt json/SARIF on stderr [PR114348]
  * https://gcc.gnu.org/pipermail/gcc-patches/2024-March/648048.html
    * (backported from commit r14-9554-g0bf99b1b7eda2f)
  gcc 13: r13-8761-gb7a2697733d19a


David Malcolm (18):
  analyzer: add caching to globals with initializers [PR110112]
  jit: avoid using __vector in testcase [PR110466]
  jit.exp: handle dwarf version mismatch in jit-check-debug-info
    [PR110466]
  analyzer: fix ICE on division of tainted floating-point values
    [PR110700]
  analyzer: fix ICE on zero-sized arrays [PR110882]
  testsuite, analyzer: add test case [PR108171]
  analyzer: fix ICE for 2 bits before the start of base region
    [PR112889]
  analyzer: fix deref-before-check false positives due to inlining
    [PR112790]
  analyzer: casting all zeroes should give all zeroes [PR113333]
  analyzer: fix defaults in compound assignments from non-zero offsets
    [PR112969]
  analyzer: fix skipping of debug stmts [PR113253]
  analyzer: fix -Wanalyzer-va-arg-type-mismatch false +ve on int types
    [PR111289]
  analyzer: fix -Wanalyzer-deref-before-check false positive seen in
    loop header macro [PR109251]
  analyzer: fix ICE due to type mismatch when replaying call summary
    [PR114473]
  analyzer: fix ICE and false positive with
    -Wanalyzer-deref-before-check [PR114408]
  diagnostics: fix ICE on sarif output when source file is unreadable
    [PR111700]
  Fix ICE in -fdiagnostics-generate-patch [PR112684]
  diagnostics: fix corrupt json/SARIF on stderr [PR114348]

Tim Lange (2):
  analyzer: Fix allocation size false positive on conjured svalue
    [PR109577]
  testsuite: Add more allocation size tests for conjured svalues
    [PR110014]

Vibhav Pant (1):
  jit: dump string literal initializers correctly

 gcc/analyzer/call-summary.cc                  |  12 ++
 gcc/analyzer/checker-event.cc                 |  40 -----
 gcc/analyzer/constraint-manager.cc            | 131 +++++++++++++++
 gcc/analyzer/constraint-manager.h             |   1 +
 gcc/analyzer/engine.cc                        |   7 +
 gcc/analyzer/inlining-iterator.h              |  40 +++++
 gcc/analyzer/kf.cc                            |  22 +++
 gcc/analyzer/region-model-manager.cc          |   9 +-
 gcc/analyzer/region-model.cc                  | 110 ++++---------
 gcc/analyzer/region.cc                        |  77 ++++++++-
 gcc/analyzer/region.h                         |  14 +-
 gcc/analyzer/sm-malloc.cc                     |  40 +++++
 gcc/analyzer/sm-taint.cc                      |   6 +
 gcc/analyzer/state-purge.cc                   |   9 +
 gcc/analyzer/store.cc                         |  11 +-
 gcc/analyzer/store.h                          |  10 +-
 gcc/analyzer/supergraph.cc                    |   4 +
 gcc/analyzer/varargs.cc                       |  38 ++++-
 gcc/diagnostic.cc                             |  24 +++
 gcc/input.cc                                  |  12 +-
 gcc/jit/jit-recording.cc                      |   2 +-
 .../diagnostic-format-sarif-file-pr111700.c   |  12 ++
 .../ubsan/analyzer-ice-pr114408.c             |   9 +
 .../gcc.dg/analyzer/allocation-size-2.c       |  24 ++-
 .../gcc.dg/analyzer/call-summaries-pr114473.c |  31 ++++
 gcc/testsuite/gcc.dg/analyzer/calloc-1.c      |  34 ++++
 .../gcc.dg/analyzer/compound-assignment-5.c   |  29 ++--
 .../analyzer/compound-assignment-pr112969.c   |  35 ++++
 gcc/testsuite/gcc.dg/analyzer/data-model-9.c  |   6 +-
 .../analyzer/deref-before-check-pr109251-1.c  |  60 +++++++
 .../analyzer/deref-before-check-pr109251-2.c  |  37 +++++
 .../analyzer/deref-before-check-pr112790.c    |  27 +++
 .../analyzer/deref-before-check-pr113253.c    | 154 ++++++++++++++++++
 .../analyzer/deref-before-check-pr114408.c    |  22 +++
 gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c  |  17 ++
 gcc/testsuite/gcc.dg/analyzer/pr108171.c      |  31 ++++
 gcc/testsuite/gcc.dg/analyzer/pr109577.c      |  16 ++
 gcc/testsuite/gcc.dg/analyzer/pr110882.c      |  18 ++
 gcc/testsuite/gcc.dg/analyzer/pr96639.c       |   2 +-
 .../gcc.dg/analyzer/realloc-pr110014.c        |  25 +++
 .../gcc.dg/analyzer/stdarg-pr111289-int.c     |  69 ++++++++
 .../gcc.dg/analyzer/stdarg-pr111289-ptr.c     |  39 +++++
 .../gcc.dg/analyzer/taint-divisor-2.c         |  13 ++
 .../gcc.dg/plugin/infoleak-pr112969.c         |  52 ++++++
 gcc/testsuite/gcc.dg/plugin/plugin.exp        |   1 +
 gcc/testsuite/jit.dg/jit.exp                  |   4 +
 gcc/testsuite/jit.dg/test-expressions.c       |  22 +--
 gcc/toplev.cc                                 |   4 +-
 48 files changed, 1231 insertions(+), 181 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-pr111700.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/compound-assignment-pr112969.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-1.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-2.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr112790.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr113253.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr114408.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr108171.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr109577.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr110882.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-int.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-ptr.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/taint-divisor-2.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/infoleak-pr112969.c

-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 01/21] analyzer: add caching to globals with initializers [PR110112]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 02/21] analyzer: Fix allocation size false positive on conjured svalue [PR109577] David Malcolm
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

PR analyzer/110112 notes that -fanalyzer is extremely slow on a source
file with large read-only static arrays, repeatedly building the
same compound_svalue representing the full initializer, and repeatedly
building svalues representing parts of the the full initialiazer.

This patch adds caches for both of these; together they reduce the time
taken by -fanalyzer -O2 on the testcase in the bug for an optimized
build:
  91.2s : no caches (status quo)
  32.4s : cache in decl_region::get_svalue_for_constructor
   3.7s : cache in region::get_initial_value_at_main
   3.1s : both caches (this patch)

gcc/analyzer/ChangeLog:
	PR analyzer/110112
	* region-model.cc (region_model::get_initial_value_for_global):
	Move code to region::calc_initial_value_at_main.
	* region.cc (region::get_initial_value_at_main): New function.
	(region::calc_initial_value_at_main): New function, based on code
	in region_model::get_initial_value_for_global.
	(region::region): Initialize m_cached_init_sval_at_main.
	(decl_region::get_svalue_for_constructor): Add a cache, splitting
	out body to...
	(decl_region::calc_svalue_for_constructor): ...this new function.
	* region.h (region::get_initial_value_at_main): New decl.
	(region::calc_initial_value_at_main): New decl.
	(region::m_cached_init_sval_at_main): New field.
	(decl_region::decl_region): Initialize m_ctor_svalue.
	(decl_region::calc_svalue_for_constructor): New decl.
	(decl_region::m_ctor_svalue): New field.

(cherry picked from commit r14-1664-gfe9771b59f576f)

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/region-model.cc | 25 +------------
 gcc/analyzer/region.cc       | 71 +++++++++++++++++++++++++++++++++---
 gcc/analyzer/region.h        | 14 ++++++-
 3 files changed, 79 insertions(+), 31 deletions(-)

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index fb81d43f91b..18996c5e5e8 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -2355,30 +2355,7 @@ region_model::get_initial_value_for_global (const region *reg) const
      the initial value of REG can be taken from the initialization value
      of the decl.  */
   if (called_from_main_p () || TREE_READONLY (decl))
-    {
-      /* Attempt to get the initializer value for base_reg.  */
-      if (const svalue *base_reg_init
-	    = base_reg->get_svalue_for_initializer (m_mgr))
-	{
-	  if (reg == base_reg)
-	    return base_reg_init;
-	  else
-	    {
-	      /* Get the value for REG within base_reg_init.  */
-	      binding_cluster c (base_reg);
-	      c.bind (m_mgr->get_store_manager (), base_reg, base_reg_init);
-	      const svalue *sval
-		= c.get_any_binding (m_mgr->get_store_manager (), reg);
-	      if (sval)
-		{
-		  if (reg->get_type ())
-		    sval = m_mgr->get_or_create_cast (reg->get_type (),
-						      sval);
-		  return sval;
-		}
-	    }
-	}
-    }
+    return reg->get_initial_value_at_main (m_mgr);
 
   /* Otherwise, return INIT_VAL(REG).  */
   return m_mgr->get_or_create_initial_value (reg);
diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc
index a18bfa50d09..f982ce67509 100644
--- a/gcc/analyzer/region.cc
+++ b/gcc/analyzer/region.cc
@@ -272,6 +272,51 @@ region::can_have_initial_svalue_p () const
     }
 }
 
+/* For regions within a global decl, get the svalue for the initial
+   value of this region when the program starts, caching the result.  */
+
+const svalue *
+region::get_initial_value_at_main (region_model_manager *mgr) const
+{
+  if (!m_cached_init_sval_at_main)
+    m_cached_init_sval_at_main = calc_initial_value_at_main (mgr);
+  return m_cached_init_sval_at_main;
+}
+
+/* Implementation of region::get_initial_value_at_main.  */
+
+const svalue *
+region::calc_initial_value_at_main (region_model_manager *mgr) const
+{
+  const decl_region *base_reg = get_base_region ()->dyn_cast_decl_region ();
+  gcc_assert (base_reg);
+
+  /* Attempt to get the initializer value for base_reg.  */
+  if (const svalue *base_reg_init
+      = base_reg->get_svalue_for_initializer (mgr))
+    {
+      if (this == base_reg)
+	return base_reg_init;
+      else
+	{
+	  /* Get the value for REG within base_reg_init.  */
+	  binding_cluster c (base_reg);
+	  c.bind (mgr->get_store_manager (), base_reg, base_reg_init);
+	  const svalue *sval
+	    = c.get_any_binding (mgr->get_store_manager (), this);
+	  if (sval)
+	    {
+	      if (get_type ())
+		sval = mgr->get_or_create_cast (get_type (), sval);
+	      return sval;
+	    }
+	}
+    }
+
+  /* Otherwise, return INIT_VAL(REG).  */
+  return mgr->get_or_create_initial_value (this);
+}
+
 /* If this region is a decl_region, return the decl.
    Otherwise return NULL.  */
 
@@ -701,7 +746,7 @@ region::is_named_decl_p (const char *decl_name) const
 
 region::region (complexity c, unsigned id, const region *parent, tree type)
 : m_complexity (c), m_id (id), m_parent (parent), m_type (type),
-  m_cached_offset (NULL)
+  m_cached_offset (NULL), m_cached_init_sval_at_main (NULL)
 {
   gcc_assert (type == NULL_TREE || TYPE_P (type));
 }
@@ -1170,14 +1215,13 @@ decl_region::maybe_get_constant_value (region_model_manager *mgr) const
   return NULL;
 }
 
-/* Get an svalue for CTOR, a CONSTRUCTOR for this region's decl.  */
+/* Implementation of decl_region::get_svalue_for_constructor
+   for when the cached value hasn't yet been calculated.  */
 
 const svalue *
-decl_region::get_svalue_for_constructor (tree ctor,
-					 region_model_manager *mgr) const
+decl_region::calc_svalue_for_constructor (tree ctor,
+					  region_model_manager *mgr) const
 {
-  gcc_assert (!TREE_CLOBBER_P (ctor));
-
   /* Create a binding map, applying ctor to it, using this
      decl_region as the base region when building child regions
      for offset calculations.  */
@@ -1189,6 +1233,21 @@ decl_region::get_svalue_for_constructor (tree ctor,
   return mgr->get_or_create_compound_svalue (get_type (), map);
 }
 
+/* Get an svalue for CTOR, a CONSTRUCTOR for this region's decl.  */
+
+const svalue *
+decl_region::get_svalue_for_constructor (tree ctor,
+					 region_model_manager *mgr) const
+{
+  gcc_assert (!TREE_CLOBBER_P (ctor));
+  gcc_assert (ctor == DECL_INITIAL (m_decl));
+
+  if (!m_ctor_svalue)
+    m_ctor_svalue = calc_svalue_for_constructor (ctor, mgr);
+
+  return m_ctor_svalue;
+}
+
 /* For use on decl_regions for global variables.
 
    Get an svalue for the initial value of this region at entry to
diff --git a/gcc/analyzer/region.h b/gcc/analyzer/region.h
index 5df0ae7487b..270e5042eeb 100644
--- a/gcc/analyzer/region.h
+++ b/gcc/analyzer/region.h
@@ -161,6 +161,7 @@ public:
   const frame_region *maybe_get_frame_region () const;
   enum memory_space get_memory_space () const;
   bool can_have_initial_svalue_p () const;
+  const svalue *get_initial_value_at_main (region_model_manager *mgr) const;
 
   tree maybe_get_decl () const;
 
@@ -240,6 +241,7 @@ public:
 
  private:
   region_offset calc_offset (region_model_manager *mgr) const;
+  const svalue *calc_initial_value_at_main (region_model_manager *mgr) const;
 
   complexity m_complexity;
   unsigned m_id; // purely for deterministic sorting at this stage, for dumps
@@ -247,6 +249,10 @@ public:
   tree m_type;
 
   mutable region_offset *m_cached_offset;
+
+  /* For regions within a global decl, a cache of the svalue for the initial
+     value of this region when the program starts.  */
+  mutable const svalue *m_cached_init_sval_at_main;
 };
 
 } // namespace ana
@@ -696,7 +702,8 @@ class decl_region : public region
 public:
   decl_region (unsigned id, const region *parent, tree decl)
   : region (complexity (parent), id, parent, TREE_TYPE (decl)), m_decl (decl),
-    m_tracked (calc_tracked_p (decl))
+    m_tracked (calc_tracked_p (decl)),
+    m_ctor_svalue (NULL)
   {}
 
   enum region_kind get_kind () const final override { return RK_DECL; }
@@ -716,6 +723,8 @@ public:
   const svalue *get_svalue_for_initializer (region_model_manager *mgr) const;
 
 private:
+  const svalue *calc_svalue_for_constructor (tree ctor,
+					     region_model_manager *mgr) const;
   static bool calc_tracked_p (tree decl);
 
   tree m_decl;
@@ -725,6 +734,9 @@ private:
      store objects).
      This can be debugged using -fdump-analyzer-untracked.  */
   bool m_tracked;
+
+  /* Cached result of get_svalue_for_constructor.  */
+  mutable const svalue *m_ctor_svalue;
 };
 
 } // namespace ana
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 02/21] analyzer: Fix allocation size false positive on conjured svalue [PR109577]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
  2024-05-09 17:42 ` [PATCH 01/21] analyzer: add caching to globals with initializers [PR110112] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-11 16:43   ` NightStrike
  2024-05-09 17:42 ` [PATCH 03/21] testsuite: Add more allocation size tests for conjured svalues [PR110014] David Malcolm
                   ` (19 subsequent siblings)
  21 siblings, 1 reply; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: Tim Lange, David Malcolm

From: Tim Lange <mail@tim-lange.me>

Currently, the analyzer tries to prove that the allocation size is a
multiple of the pointee's type size.  This patch reverses the behavior
to try to prove that the expression is not a multiple of the pointee's
type size.  With this change, each unhandled case should be gracefully
considered as correct.  This fixes the bug reported in PR 109577 by
Paul Eggert.

Regression-tested on Linux x86-64 with -m32 and -m64.

2023-06-09  Tim Lange  <mail@tim-lange.me>

	PR analyzer/109577

gcc/analyzer/ChangeLog:

	* constraint-manager.cc (class sval_finder): Visitor to find
	childs in svalue trees.
	(constraint_manager::sval_constrained_p): Add new function to
	check whether a sval might be part of an constraint.
	* constraint-manager.h: Add sval_constrained_p function.
	* region-model.cc (class size_visitor): Reverse behavior to not
	emit a warning on not explicitly considered cases.
	(region_model::check_region_size):
	Adapt to size_visitor changes.

gcc/testsuite/ChangeLog:

	* gcc.dg/analyzer/allocation-size-2.c: Change expected output
	and add new test case.
	* gcc.dg/analyzer/pr109577.c: New test.

(cherry picked from commit r14-1684-g1d57a2232575913ad1085bac0ba5e22b58185179)

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/constraint-manager.cc            | 131 ++++++++++++++++++
 gcc/analyzer/constraint-manager.h             |   1 +
 gcc/analyzer/region-model.cc                  |  80 ++++-------
 .../gcc.dg/analyzer/allocation-size-2.c       |  24 ++--
 gcc/testsuite/gcc.dg/analyzer/pr109577.c      |  16 +++
 5 files changed, 194 insertions(+), 58 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr109577.c

diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc
index 2c9c435527e..9211366fb7c 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -2218,6 +2218,137 @@ constraint_manager::get_equiv_class_by_svalue (const svalue *sval,
   return false;
 }
 
+/* Tries to find a svalue inside another svalue.  */
+
+class sval_finder : public visitor
+{
+public:
+  sval_finder (const svalue *query) : m_query (query), m_found (false)
+  {
+  }
+
+  bool found_query_p ()
+  {
+    return m_found;
+  }
+
+  void visit_region_svalue (const region_svalue *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_constant_svalue (const constant_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_unknown_svalue (const unknown_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_poisoned_svalue (const poisoned_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_setjmp_svalue (const setjmp_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_initial_svalue (const initial_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_unaryop_svalue (const unaryop_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_binop_svalue (const binop_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_sub_svalue (const sub_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_repeated_svalue (const repeated_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_bits_within_svalue (const bits_within_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_unmergeable_svalue (const unmergeable_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_placeholder_svalue (const placeholder_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_widening_svalue (const widening_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_compound_svalue (const compound_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_conjured_svalue (const conjured_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_asm_output_svalue (const asm_output_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+  void visit_const_fn_result_svalue (const const_fn_result_svalue  *sval)
+  {
+    m_found |= m_query == sval;
+  }
+
+private:
+  const svalue *m_query;
+  bool m_found;
+};
+
+/* Returns true if SVAL is constrained.  */
+
+bool
+constraint_manager::sval_constrained_p (const svalue *sval) const
+{
+  int i;
+  equiv_class *ec;
+  sval_finder finder (sval);
+  FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
+    {
+      int j;
+      const svalue *iv;
+      FOR_EACH_VEC_ELT (ec->m_vars, j, iv)
+	{
+	  iv->accept (&finder);
+	  if (finder.found_query_p ())
+	    return true;
+	}
+    }
+  return false;
+}
+
 /* Ensure that SVAL has an equivalence class within this constraint_manager;
    return the ID of the class.  */
 
diff --git a/gcc/analyzer/constraint-manager.h b/gcc/analyzer/constraint-manager.h
index 3afbc7f848e..72753e43c96 100644
--- a/gcc/analyzer/constraint-manager.h
+++ b/gcc/analyzer/constraint-manager.h
@@ -459,6 +459,7 @@ public:
 
   bool get_equiv_class_by_svalue (const svalue *sval,
 				    equiv_class_id *out) const;
+  bool sval_constrained_p (const svalue *sval) const;
   equiv_class_id get_or_add_equiv_class (const svalue *sval);
   tristate eval_condition (equiv_class_id lhs,
 			   enum tree_code op,
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 18996c5e5e8..c98b09d5322 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -2949,7 +2949,7 @@ capacity_compatible_with_type (tree cst, tree pointee_size_tree)
 
    It works by visiting all svalues inside SVAL until it reaches
    atomic nodes.  From those, it goes back up again and adds each
-   node that might be a multiple of SIZE_CST to the RESULT_SET.  */
+   node that is not a multiple of SIZE_CST to the RESULT_SET.  */
 
 class size_visitor : public visitor
 {
@@ -2960,7 +2960,7 @@ public:
     m_root_sval->accept (this);
   }
 
-  bool get_result ()
+  bool is_dubious_capacity ()
   {
     return result_set.contains (m_root_sval);
   }
@@ -2970,22 +2970,10 @@ public:
     check_constant (sval->get_constant (), sval);
   }
 
-  void visit_unknown_svalue (const unknown_svalue *sval ATTRIBUTE_UNUSED)
-    final override
-  {
-    result_set.add (sval);
-  }
-
-  void visit_poisoned_svalue (const poisoned_svalue *sval ATTRIBUTE_UNUSED)
-    final override
-  {
-    result_set.add (sval);
-  }
-
   void visit_unaryop_svalue (const unaryop_svalue *sval) final override
   {
-    const svalue *arg = sval->get_arg ();
-    if (result_set.contains (arg))
+    if (CONVERT_EXPR_CODE_P (sval->get_op ())
+	  && result_set.contains (sval->get_arg ()))
       result_set.add (sval);
   }
 
@@ -2994,28 +2982,24 @@ public:
     const svalue *arg0 = sval->get_arg0 ();
     const svalue *arg1 = sval->get_arg1 ();
 
-    if (sval->get_op () == MULT_EXPR)
-      {
-	if (result_set.contains (arg0) || result_set.contains (arg1))
-	  result_set.add (sval);
-      }
-    else
+    switch (sval->get_op ())
       {
-	if (result_set.contains (arg0) && result_set.contains (arg1))
-	  result_set.add (sval);
+	case MULT_EXPR:
+	  if (result_set.contains (arg0) && result_set.contains (arg1))
+	    result_set.add (sval);
+	  break;
+	case PLUS_EXPR:
+	case MINUS_EXPR:
+	  if (result_set.contains (arg0) || result_set.contains (arg1))
+	    result_set.add (sval);
+	  break;
+	default:
+	  break;
       }
   }
 
-  void visit_repeated_svalue (const repeated_svalue *sval) final override
-  {
-    sval->get_inner_svalue ()->accept (this);
-    if (result_set.contains (sval->get_inner_svalue ()))
-      result_set.add (sval);
-  }
-
   void visit_unmergeable_svalue (const unmergeable_svalue *sval) final override
   {
-    sval->get_arg ()->accept (this);
     if (result_set.contains (sval->get_arg ()))
       result_set.add (sval);
   }
@@ -3025,33 +3009,30 @@ public:
     const svalue *base = sval->get_base_svalue ();
     const svalue *iter = sval->get_iter_svalue ();
 
-    if (result_set.contains (base) && result_set.contains (iter))
+    if (result_set.contains (base) || result_set.contains (iter))
       result_set.add (sval);
   }
 
-  void visit_conjured_svalue (const conjured_svalue *sval ATTRIBUTE_UNUSED)
-    final override
+  void visit_initial_svalue (const initial_svalue *sval) final override
   {
-    equiv_class_id id (-1);
+    equiv_class_id id = equiv_class_id::null ();
     if (m_cm->get_equiv_class_by_svalue (sval, &id))
       {
 	if (tree cst = id.get_obj (*m_cm).get_any_constant ())
 	  check_constant (cst, sval);
-	else
-	  result_set.add (sval);
+      }
+    else if (!m_cm->sval_constrained_p (sval))
+      {
+	result_set.add (sval);
       }
   }
 
-  void visit_asm_output_svalue (const asm_output_svalue *sval ATTRIBUTE_UNUSED)
-    final override
-  {
-    result_set.add (sval);
-  }
-
-  void visit_const_fn_result_svalue (const const_fn_result_svalue
-				      *sval ATTRIBUTE_UNUSED) final override
+  void visit_conjured_svalue (const conjured_svalue *sval) final override
   {
-    result_set.add (sval);
+    equiv_class_id id = equiv_class_id::null ();
+    if (m_cm->get_equiv_class_by_svalue (sval, &id))
+      if (tree cst = id.get_obj (*m_cm).get_any_constant ())
+	check_constant (cst, sval);
   }
 
 private:
@@ -3061,10 +3042,9 @@ private:
       {
       default:
 	/* Assume all unhandled operands are compatible.  */
-	result_set.add (sval);
 	break;
       case INTEGER_CST:
-	if (capacity_compatible_with_type (cst, m_size_cst))
+	if (!capacity_compatible_with_type (cst, m_size_cst))
 	  result_set.add (sval);
 	break;
       }
@@ -3187,7 +3167,7 @@ region_model::check_region_size (const region *lhs_reg, const svalue *rhs_sval,
 	if (!is_struct)
 	  {
 	    size_visitor v (pointee_size_tree, capacity, m_constraints);
-	    if (!v.get_result ())
+	    if (v.is_dubious_capacity ())
 	      {
 		tree expr = get_representative_tree (capacity);
 		ctxt->warn (make_unique <dubious_allocation_size> (lhs_reg,
diff --git a/gcc/testsuite/gcc.dg/analyzer/allocation-size-2.c b/gcc/testsuite/gcc.dg/analyzer/allocation-size-2.c
index 2cf64e97b41..eb770f73d4a 100644
--- a/gcc/testsuite/gcc.dg/analyzer/allocation-size-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/allocation-size-2.c
@@ -76,13 +76,13 @@ void *create_buffer(int32_t n)
   return malloc(n);
 }
 
-void test_7(int32_t n) 
+void test_7(int32_t n)
 {
   int32_t *buf = create_buffer(n * sizeof (int32_t));
   free (buf);
 }
 
-void test_8(int32_t n) 
+void test_8(int32_t n)
 {
   /* FIXME: At the moment, region_model::set_value (lhs, <return_value>)
      is called at the src_node of the return edge. This edge has no stmts
@@ -98,13 +98,11 @@ void test_9 (void)
 {
   int32_t n;
   scanf("%i", &n);
-  /* n is a conjured_svalue.  */
-  void *ptr = malloc (n); /* { dg-message "'n' bytes" "note" } */
-  int32_t *iptr = (int32_t *)ptr; /* { dg-line assign9 } */
+  /* n is a conjured_svalue without any constraint. We have to assume
+     that is a multiple of sizeof (int32_t *); see PR analyzer/110014.  */
+  void *ptr = malloc (n);
+  int32_t *iptr = (int32_t *)ptr;
   free (iptr);
-
-  /* { dg-warning "allocated buffer size is not a multiple of the pointee's size \\\[CWE-131\\\]" "warning" { target *-*-* } assign9 } */
-  /* { dg-message "'int32_t \\*' (\\\{aka '(long )?int \\*'\\\})? here; 'sizeof \\(int32_t (\\\{aka (long )?int\\\})?\\)' is '4'" "note" { target *-*-* } assign9 } */
 }
 
 void test_11 (void)
@@ -157,3 +155,13 @@ void test_13 (void)
   else
     free (ptr);
 }
+
+int *test_14 (size_t n)
+{
+  int *ptr = NULL;
+  /* n is an initial_svalue and guarded such that there is no equiv_class
+     for n itself but only for a binop_svalue containing n.  */
+  if (n % sizeof (int) == 0)
+    ptr = malloc (n);
+  return ptr;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr109577.c b/gcc/testsuite/gcc.dg/analyzer/pr109577.c
new file mode 100644
index 00000000000..a6af6f7019f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr109577.c
@@ -0,0 +1,16 @@
+void *malloc (unsigned long);
+
+double *
+unsafe (unsigned long n)
+{
+  return malloc (n * sizeof (double));
+}
+
+double *
+safer (unsigned long n)
+{
+  unsigned long nbytes;
+  if (__builtin_mul_overflow (n, sizeof (double), &nbytes))
+    return 0;
+  return malloc (nbytes);
+}
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 03/21] testsuite: Add more allocation size tests for conjured svalues [PR110014]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
  2024-05-09 17:42 ` [PATCH 01/21] analyzer: add caching to globals with initializers [PR110112] David Malcolm
  2024-05-09 17:42 ` [PATCH 02/21] analyzer: Fix allocation size false positive on conjured svalue [PR109577] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-11 16:44   ` NightStrike
  2024-05-09 17:42 ` [PATCH 04/21] jit: avoid using __vector in testcase [PR110466] David Malcolm
                   ` (18 subsequent siblings)
  21 siblings, 1 reply; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: Tim Lange, David Malcolm

From: Tim Lange <mail@tim-lange.me>

This patch adds the reproducers reported in PR 110014 as test cases. The
false positives in those cases are already fixed with PR 109577.

2023-06-09  Tim Lange  <mail@tim-lange.me>

	PR analyzer/110014

gcc/testsuite/ChangeLog:

	* gcc.dg/analyzer/realloc-pr110014.c: New tests.

(cherry picked from commit r14-1685-g39adc5eebd61fd276f3f1ef9d7228756a35bd0cb)

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 .../gcc.dg/analyzer/realloc-pr110014.c        | 25 +++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c

diff --git a/gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c b/gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c
new file mode 100644
index 00000000000..d76b8781413
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c
@@ -0,0 +1,25 @@
+void *realloc (void *, unsigned long)
+  __attribute__((__nothrow__, __leaf__))
+  __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__ (2)));
+
+long *
+slurp (long *buffer, unsigned long file_size)
+{
+  unsigned long cc;
+  if (!__builtin_add_overflow (file_size - file_size % sizeof (long),
+			       2 * sizeof (long), &cc))
+    buffer = realloc (buffer, cc);
+  return buffer;
+}
+
+long *
+slurp1 (long *buffer, unsigned long file_size)
+{
+  return realloc (buffer, file_size - file_size % sizeof (long));
+}
+
+long *
+slurp2 (long *buffer, unsigned long file_size)
+{
+  return realloc (buffer, (file_size / sizeof (long)) * sizeof (long));
+}
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 04/21] jit: avoid using __vector in testcase [PR110466]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (2 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 03/21] testsuite: Add more allocation size tests for conjured svalues [PR110014] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 05/21] jit.exp: handle dwarf version mismatch in jit-check-debug-info [PR110466] David Malcolm
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm, Marek Polacek

r13-4531-gd2e782cb99c311 added test coverage to libgccjit's vector
support, but used __vector, which doesn't work on Power.  Additionally
the size param to gcc_jit_type_get_vector was wrong.

Fixed thusly.

gcc/testsuite/ChangeLog:
	PR jit/110466
	* jit.dg/test-expressions.c (run_test_of_comparison): Fix size
	param to gcc_jit_type_get_vector.
	(verify_comparisons): Use a typedef rather than __vector.

(cherry picked from commit r14-2222-g6735d660839533)

Co-authored-by: Marek Polacek <polacek@redhat.com>
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/testsuite/jit.dg/test-expressions.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/gcc/testsuite/jit.dg/test-expressions.c b/gcc/testsuite/jit.dg/test-expressions.c
index 13b3baf79ea..2337b01907e 100644
--- a/gcc/testsuite/jit.dg/test-expressions.c
+++ b/gcc/testsuite/jit.dg/test-expressions.c
@@ -417,7 +417,7 @@ static void run_test_of_comparison(gcc_jit_context *ctxt,
 			 const char *expected)
 {
   gcc_jit_type *vec_type =
-    gcc_jit_type_get_vector (type, 4);
+    gcc_jit_type_get_vector (type, 2);
 
   CHECK_STRING_VALUE (
     make_test_of_comparison (ctxt,
@@ -560,17 +560,17 @@ verify_comparisons (gcc_jit_result *result)
   CHECK_VALUE (test_COMPARISON_GE_on_int (1, 2), 0);
   CHECK_VALUE (test_COMPARISON_GE_on_int (2, 1), 1);
 
-  typedef int __vector __attribute__ ((__vector_size__ (sizeof(int) * 2)));
-  typedef __vector (*test_vec_fn) (__vector, __vector);
+  typedef int v2si __attribute__ ((__vector_size__ (sizeof(int) * 2)));
+  typedef v2si (*test_vec_fn) (v2si, v2si);
 
-  __vector zero_zero = {0, 0};
-  __vector zero_one = {0, 1};
-  __vector one_zero = {1, 0};
+  v2si zero_zero = {0, 0};
+  v2si zero_one = {0, 1};
+  v2si one_zero = {1, 0};
 
-  __vector true_true = {-1, -1};
-  __vector false_true = {0, -1};
-  __vector true_false = {-1, 0};
-  __vector false_false = {0, 0};
+  v2si true_true = {-1, -1};
+  v2si false_true = {0, -1};
+  v2si true_false = {-1, 0};
+  v2si false_false = {0, 0};
 
   test_vec_fn test_COMPARISON_EQ_on_vec_int =
     (test_vec_fn)gcc_jit_result_get_code (result,
@@ -615,7 +615,7 @@ verify_comparisons (gcc_jit_result *result)
   CHECK_VECTOR_VALUE (2, test_COMPARISON_GE_on_vec_int (zero_one, one_zero), false_true);
 
   typedef float __vector_f __attribute__ ((__vector_size__ (sizeof(float) * 2)));
-  typedef __vector (*test_vec_f_fn) (__vector_f, __vector_f);
+  typedef v2si (*test_vec_f_fn) (__vector_f, __vector_f);
 
   __vector_f zero_zero_f = {0, 0};
   __vector_f zero_one_f = {0, 1};
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 05/21] jit.exp: handle dwarf version mismatch in jit-check-debug-info [PR110466]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (3 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 04/21] jit: avoid using __vector in testcase [PR110466] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 06/21] analyzer: fix ICE on division of tainted floating-point values [PR110700] David Malcolm
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

gcc/testsuite/ChangeLog:
	PR jit/110466
	* jit.dg/jit.exp (jit-check-debug-info): Gracefully handle too
	early versions of gdb that don't support our dwarf version, via
	"unsupported".

(cherry picked from commit r14-2223-gc3c0ba5436170e)

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/testsuite/jit.dg/jit.exp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gcc/testsuite/jit.dg/jit.exp b/gcc/testsuite/jit.dg/jit.exp
index 35d38cec5bc..83fb6371fd2 100644
--- a/gcc/testsuite/jit.dg/jit.exp
+++ b/gcc/testsuite/jit.dg/jit.exp
@@ -440,6 +440,10 @@ proc jit-check-debug-info { obj_file cmds match } {
         send $cmd
     }
     expect {
+	-re "Dwarf Error: wrong version in compilation unit header" {
+	    set testcase [testname-for-summary]
+	    unsupported "$testcase: gdb does not support dwarf version"
+	}
         -re $match { pass OK }
         default { fail FAIL }
     }
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 06/21] analyzer: fix ICE on division of tainted floating-point values [PR110700]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (4 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 05/21] jit.exp: handle dwarf version mismatch in jit-check-debug-info [PR110466] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 07/21] analyzer: fix ICE on zero-sized arrays [PR110882] David Malcolm
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

gcc/analyzer/ChangeLog:
	PR analyzer/110700
	* region-model-manager.cc
	(region_model_manager::get_or_create_int_cst): Assert that we have
	an integral or pointer type.
	* sm-taint.cc (taint_state_machine::check_for_tainted_divisor):
	Don't check non-integral types.

gcc/testsuite/ChangeLog:
	PR analyzer/110700
	* gcc.dg/analyzer/taint-divisor-2.c: New test.

(cherry picked from commit r14-2658-gb86c0fe327a519)

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/region-model-manager.cc            |  3 ++-
 gcc/analyzer/sm-taint.cc                        |  6 ++++++
 gcc/testsuite/gcc.dg/analyzer/taint-divisor-2.c | 13 +++++++++++++
 3 files changed, 21 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/taint-divisor-2.c

diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc
index fab5bba15d5..1a9886fd83c 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -233,7 +233,8 @@ const svalue *
 region_model_manager::get_or_create_int_cst (tree type, poly_int64 val)
 {
   gcc_assert (type);
-  tree tree_cst = build_int_cst (type, val);
+  gcc_assert (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type));
+  tree tree_cst = wide_int_to_tree (type, val);
   return get_or_create_constant_svalue (tree_cst);
 }
 
diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index f72f194460c..7bce3ef79b2 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -1344,6 +1344,12 @@ taint_state_machine::check_for_tainted_divisor (sm_context *sm_ctxt,
     return;
 
   tree divisor_expr = gimple_assign_rhs2 (assign);;
+
+  /* Until we track conditions on floating point values, we can't check to
+     see if they've been checked against zero.  */
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (divisor_expr)))
+    return;
+
   const svalue *divisor_sval = old_model->get_rvalue (divisor_expr, NULL);
 
   state_t state = sm_ctxt->get_state (assign, divisor_sval);
diff --git a/gcc/testsuite/gcc.dg/analyzer/taint-divisor-2.c b/gcc/testsuite/gcc.dg/analyzer/taint-divisor-2.c
new file mode 100644
index 00000000000..de9a1cb3a46
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/taint-divisor-2.c
@@ -0,0 +1,13 @@
+// TODO: remove need for this option:
+/* { dg-additional-options "-fanalyzer-checker=taint" } */
+
+#include "analyzer-decls.h"
+
+__attribute__ ((tainted_args))
+double pr110700 (double x, double y)
+{
+  /* Ideally we'd complain here with -Wanalyzer-tainted-divisor, but
+     until we track conditions on floating point values, we can't check to
+     see if they've been checked against zero.  */
+  return x / y;
+}
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 07/21] analyzer: fix ICE on zero-sized arrays [PR110882]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (5 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 06/21] analyzer: fix ICE on division of tainted floating-point values [PR110700] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 08/21] testsuite, analyzer: add test case [PR108171] David Malcolm
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

gcc/analyzer/ChangeLog:
	PR analyzer/110882
	* region.cc (int_size_in_bits): Fail on zero-sized types.

gcc/testsuite/ChangeLog:
	PR analyzer/110882
	* gcc.dg/analyzer/pr110882.c: New test.

(cherry picked from commit r14-2955-gc62f93d1e0383d)

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/region.cc                   |  6 +++++-
 gcc/testsuite/gcc.dg/analyzer/pr110882.c | 18 ++++++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr110882.c

diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc
index f982ce67509..c1bfecabd15 100644
--- a/gcc/analyzer/region.cc
+++ b/gcc/analyzer/region.cc
@@ -395,7 +395,11 @@ int_size_in_bits (const_tree type, bit_size_t *out)
     }
 
   tree sz = TYPE_SIZE (type);
-  if (sz && tree_fits_uhwi_p (sz))
+  if (sz
+      && tree_fits_uhwi_p (sz)
+      /* If the size is zero, then we may have a zero-sized
+	 array; handle such cases by returning false.  */
+      && !integer_zerop (sz))
     {
       *out = TREE_INT_CST_LOW (sz);
       return true;
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr110882.c b/gcc/testsuite/gcc.dg/analyzer/pr110882.c
new file mode 100644
index 00000000000..80027184053
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr110882.c
@@ -0,0 +1,18 @@
+/* { dg-additional-options "-Wno-analyzer-too-complex" } */
+
+struct csv_row {
+  char *columns[0];
+};
+
+void
+parse_csv_line (int n_columns, const char *columns[])
+{
+  for (int n = 0; n < n_columns; n++) {
+      columns[n] = ((void *)0);
+  }
+}
+
+void parse_csv_data (int n_columns, struct csv_row *entry)
+{
+  parse_csv_line(n_columns, (const char **)entry->columns);
+}
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 08/21] testsuite, analyzer: add test case [PR108171]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (6 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 07/21] analyzer: fix ICE on zero-sized arrays [PR110882] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 09/21] jit: dump string literal initializers correctly David Malcolm
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

The ICE in PR analyzer/108171 appears to be a dup of the recently fixed
PR analyzer/110882 and is likewise fixed by it; adding this test case.

gcc/testsuite/ChangeLog:
	PR analyzer/108171
	* gcc.dg/analyzer/pr108171.c: New test.

(cherry picked from commit r14-2957-gf80efa49b7a163)

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/testsuite/gcc.dg/analyzer/pr108171.c | 31 ++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr108171.c

diff --git a/gcc/testsuite/gcc.dg/analyzer/pr108171.c b/gcc/testsuite/gcc.dg/analyzer/pr108171.c
new file mode 100644
index 00000000000..5f7b9fd7875
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr108171.c
@@ -0,0 +1,31 @@
+struct nl_context {
+  void *cmd_private;
+};
+
+struct sfeatures_context {
+  int a;
+  int req_mask[0];
+};
+
+int set_sf_req_mask_idx;
+
+extern void fill_legacy_flag();
+
+void
+fill_sfeatures_bitmap(struct nl_context *nlctx) {
+  while (nlctx) {
+    fill_legacy_flag();
+    struct nl_context __trans_tmp_1 = *nlctx;
+    struct sfeatures_context *sfctx = __trans_tmp_1.cmd_private;
+    sfctx->req_mask[set_sf_req_mask_idx] |= 1;
+  }
+}
+
+void
+nl_sfeatures() {
+  struct nl_context nlctx;
+  struct sfeatures_context *sfctx;
+  nlctx.cmd_private = &sfctx;
+  sfctx = 0;
+  fill_sfeatures_bitmap(&nlctx);
+}
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 09/21] jit: dump string literal initializers correctly
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (7 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 08/21] testsuite, analyzer: add test case [PR108171] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 10/21] analyzer: fix ICE for 2 bits before the start of base region [PR112889] David Malcolm
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: Vibhav Pant, David Malcolm

From: Vibhav Pant <vibhavp@gmail.com>

Signed-off-by: David Malcolm <dmalcolm@redhat.com>

gcc/jit/ChangeLog:
	* jit-recording.cc (recording::global::write_to_dump): Fix
	dump of string literal initializers.

(cherry picked from commit r14-4923-gac66744d94226a)

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/jit/jit-recording.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index df0368ff8f7..cf734cf7ef5 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -4919,7 +4919,7 @@ recording::global::write_to_dump (dump &d)
   else if (m_rvalue_init)
     {
       d.write (" = ");
-      d.write (m_rvalue_init->get_debug_string ());
+      d.write ("%s", m_rvalue_init->get_debug_string ());
       d.write (";\n");
     }
 
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 10/21] analyzer: fix ICE for 2 bits before the start of base region [PR112889]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (8 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 09/21] jit: dump string literal initializers correctly David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 11/21] analyzer: fix deref-before-check false positives due to inlining [PR112790] David Malcolm
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Cncrete bindings were using -1 and -2 in the offset field to signify
deleted and empty hash slots, but these are valid values, leading to
assertion failures inside hash_map::put on a debug build, and probable
bugs in a release build.

(gdb) call k.dump(true)
start: -2, size: 1, next: -1

(gdb) p k.is_empty()
$6 = true

Fix by using the size field rather than the offset.

Backported from commit r14-6297-g775aeabcb870b7 (moving the testcase
from c-c++-common to gcc.dg).

gcc/analyzer/ChangeLog:
	PR analyzer/112889
	* store.h (concrete_binding::concrete_binding): Strengthen
	assertion to require size to be be positive, rather than just
	non-zero.
	(concrete_binding::mark_deleted): Use size rather than start bit
	offset.
	(concrete_binding::mark_empty): Likewise.
	(concrete_binding::is_deleted): Likewise.
	(concrete_binding::is_empty): Likewise.

gcc/testsuite/ChangeLog:
	PR analyzer/112889
	* gcc.dg/analyzer/ice-pr112889.c: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/store.h                         | 10 +++++-----
 gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c | 17 +++++++++++++++++
 2 files changed, 22 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c

diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h
index 7ded650b608..6b06be29d8f 100644
--- a/gcc/analyzer/store.h
+++ b/gcc/analyzer/store.h
@@ -368,7 +368,7 @@ public:
   concrete_binding (bit_offset_t start_bit_offset, bit_size_t size_in_bits)
   : m_bit_range (start_bit_offset, size_in_bits)
   {
-    gcc_assert (!m_bit_range.empty_p ());
+    gcc_assert (m_bit_range.m_size_in_bits > 0);
   }
   bool concrete_p () const final override { return true; }
 
@@ -409,10 +409,10 @@ public:
 
   static int cmp_ptr_ptr (const void *, const void *);
 
-  void mark_deleted () { m_bit_range.m_start_bit_offset = -1; }
-  void mark_empty () { m_bit_range.m_start_bit_offset = -2; }
-  bool is_deleted () const { return m_bit_range.m_start_bit_offset == -1; }
-  bool is_empty () const { return m_bit_range.m_start_bit_offset == -2; }
+  void mark_deleted () { m_bit_range.m_size_in_bits = -1; }
+  void mark_empty () { m_bit_range.m_size_in_bits = -2; }
+  bool is_deleted () const { return m_bit_range.m_size_in_bits == -1; }
+  bool is_empty () const { return m_bit_range.m_size_in_bits == -2; }
 
 private:
   bit_range m_bit_range;
diff --git a/gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c b/gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c
new file mode 100644
index 00000000000..e90a53e79ba
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/ice-pr112889.c
@@ -0,0 +1,17 @@
+typedef unsigned char __u8;
+struct sk_buff
+{
+  unsigned char *data;
+};
+struct cpl_pass_accept_req
+{
+  __u8 : 6;
+  __u8 sack : 1;
+};
+void build_cpl_pass_accept_req(struct sk_buff* skb)
+{
+  struct cpl_pass_accept_req* req;
+  skb->data -= sizeof(*req);
+  req = (struct cpl_pass_accept_req *)skb->data;
+  req->sack = 1;
+}
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 11/21] analyzer: fix deref-before-check false positives due to inlining [PR112790]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (9 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 10/21] analyzer: fix ICE for 2 bits before the start of base region [PR112889] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 12/21] analyzer: casting all zeroes should give all zeroes [PR113333] David Malcolm
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Backported from commit r14-6918-g5743e1899d5964 (moving testcase from
c-c++-common to gcc.dg).

gcc/analyzer/ChangeLog:
	PR analyzer/112790
	* checker-event.cc (class inlining_info): Move to...
	* inlining-iterator.h (class inlining_info): ...here.
	* sm-malloc.cc: Include "analyzer/inlining-iterator.h".
	(maybe_complain_about_deref_before_check): Reject stmts that were
	inlined from another function.

gcc/testsuite/ChangeLog:
	PR analyzer/112790
	* gcc.dg/analyzer/deref-before-check-pr112790.c: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/checker-event.cc                 | 40 -------------------
 gcc/analyzer/inlining-iterator.h              | 40 +++++++++++++++++++
 gcc/analyzer/sm-malloc.cc                     | 10 +++++
 .../analyzer/deref-before-check-pr112790.c    | 27 +++++++++++++
 4 files changed, 77 insertions(+), 40 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr112790.c

diff --git a/gcc/analyzer/checker-event.cc b/gcc/analyzer/checker-event.cc
index 3612df7bd1d..3cb2fb9175c 100644
--- a/gcc/analyzer/checker-event.cc
+++ b/gcc/analyzer/checker-event.cc
@@ -106,46 +106,6 @@ event_kind_to_string (enum event_kind ek)
     }
 }
 
-/* A class for fixing up fndecls and stack depths in checker_event, based
-   on inlining records.
-
-   The early inliner runs before the analyzer, which can lead to confusing
-   output.
-
-   Tne base fndecl and depth within a checker_event are from call strings
-   in program_points, which reflect the call strings after inlining.
-   This class lets us offset the depth and fix up the reported fndecl and
-   stack depth to better reflect the user's original code.  */
-
-class inlining_info
-{
-public:
-  inlining_info (location_t loc)
-  {
-    inlining_iterator iter (loc);
-    m_inner_fndecl = iter.get_fndecl ();
-    int num_frames = 0;
-    while (!iter.done_p ())
-      {
-	m_outer_fndecl = iter.get_fndecl ();
-	num_frames++;
-	iter.next ();
-      }
-    if (num_frames > 1)
-      m_extra_frames = num_frames - 1;
-    else
-      m_extra_frames = 0;
-  }
-
-  tree get_inner_fndecl () const { return m_inner_fndecl; }
-  int get_extra_frames () const { return m_extra_frames; }
-
-private:
-  tree m_outer_fndecl;
-  tree m_inner_fndecl;
-  int m_extra_frames;
-};
-
 /* class checker_event : public diagnostic_event.  */
 
 /* checker_event's ctor.  */
diff --git a/gcc/analyzer/inlining-iterator.h b/gcc/analyzer/inlining-iterator.h
index 7d4798ce6ea..76ba1dc3cf4 100644
--- a/gcc/analyzer/inlining-iterator.h
+++ b/gcc/analyzer/inlining-iterator.h
@@ -106,4 +106,44 @@ private:
   tree m_next_abstract_origin;
 };
 
+/* A class for fixing up fndecls and stack depths in checker_event, based
+   on inlining records.
+
+   The early inliner runs before the analyzer, which can lead to confusing
+   output.
+
+   Tne base fndecl and depth within a checker_event are from call strings
+   in program_points, which reflect the call strings after inlining.
+   This class lets us offset the depth and fix up the reported fndecl and
+   stack depth to better reflect the user's original code.  */
+
+class inlining_info
+{
+public:
+  inlining_info (location_t loc)
+  {
+    inlining_iterator iter (loc);
+    m_inner_fndecl = iter.get_fndecl ();
+    int num_frames = 0;
+    while (!iter.done_p ())
+      {
+	m_outer_fndecl = iter.get_fndecl ();
+	num_frames++;
+	iter.next ();
+      }
+    if (num_frames > 1)
+      m_extra_frames = num_frames - 1;
+    else
+      m_extra_frames = 0;
+  }
+
+  tree get_inner_fndecl () const { return m_inner_fndecl; }
+  int get_extra_frames () const { return m_extra_frames; }
+
+private:
+  tree m_outer_fndecl;
+  tree m_inner_fndecl;
+  int m_extra_frames;
+};
+
 #endif /* GCC_ANALYZER_INLINING_ITERATOR_H */
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 74701375409..64295cfb66e 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "analyzer/program-state.h"
 #include "analyzer/checker-event.h"
 #include "analyzer/exploded-graph.h"
+#include "analyzer/inlining-iterator.h"
 
 #if ENABLE_ANALYZER
 
@@ -2147,6 +2148,15 @@ maybe_complain_about_deref_before_check (sm_context *sm_ctxt,
   if (checked_in_frame->get_index () > assumed_nonnull_in_frame->get_index ())
     return;
 
+  /* Don't complain if STMT was inlined from another function, to avoid
+     similar false positives involving shared helper functions.  */
+  if (stmt->location)
+    {
+      inlining_info info (stmt->location);
+      if (info.get_extra_frames () > 0)
+	return;
+    }
+
   tree diag_ptr = sm_ctxt->get_diagnostic_tree (ptr);
   if (diag_ptr)
     sm_ctxt->warn
diff --git a/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr112790.c b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr112790.c
new file mode 100644
index 00000000000..8f74468f849
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr112790.c
@@ -0,0 +1,27 @@
+/* Reproducer for false positive from -Wanalyzer-deref-before-check
+   seen on Linux kernel's block/bdev.c due to -fanalyzer mishandling
+   inlined functions.  */
+
+/* { dg-additional-options "-O2 -g -fno-delete-null-pointer-checks" } */
+
+typedef unsigned char u8;
+struct inode {
+  void *i_mapping;
+  u8 i_blkbits;
+};
+struct block_device {
+  struct inode *bd_inode;
+};
+int sync_blockdev(struct block_device *bdev);
+int set_blocksize(struct block_device *bdev, u8 size) {
+  if (bdev->bd_inode->i_blkbits != size) { /* { dg-bogus "pointer 'bdev' is dereferenced here" } */
+    sync_blockdev(bdev);
+  }
+  return 0;
+}
+extern int filemap_write_and_wait(void *);
+int sync_blockdev(struct block_device *bdev) {
+  if (!bdev) /* { dg-bogus "check of 'bdev' for NULL after already dereferencing it" } */
+    return 0;
+  return filemap_write_and_wait(bdev->bd_inode->i_mapping);
+}
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 12/21] analyzer: casting all zeroes should give all zeroes [PR113333]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (10 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 11/21] analyzer: fix deref-before-check false positives due to inlining [PR112790] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 13/21] analyzer: fix defaults in compound assignments from non-zero offsets [PR112969] David Malcolm
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

In particular, accessing the result of *calloc (1, SZ) (if non-NULL)
should be known to be all zeroes.

(backported from commit r14-7265-gd235bf2e807c5f)

gcc/analyzer/ChangeLog:
	PR analyzer/113333
	* region-model-manager.cc
	(region_model_manager::maybe_fold_unaryop): Casting all zeroes
	should give all zeroes.

gcc/testsuite/ChangeLog:
	PR analyzer/113333
	* gcc.dg/analyzer/calloc-1.c: Add tests.
	* gcc.dg/analyzer/data-model-9.c: Update expected results.
	* gcc.dg/analyzer/pr96639.c: Update expected results.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/region-model-manager.cc         |  6 ++++
 gcc/testsuite/gcc.dg/analyzer/calloc-1.c     | 34 ++++++++++++++++++++
 gcc/testsuite/gcc.dg/analyzer/data-model-9.c |  6 ++--
 gcc/testsuite/gcc.dg/analyzer/pr96639.c      |  2 +-
 4 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc
index 1a9886fd83c..51a2d8b029f 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -422,6 +422,12 @@ region_model_manager::maybe_fold_unaryop (tree type, enum tree_code op,
 	      && region_sval->get_type ()
 	      && POINTER_TYPE_P (region_sval->get_type ()))
 	    return get_ptr_svalue (type, region_sval->get_pointee ());
+
+	/* Casting all zeroes should give all zeroes.  */
+	if (type
+	    && arg->all_zeroes_p ()
+	    && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
+	  return get_or_create_int_cst (type, 0);
       }
       break;
     case TRUTH_NOT_EXPR:
diff --git a/gcc/testsuite/gcc.dg/analyzer/calloc-1.c b/gcc/testsuite/gcc.dg/analyzer/calloc-1.c
index bc28128671f..efb1a24c96a 100644
--- a/gcc/testsuite/gcc.dg/analyzer/calloc-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/calloc-1.c
@@ -25,3 +25,37 @@ char *test_1 (size_t sz)
 
   return p;
 }
+
+char **
+test_pr113333_1 (void)
+{
+  char **p = (char **)calloc (1, sizeof(char *));
+  if (p)
+    {
+      __analyzer_eval (*p == 0); /* { dg-warning "TRUE" } */
+      __analyzer_eval (p[0] == 0); /* { dg-warning "TRUE" } */
+    }
+  return p;
+}
+
+char **
+test_pr113333_2 (void)
+{
+  char **p = (char **)calloc (2, sizeof(char *));
+  if (p)
+    {
+      __analyzer_eval (*p == 0); /* { dg-warning "TRUE" } */
+      __analyzer_eval (p[0] == 0); /* { dg-warning "TRUE" } */
+      __analyzer_eval (p[1] == 0); /* { dg-warning "TRUE" } */
+    }
+  return p;
+}
+
+char **
+test_pr113333_3 (void)
+{
+  char **vec = (char **)calloc (1, sizeof(char *));
+  if (vec)
+    for (char **p=vec ; *p ; p++); /* { dg-bogus "heap-based buffer over-read" } */
+  return vec;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-9.c b/gcc/testsuite/gcc.dg/analyzer/data-model-9.c
index 159bc612576..2121f20c4f0 100644
--- a/gcc/testsuite/gcc.dg/analyzer/data-model-9.c
+++ b/gcc/testsuite/gcc.dg/analyzer/data-model-9.c
@@ -14,8 +14,7 @@ void test_1 (void)
   struct foo *f = calloc (1, sizeof (struct foo));
   if (f == NULL)
     return;
-  __analyzer_eval (f->i == 0); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */
-  /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */
+  __analyzer_eval (f->i == 0); /* { dg-warning "TRUE" } */
   free (f);
 }
 
@@ -27,7 +26,6 @@ void test_2 (void)
   if (f == NULL)
     return;
   memset (f, 0, sizeof (struct foo));
-  __analyzer_eval (f->i == 0); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */
-  /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */
+  __analyzer_eval (f->i == 0); /* { dg-warning "TRUE" } */
   free (f);
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96639.c b/gcc/testsuite/gcc.dg/analyzer/pr96639.c
index aedf0464dc9..c06a5c02f79 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr96639.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr96639.c
@@ -6,5 +6,5 @@ x7 (void)
   int **md = calloc (1, sizeof (void *));
 
   return md[0][0]; /* { dg-warning "possibly-NULL" "unchecked deref" } */
-  /* { dg-warning "leak of 'md'" "leak" { target *-*-* } .-1 } */
+  /* { dg-warning "Wanalyzer-null-dereference" "deref of NULL" { target *-*-* } .-1 } */
 }
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 13/21] analyzer: fix defaults in compound assignments from non-zero offsets [PR112969]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (11 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 12/21] analyzer: casting all zeroes should give all zeroes [PR113333] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 14/21] analyzer: fix skipping of debug stmts [PR113253] David Malcolm
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

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.

Backported from commit r14-8428-g6426d466779fa8 (keeping tests
in gcc.dg, rather than c-c++-common).

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
	* gcc.dg/analyzer/compound-assignment-5.c (test_3): Remove
	xfails, reorder tests.
	* gcc.dg/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                         | 11 +++-
 .../gcc.dg/analyzer/compound-assignment-5.c   | 29 ++++-------
 .../analyzer/compound-assignment-pr112969.c   | 35 +++++++++++++
 .../gcc.dg/plugin/infoleak-pr112969.c         | 52 +++++++++++++++++++
 gcc/testsuite/gcc.dg/plugin/plugin.exp        |  1 +
 5 files changed, 109 insertions(+), 19 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/compound-assignment-pr112969.c
 create mode 100644 gcc/testsuite/gcc.dg/plugin/infoleak-pr112969.c

diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index e8c927b9fe9..0acb0a2b186 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -1718,7 +1718,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)
     {
diff --git a/gcc/testsuite/gcc.dg/analyzer/compound-assignment-5.c b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-5.c
index ccf8fe392bf..e1f42177b08 100644
--- a/gcc/testsuite/gcc.dg/analyzer/compound-assignment-5.c
+++ b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-5.c
@@ -23,7 +23,7 @@ void test_1 (void)
 
 /* Copying from an on-stack array to a global array.  */
 
-struct coord glob_arr[16];
+struct coord glob_arr2[16];
 
 void test_2 (void)
 {
@@ -31,32 +31,29 @@ void test_2 (void)
   arr[3].x = 5;
   arr[3].y = 6;
 
-  glob_arr[7] = arr[3];
+  glob_arr2[7] = arr[3];
 
-  __analyzer_eval (glob_arr[7].x == 5); /* { dg-warning "TRUE" } */
-  __analyzer_eval (glob_arr[7].y == 6); /* { dg-warning "TRUE" } */
+  __analyzer_eval (glob_arr2[7].x == 5); /* { dg-warning "TRUE" } */
+  __analyzer_eval (glob_arr2[7].y == 6); /* { dg-warning "TRUE" } */
 }
 
 /* Copying from a partially initialized on-stack array to a global array.  */
 
-struct coord glob_arr[16];
+struct coord glob_arr3[16];
 
 void test_3 (void)
 {
   struct coord arr[16];
   arr[3].y = 6;
 
-  glob_arr[7] = arr[3]; // or should the uninit warning be here?
+  glob_arr3[7] = arr[3]; // or should the uninit warning be here?
 
-  __analyzer_eval (glob_arr[7].x); /* { dg-warning "uninitialized" "uninit" { xfail *-*-* } } */
-  /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */
-  __analyzer_eval (glob_arr[7].y == 6); /* { dg-warning "TRUE" } */
+  __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.  */
 
-struct coord glob_arr[16];
-
 void test_4 (int i)
 {
   struct coord arr_a[16];
@@ -77,8 +74,6 @@ void test_4 (int i)
 
 /* Symbolic bindings: copying within an array: symbolic src and dest  */
 
-struct coord glob_arr[16];
-
 void test_5a (int i, int j)
 {
   struct coord arr[16];
@@ -95,8 +90,6 @@ void test_5a (int i, int j)
 
 /* Symbolic bindings: copying within an array: symbolic src, concrete dest.  */
 
-struct coord glob_arr[16];
-
 void test_5b (int i)
 {
   struct coord arr[16];
@@ -113,8 +106,6 @@ void test_5b (int i)
 
 /* Symbolic bindings: copying within an array: concrete src, symbolic dest.  */
 
-struct coord glob_arr[16];
-
 void test_5c (int i)
 {
   struct coord arr[16];
@@ -132,10 +123,12 @@ void test_5c (int i)
 /* No info on the subregion being copied, and hence
    binding_cluster2::maybe_get_compound_binding should return NULL.  */
 
+struct coord glob_arr6[16];
+
 void test_6 (void)
 {
   struct coord arr[16];
-  arr[7] = glob_arr[3];
+  arr[7] = glob_arr6[3];
 
   __analyzer_eval (arr[7].x == 5); /* { dg-warning "UNKNOWN" } */
   __analyzer_eval (arr[7].y == 6); /* { dg-warning "UNKNOWN" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/compound-assignment-pr112969.c b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-pr112969.c
new file mode 100644
index 00000000000..4bc037cb7cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-pr112969.c
@@ -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
index 00000000000..e78fe365975
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/infoleak-pr112969.c
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index 4d6304cd100..6465b3c34bf 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -141,6 +141,7 @@ set plugin_test_list [list \
 	  infoleak-CVE-2017-18550-1.c \
 	  infoleak-antipatterns-1.c \
 	  infoleak-fixit-1.c \
+	  infoleak-pr112969.c \
 	  infoleak-net-ethtool-ioctl.c \
 	  infoleak-vfio_iommu_type1.c \
 	  taint-CVE-2011-0521-1-fixed.c \
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 14/21] analyzer: fix skipping of debug stmts [PR113253]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (12 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 13/21] analyzer: fix defaults in compound assignments from non-zero offsets [PR112969] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 15/21] analyzer: fix -Wanalyzer-va-arg-type-mismatch false +ve on int types [PR111289] David Malcolm
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

PR analyzer/113253 reports a case where the analyzer output varied
with and without -g enabled.

The root cause was that debug stmts were in the
FOR_EACH_IMM_USE_FAST list for SSA names, leading to the analyzer's
state purging logic differing between the -g and non-debugging cases,
and thus leading to differences in the exploration of the user's code.

Fix by skipping such stmts in the state-purging logic, and removing
debug stmts when constructing the supergraph.

gcc/analyzer/ChangeLog:
	PR analyzer/113253
	* region-model.cc (region_model::on_stmt_pre): Add gcc_unreachable
	for debug statements.
	* state-purge.cc
	(state_purge_per_ssa_name::state_purge_per_ssa_name): Skip any
	debug stmts in the FOR_EACH_IMM_USE_FAST list.
	* supergraph.cc (supergraph::supergraph): Don't add debug stmts
	to the supernodes.

gcc/testsuite/ChangeLog:
	PR analyzer/113253
	* gcc.dg/analyzer/deref-before-check-pr113253.c: New test.

(cherry picked from commit r14-8670-gcc7aebff74d896)

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/region-model.cc                  |   5 +
 gcc/analyzer/state-purge.cc                   |   9 +
 gcc/analyzer/supergraph.cc                    |   4 +
 .../analyzer/deref-before-check-pr113253.c    | 154 ++++++++++++++++++
 4 files changed, 172 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr113253.c

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index c98b09d5322..7e42fcdfd55 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -1237,6 +1237,11 @@ region_model::on_stmt_pre (const gimple *stmt,
       /* No-op for now.  */
       break;
 
+    case GIMPLE_DEBUG:
+      /* We should have stripped these out when building the supergraph.  */
+      gcc_unreachable ();
+      break;
+
     case GIMPLE_ASSIGN:
       {
 	const gassign *assign = as_a <const gassign *> (stmt);
diff --git a/gcc/analyzer/state-purge.cc b/gcc/analyzer/state-purge.cc
index 3a73146d928..31a207436f0 100644
--- a/gcc/analyzer/state-purge.cc
+++ b/gcc/analyzer/state-purge.cc
@@ -329,6 +329,15 @@ state_purge_per_ssa_name::state_purge_per_ssa_name (const state_purge_map &map,
 	      map.log ("used by stmt: %s", pp_formatted_text (&pp));
 	    }
 
+	  if (is_gimple_debug (use_stmt))
+	    {
+	      /* We skipped debug stmts when building the supergraph,
+		 so ignore them now.  */
+	      if (map.get_logger ())
+		map.log ("skipping debug stmt");
+	      continue;
+	    }
+
 	  const supernode *snode
 	    = map.get_sg ().get_supernode_for_stmt (use_stmt);
 
diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc
index a23ff15ece4..f07d68c60b8 100644
--- a/gcc/analyzer/supergraph.cc
+++ b/gcc/analyzer/supergraph.cc
@@ -182,6 +182,10 @@ supergraph::supergraph (logger *logger)
 	  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
 	    {
 	      gimple *stmt = gsi_stmt (gsi);
+	      /* Discard debug stmts here, so we don't have to check for
+		 them anywhere within the analyzer.  */
+	      if (is_gimple_debug (stmt))
+		continue;
 	      node_for_stmts->m_stmts.safe_push (stmt);
 	      m_stmt_to_node_t.put (stmt, node_for_stmts);
 	      m_stmt_uids.make_uid_unique (stmt);
diff --git a/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr113253.c b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr113253.c
new file mode 100644
index 00000000000..d9015accd6a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr113253.c
@@ -0,0 +1,154 @@
+/* Regression test for PR analyzer/113253 which was showing analyzer
+   differences with and without -g.
+
+   C only: reduced reproducer doesn't easily work with C++.  */
+
+/* { dg-additional-options "-O2 -g" } */
+
+typedef long int ptrdiff_t;
+typedef unsigned long int uintptr_t;
+typedef long int EMACS_INT;
+enum
+{
+  EMACS_INT_WIDTH = 64,
+  VALBITS = EMACS_INT_WIDTH - 3,
+};
+typedef struct Lisp_X* Lisp_Word;
+enum Lisp_Type
+{
+  Lisp_Symbol = 0,
+  Lisp_Vectorlike = 5,
+};
+typedef Lisp_Word Lisp_Object;
+static inline EMACS_INT(XLI)(Lisp_Object o)
+{
+  return ((EMACS_INT)(o));
+}
+static inline void*(XLP)(Lisp_Object o)
+{
+  return ((void*)(o));
+}
+struct Lisp_Symbol
+{};
+typedef uintptr_t Lisp_Word_tag;
+extern struct Lisp_Symbol lispsym[1608];
+union vectorlike_header
+{
+  ptrdiff_t size;
+};
+enum pvec_type
+{
+  PVEC_MARKER,
+};
+enum More_Lisp_Bits
+{
+  PSEUDOVECTOR_SIZE_BITS = 12,
+  PSEUDOVECTOR_REST_BITS = 12,
+  PSEUDOVECTOR_AREA_BITS = PSEUDOVECTOR_SIZE_BITS + PSEUDOVECTOR_REST_BITS,
+  PVEC_TYPE_MASK = 0x3f << PSEUDOVECTOR_AREA_BITS
+};
+static inline _Bool
+PSEUDOVECTORP(Lisp_Object a, int code)
+{
+  return (
+    ((((union vectorlike_header*)((uintptr_t)XLP((a)) -
+                                  (uintptr_t)(
+                                    (Lisp_Word_tag)(Lisp_Vectorlike)
+                                    << (((0x7fffffffffffffffL >> (3 - 1)) / 2 <
+                                         (9223372036854775807L))
+                                          ? 0
+                                          : VALBITS))))
+        ->size &
+      (((9223372036854775807L) - (9223372036854775807L) / 2) |
+       PVEC_TYPE_MASK)) ==
+     (((9223372036854775807L) - (9223372036854775807L) / 2) |
+      ((code) << PSEUDOVECTOR_AREA_BITS))));
+}
+static inline Lisp_Object
+make_lisp_symbol(struct Lisp_Symbol* sym)
+{
+  Lisp_Object a = ((Lisp_Word)(
+    ((Lisp_Word_tag)(Lisp_Symbol)
+     << (((0x7fffffffffffffffL >> (3 - 1)) / 2 < (9223372036854775807L))
+           ? 0
+           : VALBITS))));
+  return a;
+}
+static inline Lisp_Object
+builtin_lisp_symbol(int index)
+{
+  return make_lisp_symbol(&lispsym[index]);
+}
+static inline _Bool(BASE_EQ)(Lisp_Object x, Lisp_Object y)
+{
+  return (XLI(x) == XLI(y));
+}
+static inline _Bool(NILP)(Lisp_Object x)
+{
+  return BASE_EQ(x, builtin_lisp_symbol(0));
+}
+struct thread_state
+{
+  struct buffer* m_current_buffer;
+};
+extern struct thread_state* current_thread;
+struct Lisp_Marker
+{
+  struct buffer* buffer;
+};
+static inline _Bool
+MARKERP(Lisp_Object x)
+{
+  return PSEUDOVECTORP(x, PVEC_MARKER);
+}
+static inline struct Lisp_Marker*
+XMARKER(Lisp_Object a)
+{
+  return ((
+    struct Lisp_Marker*)((uintptr_t)XLP(a) -
+                         (uintptr_t)((Lisp_Word_tag)(Lisp_Vectorlike)
+                                     << (((0x7fffffffffffffffL >> (3 - 1)) / 2 <
+                                          (9223372036854775807L))
+                                           ? 0
+                                           : VALBITS))));
+}
+extern void
+unchain_marker();
+struct buffer
+{
+  Lisp_Object name_;
+};
+static inline struct buffer*
+XBUFFER(Lisp_Object a)
+{
+  return (
+    (struct buffer*)((uintptr_t)XLP(a) -
+                     (uintptr_t)((Lisp_Word_tag)(Lisp_Vectorlike)
+                                 << (((0x7fffffffffffffffL >> (3 - 1)) / 2 <
+                                      (9223372036854775807L))
+                                       ? 0
+                                       : VALBITS))));
+}
+static inline _Bool
+BUFFER_LIVE_P(struct buffer* b)
+{
+  return !NILP(((b)->name_));
+}
+static inline struct buffer*
+decode_buffer(Lisp_Object b)
+{
+  return NILP(b) ? (current_thread->m_current_buffer) : (XBUFFER(b));
+}
+static struct buffer*
+live_buffer(Lisp_Object buffer)
+{
+  struct buffer* b = decode_buffer(buffer);
+  return BUFFER_LIVE_P(b) ? b : ((void*)0);
+}
+Lisp_Object
+set_marker_internal(Lisp_Object position, Lisp_Object buffer)
+{
+  struct buffer* b = live_buffer(buffer);
+  if (NILP(position) || (MARKERP(position) && !XMARKER(position)->buffer) || !b) /* { dg-bogus "Wanalyzer-deref-before-check" } */
+    unchain_marker();
+}
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 15/21] analyzer: fix -Wanalyzer-va-arg-type-mismatch false +ve on int types [PR111289]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (13 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 14/21] analyzer: fix skipping of debug stmts [PR113253] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 16/21] analyzer: fix -Wanalyzer-deref-before-check false positive seen in loop header macro [PR109251] David Malcolm
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Backported from commit r14-9076-g5651ad62b08096 (moving new tests from
c-c++-common to gcc.dg).

gcc/analyzer/ChangeLog:
	PR analyzer/111289
	* varargs.cc (representable_in_integral_type_p): New.
	(va_arg_compatible_types_p): Add "arg_sval" param.  Handle integer
	types.
	(kf_va_arg::impl_call_pre): Pass arg_sval to
	va_arg_compatible_types_p.

gcc/testsuite/ChangeLog:
	PR analyzer/111289
	* gcc.dg/analyzer/stdarg-pr111289-int.c: New test.
	* gcc.dg/analyzer/stdarg-pr111289-ptr.c: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/varargs.cc                       | 38 ++++++++--
 .../gcc.dg/analyzer/stdarg-pr111289-int.c     | 69 +++++++++++++++++++
 .../gcc.dg/analyzer/stdarg-pr111289-ptr.c     | 39 +++++++++++
 3 files changed, 142 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-int.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-ptr.c

diff --git a/gcc/analyzer/varargs.cc b/gcc/analyzer/varargs.cc
index aeea73a3899..6e13271969a 100644
--- a/gcc/analyzer/varargs.cc
+++ b/gcc/analyzer/varargs.cc
@@ -961,13 +961,43 @@ public:
   }
 };
 
-/* Return true if it's OK to copy a value from ARG_TYPE to LHS_TYPE via
+static bool
+representable_in_integral_type_p (const svalue &sval, const_tree type)
+{
+  gcc_assert (INTEGRAL_TYPE_P (type));
+
+  if (tree cst = sval.maybe_get_constant ())
+    return wi::fits_to_tree_p (wi::to_wide (cst), type);
+
+  return true;
+}
+
+/* Return true if it's OK to copy ARG_SVAL from ARG_TYPE to LHS_TYPE via
    va_arg (where argument promotion has already happened).  */
 
 static bool
-va_arg_compatible_types_p (tree lhs_type, tree arg_type)
+va_arg_compatible_types_p (tree lhs_type, tree arg_type, const svalue &arg_sval)
 {
-  return compat_types_p (arg_type, lhs_type);
+  if (compat_types_p (arg_type, lhs_type))
+    return true;
+
+  /* It's OK if both types are integer types, where one is signed and the
+     other type the corresponding unsigned type, when the value is
+     representable in both types.  */
+  if (INTEGRAL_TYPE_P (lhs_type)
+      && INTEGRAL_TYPE_P (arg_type)
+      && TYPE_UNSIGNED (lhs_type) != TYPE_UNSIGNED (arg_type)
+      && TYPE_PRECISION (lhs_type) == TYPE_PRECISION (arg_type)
+      && representable_in_integral_type_p (arg_sval, lhs_type)
+      && representable_in_integral_type_p (arg_sval, arg_type))
+    return true;
+
+  /* It's OK if one type is a pointer to void and the other is a
+     pointer to a character type.
+     This is handled by compat_types_p.  */
+
+  /* Otherwise the types are not compatible.  */
+  return false;
 }
 
 /* If AP_SVAL is a pointer to a var_arg_region, return that var_arg_region.
@@ -1031,7 +1061,7 @@ kf_va_arg::impl_call_pre (const call_details &cd) const
 		{
 		  tree lhs_type = cd.get_lhs_type ();
 		  tree arg_type = arg_sval->get_type ();
-		  if (va_arg_compatible_types_p (lhs_type, arg_type))
+		  if (va_arg_compatible_types_p (lhs_type, arg_type, *arg_sval))
 		    cd.maybe_set_lhs (arg_sval);
 		  else
 		    {
diff --git a/gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-int.c b/gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-int.c
new file mode 100644
index 00000000000..33d83169c3e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-int.c
@@ -0,0 +1,69 @@
+#include <stdarg.h>
+#include <stdint.h>
+#include <limits.h>
+
+typedef unsigned int mode_t;
+
+extern void openat (int, const char *, int, mode_t);
+
+/* Signed vs unsigned of same integral type.  */
+
+static void
+test_1 (char const *name, ...)
+{
+  va_list arg;
+  va_start (arg, name);
+
+  mode_t mode = va_arg (arg, mode_t); /* { dg-bogus "-Wanalyzer-va-arg-type-mismatch" } */
+
+  va_end (arg);
+  openat (-42, name, 0, mode);
+}
+
+void
+call_test_1 ()
+{
+  test_1 ("nonexist.ent/", 0600);
+}
+
+/* Not the same size: small enough for int promotion.  */
+
+int16_t global_2;
+
+static void
+test_2 (char const *name, ...)
+{
+  va_list arg;
+  va_start (arg, name);
+
+  global_2 = va_arg (arg, int16_t); /* { dg-warning "promoted to 'int'" } */
+
+  va_end (arg);
+}
+
+void
+call_test_2 ()
+{
+  test_2 ("nonexist.ent/", 42);
+}
+
+/* Not the same size: too big for int promotion.  */
+
+long long global_3;
+
+static void
+test_3 (char const *name, ...)
+{
+  va_list arg;
+  va_start (arg, name);
+
+  global_3 = va_arg (arg, long long); /* { dg-warning "'va_arg' expected 'long long int' but received 'int' for variadic argument 1 of 'arg'" } */
+
+  va_end (arg);
+}
+
+void
+call_test_3 ()
+{
+  test_3 ("nonexist.ent/", 42);
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-ptr.c b/gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-ptr.c
new file mode 100644
index 00000000000..7bdbf256d59
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/stdarg-pr111289-ptr.c
@@ -0,0 +1,39 @@
+#include <stdarg.h>
+
+static void *
+test_1 (const char *fmt, ...)
+{
+  va_list arg;
+  va_start (arg, fmt);
+
+  void *p = va_arg (arg, void *); /* { dg-bogus "-Wanalyzer-va-arg-type-mismatch" } */
+
+  va_end (arg);
+
+  return p;
+}
+
+void *
+call_test_1 ()
+{
+  return test_1 ("fmt", "foo");
+}
+
+static char *
+test_2 (const char *fmt, ...)
+{
+  va_list arg;
+  va_start (arg, fmt);
+
+  char *p = va_arg (arg, char *); /* { dg-bogus "-Wanalyzer-va-arg-type-mismatch" } */
+
+  va_end (arg);
+
+  return p;
+}
+
+char *
+call_test_2 (void *q)
+{
+  return test_2 ("fmt", q);
+}
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 16/21] analyzer: fix -Wanalyzer-deref-before-check false positive seen in loop header macro [PR109251]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (14 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 15/21] analyzer: fix -Wanalyzer-va-arg-type-mismatch false +ve on int types [PR111289] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 17/21] analyzer: fix ICE due to type mismatch when replaying call summary [PR114473] David Malcolm
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Backported from commit r14-9586-g9093f275e0a343 (moving tests from
c-c++-common to gcc.dg)

gcc/analyzer/ChangeLog:
	PR analyzer/109251
	* sm-malloc.cc (deref_before_check::emit): Reject cases where the
	check is in a loop header within a macro expansion.
	(deref_before_check::loop_header_p): New.

gcc/testsuite/ChangeLog:
	PR analyzer/109251
	* gcc.dg/analyzer/deref-before-check-pr109251-1.c: New test.
	* gcc.dg/analyzer/deref-before-check-pr109251-2.c: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/sm-malloc.cc                     | 30 ++++++++++
 .../analyzer/deref-before-check-pr109251-1.c  | 60 +++++++++++++++++++
 .../analyzer/deref-before-check-pr109251-2.c  | 37 ++++++++++++
 3 files changed, 127 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-1.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-2.c

diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 64295cfb66e..e9384a14dea 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -1565,6 +1565,21 @@ public:
     if (linemap_location_from_macro_definition_p (line_table, check_loc))
       return false;
 
+    /* Reject warning if the check is in a loop header within a
+       macro expansion.  This rejects cases like:
+       |  deref of x;
+       |  [...snip...]
+       |  FOR_EACH(x) {
+       |    [...snip...]
+       |  }
+       where the FOR_EACH macro tests for non-nullness of x, since
+       the user is hoping to encapsulate the details of iteration
+       in the macro, and the extra check on the first iteration
+       would just be noise if we reported it.  */
+    if (loop_header_p (m_check_enode->get_point ())
+	&& linemap_location_from_macro_expansion_p (line_table, check_loc))
+      return false;
+
     /* Reject if m_deref_expr is sufficiently different from m_arg
        for cases where the dereference is spelled differently from
        the check, which is probably two different ways to get the
@@ -1621,6 +1636,21 @@ public:
   }
 
 private:
+  static bool loop_header_p (const program_point &point)
+  {
+    const supernode *snode = point.get_supernode ();
+    if (!snode)
+      return false;
+    for (auto &in_edge : snode->m_preds)
+      {
+	if (const cfg_superedge *cfg_in_edge
+	      = in_edge->dyn_cast_cfg_superedge ())
+	  if (cfg_in_edge->back_edge_p ())
+	    return true;
+      }
+    return false;
+  }
+
   static bool sufficiently_similar_p (tree expr_a, tree expr_b)
   {
     pretty_printer *pp_a = global_dc->printer->clone ();
diff --git a/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-1.c b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-1.c
new file mode 100644
index 00000000000..769cffae6d7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-1.c
@@ -0,0 +1,60 @@
+/* Reduced from linux-5.10.162's kernel/sched/fair.c,
+   with !CONFIG_FAIR_GROUP_SCHED.  */
+
+#define NULL ((void*)0)
+
+struct load_weight
+{
+  unsigned long weight;
+  /* [...snip...] */
+};
+
+struct sched_entity
+{
+  struct load_weight load;
+  /* [...snip...] */
+  unsigned int on_rq;
+  /* [...snip...] */
+};
+
+struct cfs_rq
+{
+  /* [...snip...] */
+  unsigned int nr_running;
+  /* [...snip...] */
+};
+
+extern int
+__calc_delta(int delta_exec, unsigned long weight /* [...snip...] */);
+
+/* !CONFIG_FAIR_GROUP_SCHED */
+#define for_each_sched_entity(se) \
+  for (; se; se = (struct sched_entity *)NULL)
+
+extern struct cfs_rq*
+cfs_rq_of(struct sched_entity* se);
+
+extern int
+__sched_period(unsigned long nr_running);
+
+int
+sched_slice(struct cfs_rq* cfs_rq, struct sched_entity* se)
+{
+  unsigned int nr_running = cfs_rq->nr_running;
+  int slice;
+
+  /* [...snip...] */
+
+  slice = __sched_period(nr_running + !se->on_rq);
+
+  for_each_sched_entity(se) {
+    /* [...snip...] */
+    cfs_rq = cfs_rq_of(se);
+    /* [...snip...] */
+    slice = __calc_delta(slice, se->load.weight);
+  }
+
+  /* [...snip...] */
+
+  return slice;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-2.c b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-2.c
new file mode 100644
index 00000000000..8e85a47d315
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr109251-2.c
@@ -0,0 +1,37 @@
+struct node
+{
+  struct node *next;
+  int val;
+};
+
+int test_loop_1 (struct node *n)
+{
+  int total = 0;
+  if (n->val = 42)
+    return -1;
+  for (struct node *iter = n; iter; iter=iter->next)
+    total += iter->val;
+  return total;
+}
+
+int test_loop_2 (struct node *n)
+{
+  int total = 0;
+  if (n->val = 42)
+    return -1;
+  for (; n; n=n->next)
+    total += n->val;
+  return total;
+}
+
+#define FOR_EACH_NODE(ITER) for (; (ITER); (ITER)=(ITER)->next)
+
+int test_loop_3 (struct node *n)
+{
+  int total = 0;
+  if (n->val = 42)
+    return -1;
+  FOR_EACH_NODE (n)
+    total += n->val;
+  return total;
+}
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 17/21] analyzer: fix ICE due to type mismatch when replaying call summary [PR114473]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (15 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 16/21] analyzer: fix -Wanalyzer-deref-before-check false positive seen in loop header macro [PR109251] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 18/21] analyzer: fix ICE and false positive with -Wanalyzer-deref-before-check [PR114408] David Malcolm
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

gcc/analyzer/ChangeLog:
	PR analyzer/114473
	* call-summary.cc
	(call_summary_replay::convert_svalue_from_summary): Assert that
	the types match.
	(call_summary_replay::convert_region_from_summary): Likewise.
	(call_summary_replay::convert_region_from_summary_1): Add missing
	cast for the deref of RK_SYMBOLIC case.

gcc/testsuite/ChangeLog:
	PR analyzer/114473
	* gcc.dg/analyzer/call-summaries-pr114473.c: New test.

(cherry picked from commit r14-9697-gfdd59818e2abf6)

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/call-summary.cc                  | 12 +++++++
 .../gcc.dg/analyzer/call-summaries-pr114473.c | 31 +++++++++++++++++++
 2 files changed, 43 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c

diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc
index a18a1b1b40a..836dcd4318d 100644
--- a/gcc/analyzer/call-summary.cc
+++ b/gcc/analyzer/call-summary.cc
@@ -234,6 +234,11 @@ call_summary_replay::convert_svalue_from_summary (const svalue *summary_sval)
 
   const svalue *caller_sval = convert_svalue_from_summary_1 (summary_sval);
 
+  if (caller_sval)
+    if (summary_sval->get_type () && caller_sval->get_type ())
+      gcc_assert (types_compatible_p (summary_sval->get_type (),
+				      caller_sval->get_type ()));
+
   /* Add to cache.  */
   add_svalue_mapping (summary_sval, caller_sval);
 
@@ -551,6 +556,11 @@ call_summary_replay::convert_region_from_summary (const region *summary_reg)
 
   const region *caller_reg = convert_region_from_summary_1 (summary_reg);
 
+  if (caller_reg)
+    if (summary_reg->get_type () && caller_reg->get_type ())
+      gcc_assert (types_compatible_p (summary_reg->get_type (),
+				      caller_reg->get_type ()));
+
   /* Add to cache.  */
   add_region_mapping (summary_reg, caller_reg);
 
@@ -601,6 +611,8 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
 	  = get_caller_model ()->deref_rvalue (caller_ptr_sval,
 					       NULL_TREE,
 					       get_ctxt ());
+	caller_reg = mgr->get_cast_region (caller_reg,
+					   summary_reg->get_type ());
 	return caller_reg;
       }
       break;
diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c
new file mode 100644
index 00000000000..4598840f0df
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr114473.c
@@ -0,0 +1,31 @@
+/* { dg-additional-options "-fanalyzer-call-summaries" } */
+
+int a;
+extern int *q[];
+
+int *
+baz (int *src)
+{
+  while (a)
+    {
+      src && a;
+      return src;
+    }
+}
+
+void
+bar (int **src)
+{
+  for (unsigned j = 0; j;)
+    a = 0;
+  while (a)
+    baz (src[0]);
+}
+
+void
+foo (void)
+{
+  bar (q);
+  baz (&a);
+  bar (q);
+}
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 18/21] analyzer: fix ICE and false positive with -Wanalyzer-deref-before-check [PR114408]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (16 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 17/21] analyzer: fix ICE due to type mismatch when replaying call summary [PR114473] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 19/21] diagnostics: fix ICE on sarif output when source file is unreadable [PR111700] David Malcolm
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Backported from commit r14-9646-g80a0cb37456c49 (moving testcase to gcc.dg
and handling conflict in kf.cc)

gcc/analyzer/ChangeLog:
	PR analyzer/114408
	* engine.cc (impl_run_checkers): Free up any dominance info that
	we may have created.
	* kf.cc (class kf_ubsan_handler): New.
	(register_sanitizer_builtins): New.
	(register_known_functions): Call register_sanitizer_builtins.

gcc/testsuite/ChangeLog:
	PR analyzer/114408
	* gcc.dg/analyzer/deref-before-check-pr114408.c: New test.
	* c-c++-common/ubsan/analyzer-ice-pr114408.c: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/engine.cc                        |  7 ++++++
 gcc/analyzer/kf.cc                            | 22 +++++++++++++++++++
 .../ubsan/analyzer-ice-pr114408.c             |  9 ++++++++
 .../analyzer/deref-before-check-pr114408.c    | 22 +++++++++++++++++++
 4 files changed, 60 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr114408.c

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index a5965c2b8ff..c5aadc41d11 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -6163,6 +6163,13 @@ impl_run_checkers (logger *logger)
     eng.get_model_manager ()->dump_untracked_regions ();
 
   delete purge_map;
+
+  /* Free up any dominance info that we may have created.  */
+  FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
+    {
+      function *fun = node->get_fun ();
+      free_dominance_info (fun, CDI_DOMINATORS);
+    }
 }
 
 /* Handle -fdump-analyzer and -fdump-analyzer-stderr.  */
diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc
index 93c46630f36..4389ff917b8 100644
--- a/gcc/analyzer/kf.cc
+++ b/gcc/analyzer/kf.cc
@@ -987,6 +987,27 @@ region_model::impl_deallocation_call (const call_details &cd)
   kf.impl_call_post (cd);
 }
 
+/* Handle calls to the various __builtin___ubsan_handle_*.
+   These can return, but continuing after such a return
+   isn't likely to be interesting to the user of the analyzer.
+   Hence we terminate the analysis path at one of these calls.  */
+
+class kf_ubsan_handler : public internal_known_function
+{
+  void impl_call_post (const call_details &cd) const final override
+  {
+    if (cd.get_ctxt ())
+      cd.get_ctxt ()->terminate_path ();
+  }
+};
+
+static void
+register_sanitizer_builtins (known_function_manager &kfm)
+{
+  kfm.add (BUILT_IN_UBSAN_HANDLE_NONNULL_ARG,
+	   make_unique<kf_ubsan_handler> ());
+}
+
 /* Populate KFM with instances of known functions supported by the core of the
    analyzer (as opposed to plugins).  */
 
@@ -1028,6 +1049,7 @@ register_known_functions (known_function_manager &kfm)
     kfm.add (BUILT_IN_STRNDUP, make_unique<kf_strndup> ());
     kfm.add (BUILT_IN_STRLEN, make_unique<kf_strlen> ());
 
+    register_sanitizer_builtins (kfm);
     register_varargs_builtins (kfm);
   }
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c b/gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c
new file mode 100644
index 00000000000..55f918726ee
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/analyzer-ice-pr114408.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-require-effective-target analyzer } */
+/* { dg-options "-fanalyzer -fsanitize=undefined" } */
+
+int main(){}
+
+int HMAP_unset_copy(const char *key) {
+    return __builtin_strcmp("a", key) + __builtin_strcmp("a", key);
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr114408.c b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr114408.c
new file mode 100644
index 00000000000..d55720271d0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/deref-before-check-pr114408.c
@@ -0,0 +1,22 @@
+extern void unknown_returns (const char *p);
+extern void unknown_noreturn (const char *p) __attribute__((__noreturn__));
+
+void test_1 (const char *p)
+{
+  if (p)
+    unknown_returns (p);
+  __builtin_strcmp ("a", p); /* { dg-message "pointer 'p' is dereferenced here" "" { target c } } */
+  if (p) /* { dg-warning "check of 'p' for NULL after already dereferencing it" "" { target c } } */
+    unknown_returns (p);
+  __builtin_strcmp ("a", p);  
+}
+
+void test_2 (const char *p)
+{
+  if (p)
+    unknown_noreturn (p);
+  __builtin_strcmp ("a", p);
+  if (p) /* { dg-bogus "check of 'p' for NULL after already dereferencing it" } */
+    unknown_noreturn (p);
+  __builtin_strcmp ("a", p);  
+}
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 19/21] diagnostics: fix ICE on sarif output when source file is unreadable [PR111700]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (17 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 18/21] analyzer: fix ICE and false positive with -Wanalyzer-deref-before-check [PR114408] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 20/21] Fix ICE in -fdiagnostics-generate-patch [PR112684] David Malcolm
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Backported from r14-4474-g94caa6a6b4bd73.

gcc/ChangeLog:
	PR driver/111700
	* input.cc (file_cache::add_file): Update leading comment to
	clarify that it can fail.
	(file_cache::lookup_or_add_file): Likewise.
	(get_source_file_content): Gracefully handle lookup_or_add_file
	failing.

gcc/testsuite/ChangeLog:
	PR driver/111700
	* c-c++-common/diagnostic-format-sarif-file-pr111700.c: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/input.cc                                         | 12 ++++++++++--
 .../diagnostic-format-sarif-file-pr111700.c          | 12 ++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-pr111700.c

diff --git a/gcc/input.cc b/gcc/input.cc
index eaf301ec7c1..d1668ef5dcd 100644
--- a/gcc/input.cc
+++ b/gcc/input.cc
@@ -443,7 +443,10 @@ file_cache::evicted_cache_tab_entry (unsigned *highest_use_count)
    accessed by caret diagnostic.  This cache is added to an array of
    cache and can be retrieved by lookup_file_in_cache_tab.  This
    function returns the created cache.  Note that only the last
-   num_file_slots files are cached.  */
+   num_file_slots files are cached.
+
+   This can return nullptr if the FILE_PATH can't be opened for
+   reading, or if the content can't be converted to the input_charset.  */
 
 file_cache_slot*
 file_cache::add_file (const char *file_path)
@@ -547,7 +550,10 @@ file_cache::~file_cache ()
 /* Lookup the cache used for the content of a given file accessed by
    caret diagnostic.  If no cached file was found, create a new cache
    for this file, add it to the array of cached file and return
-   it.  */
+   it.
+
+   This can return nullptr on a cache miss if FILE_PATH can't be opened for
+   reading, or if the content can't be converted to the input_charset.  */
 
 file_cache_slot*
 file_cache::lookup_or_add_file (const char *file_path)
@@ -1071,6 +1077,8 @@ get_source_file_content (const char *file_path)
   diagnostic_file_cache_init ();
 
   file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path);
+  if (c == nullptr)
+    return char_span (nullptr, 0);
   return c->get_full_file_content ();
 }
 
diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-pr111700.c b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-pr111700.c
new file mode 100644
index 00000000000..06605accf6e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-pr111700.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fdiagnostics-format=sarif-file" } */
+
+# 0 "this-file-does-not-exist.c"
+#warning message
+
+/* Verify that some JSON was written to a file with the expected name.  */
+/* { dg-final { verify-sarif-file } } */
+
+/* ...and that it at least includes the warning
+       { dg-final { scan-sarif-file "\"message\": " } }
+         { dg-final { scan-sarif-file "\"text\": \"#warning message" } } */
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 20/21] Fix ICE in -fdiagnostics-generate-patch [PR112684]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (18 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 19/21] diagnostics: fix ICE on sarif output when source file is unreadable [PR111700] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-09 17:42 ` [PATCH 21/21] diagnostics: fix corrupt json/SARIF on stderr [PR114348] David Malcolm
  2024-05-13  9:03 ` [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) Jakub Jelinek
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Backported from r14-8255-ge254d1224df306.

gcc/ChangeLog:
	PR middle-end/112684
	* toplev.cc (toplev::main): Don't ICE in
	-fdiagnostics-generate-patch when exiting after options,
	since no edit context will have been created.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/toplev.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 109c9d58cbd..19391208eac 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -2292,10 +2292,8 @@ toplev::main (int argc, char **argv)
      emit some diagnostics here.  */
   invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
 
-  if (flag_diagnostics_generate_patch)
+  if (global_dc->edit_context_ptr)
     {
-      gcc_assert (global_dc->edit_context_ptr);
-
       pretty_printer pp;
       pp_show_color (&pp) = pp_show_color (global_dc->printer);
       global_dc->edit_context_ptr->print_diff (&pp, true);
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 21/21] diagnostics: fix corrupt json/SARIF on stderr [PR114348]
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (19 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 20/21] Fix ICE in -fdiagnostics-generate-patch [PR112684] David Malcolm
@ 2024-05-09 17:42 ` David Malcolm
  2024-05-13  9:03 ` [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) Jakub Jelinek
  21 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2024-05-09 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Various values of -fdiagnostics-format= request machine-readable output
on stderr, using JSON, but in various places we use fnotice to write
free-form text to stderr, such as "compilation terminated", leading to
corrupt JSON.

Fix by having fnotice skip the output for such cases.

Backported from r14-9554-g0bf99b1b7eda2f (using a variable rather
than a vfunc of class diagnostic_output_format, since the latter
was added in gcc 14)

gcc/ChangeLog:
	PR middle-end/114348
	* diagnostic.cc (output_format): New variable.
	(fnotice): Bail out if the user requested one of the
	machine-readable diagnostic output formats on stderr.
	(diagnostic_output_format_init): Set output_format.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/diagnostic.cc | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 0f093081161..a3d84cf0bfa 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -2175,6 +2175,9 @@ internal_error_no_backtrace (const char *gmsgid, ...)
   gcc_unreachable ();
 }
 \f
+
+static enum diagnostics_output_format output_format;
+
 /* Special case error functions.  Most are implemented in terms of the
    above, or should be.  */
 
@@ -2183,6 +2186,25 @@ internal_error_no_backtrace (const char *gmsgid, ...)
 void
 fnotice (FILE *file, const char *cmsgid, ...)
 {
+  /* If the user requested one of the machine-readable diagnostic output
+     formats on stderr (e.g. -fdiagnostics-format=sarif-stderr), then
+     emitting free-form text on stderr will lead to corrupt output.
+     Skip the message for such cases.  */
+  if (file == stderr && global_dc)
+    switch (output_format)
+      {
+      default:
+	gcc_unreachable ();
+      case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
+      case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE:
+      case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
+	break;
+      case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR:
+      case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
+	/* stderr is meant to machine-readable; skip.  */
+	return;
+      }
+
   va_list ap;
 
   va_start (ap, cmsgid);
@@ -2290,6 +2312,8 @@ diagnostic_output_format_init (diagnostic_context *context,
 			       const char *base_file_name,
 			       enum diagnostics_output_format format)
 {
+  output_format = format;
+
   switch (format)
     {
     default:
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 02/21] analyzer: Fix allocation size false positive on conjured svalue [PR109577]
  2024-05-09 17:42 ` [PATCH 02/21] analyzer: Fix allocation size false positive on conjured svalue [PR109577] David Malcolm
@ 2024-05-11 16:43   ` NightStrike
  0 siblings, 0 replies; 25+ messages in thread
From: NightStrike @ 2024-05-11 16:43 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, Tim Lange

On Thu, May 9, 2024 at 1:45 PM David Malcolm <dmalcolm@redhat.com> wrote:
>
> From: Tim Lange <mail@tim-lange.me>
>
> Currently, the analyzer tries to prove that the allocation size is a
> multiple of the pointee's type size.  This patch reverses the behavior
> to try to prove that the expression is not a multiple of the pointee's
> type size.  With this change, each unhandled case should be gracefully
> considered as correct.  This fixes the bug reported in PR 109577 by
> Paul Eggert.
>

<snip>

> diff --git a/gcc/testsuite/gcc.dg/analyzer/pr109577.c b/gcc/testsuite/gcc.dg/analyzer/pr109577.c
> new file mode 100644
> index 00000000000..a6af6f7019f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/analyzer/pr109577.c
> @@ -0,0 +1,16 @@
> +void *malloc (unsigned long);

This change missed my comment here describing this mistake:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109577#c5

Can you please fix this on all branches?

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 03/21] testsuite: Add more allocation size tests for conjured svalues [PR110014]
  2024-05-09 17:42 ` [PATCH 03/21] testsuite: Add more allocation size tests for conjured svalues [PR110014] David Malcolm
@ 2024-05-11 16:44   ` NightStrike
  0 siblings, 0 replies; 25+ messages in thread
From: NightStrike @ 2024-05-11 16:44 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, Tim Lange

On Thu, May 9, 2024 at 1:47 PM David Malcolm <dmalcolm@redhat.com> wrote:
>
> From: Tim Lange <mail@tim-lange.me>
>
> This patch adds the reproducers reported in PR 110014 as test cases. The
> false positives in those cases are already fixed with PR 109577.
>
> 2023-06-09  Tim Lange  <mail@tim-lange.me>
>
>         PR analyzer/110014
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/analyzer/realloc-pr110014.c: New tests.
>

<snip>

> diff --git a/gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c b/gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c
> new file mode 100644
> index 00000000000..d76b8781413
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/analyzer/realloc-pr110014.c
> @@ -0,0 +1,25 @@
> +void *realloc (void *, unsigned long)
> +  __attribute__((__nothrow__, __leaf__))
> +  __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__ (2)));

This change missed my comment about the wrong type for realloc from
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110014#c3

Can you please fix this on all branches?

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics)
  2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
                   ` (20 preceding siblings ...)
  2024-05-09 17:42 ` [PATCH 21/21] diagnostics: fix corrupt json/SARIF on stderr [PR114348] David Malcolm
@ 2024-05-13  9:03 ` Jakub Jelinek
  21 siblings, 0 replies; 25+ messages in thread
From: Jakub Jelinek @ 2024-05-13  9:03 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches

On Thu, May 09, 2024 at 01:42:15PM -0400, David Malcolm wrote:
> I've pushed the following changes to releases/gcc-13
> as r13-8741-g89feb3557a0188 through r13-8761-gb7a2697733d19a.

Unfortunately many of the commits contained git commit message wording
that update_git_version can't cope with.
Wording like
(cherry picked from commit r14-1664-gfe9771b59f576f)
is wrong,
(cherry picked from commit .....)
is reserved solely for what one gets from git cherry-pick -x
(i.e. the full commit hash without anything extra).

I had to ignore the following commits in the ChangeLog generation
because of this:

89feb3557a018893cfe50c2e07f91559bd3cde2b
ccf8d3e3d26c6ba3d5e11fffeed8d64018e9c060
e0c52905f666e3d23881f82dbf39466a24f009f4
b38472ffc1e631bd357573b44d956ce16d94e666
a0b13d0860848dd5f2876897ada1e22e4e681e91
b8c772cae97b54386f7853edf0f9897012bfa90b
810d35a7e054bcbb5b66d2e5924428e445f5fba9
0df1ee083434ac00ecb19582b1e5b25e105981b2
2c688f6afce4cbb414f5baab1199cd525f309fca
60dcb710b6b4aa22ea96abc8df6dfe9067f3d7fe
44968a0e00f656e9bb3e504bb2fa1a8282002015

Can you please add the ChangeLog entries for these by hand
(commits which only touch ChangeLog files are allowed and shouldn't
contain ChangeLog style entry in the commit message)?

Thanks.

	Jakub


^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2024-05-13  9:03 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-09 17:42 [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) David Malcolm
2024-05-09 17:42 ` [PATCH 01/21] analyzer: add caching to globals with initializers [PR110112] David Malcolm
2024-05-09 17:42 ` [PATCH 02/21] analyzer: Fix allocation size false positive on conjured svalue [PR109577] David Malcolm
2024-05-11 16:43   ` NightStrike
2024-05-09 17:42 ` [PATCH 03/21] testsuite: Add more allocation size tests for conjured svalues [PR110014] David Malcolm
2024-05-11 16:44   ` NightStrike
2024-05-09 17:42 ` [PATCH 04/21] jit: avoid using __vector in testcase [PR110466] David Malcolm
2024-05-09 17:42 ` [PATCH 05/21] jit.exp: handle dwarf version mismatch in jit-check-debug-info [PR110466] David Malcolm
2024-05-09 17:42 ` [PATCH 06/21] analyzer: fix ICE on division of tainted floating-point values [PR110700] David Malcolm
2024-05-09 17:42 ` [PATCH 07/21] analyzer: fix ICE on zero-sized arrays [PR110882] David Malcolm
2024-05-09 17:42 ` [PATCH 08/21] testsuite, analyzer: add test case [PR108171] David Malcolm
2024-05-09 17:42 ` [PATCH 09/21] jit: dump string literal initializers correctly David Malcolm
2024-05-09 17:42 ` [PATCH 10/21] analyzer: fix ICE for 2 bits before the start of base region [PR112889] David Malcolm
2024-05-09 17:42 ` [PATCH 11/21] analyzer: fix deref-before-check false positives due to inlining [PR112790] David Malcolm
2024-05-09 17:42 ` [PATCH 12/21] analyzer: casting all zeroes should give all zeroes [PR113333] David Malcolm
2024-05-09 17:42 ` [PATCH 13/21] analyzer: fix defaults in compound assignments from non-zero offsets [PR112969] David Malcolm
2024-05-09 17:42 ` [PATCH 14/21] analyzer: fix skipping of debug stmts [PR113253] David Malcolm
2024-05-09 17:42 ` [PATCH 15/21] analyzer: fix -Wanalyzer-va-arg-type-mismatch false +ve on int types [PR111289] David Malcolm
2024-05-09 17:42 ` [PATCH 16/21] analyzer: fix -Wanalyzer-deref-before-check false positive seen in loop header macro [PR109251] David Malcolm
2024-05-09 17:42 ` [PATCH 17/21] analyzer: fix ICE due to type mismatch when replaying call summary [PR114473] David Malcolm
2024-05-09 17:42 ` [PATCH 18/21] analyzer: fix ICE and false positive with -Wanalyzer-deref-before-check [PR114408] David Malcolm
2024-05-09 17:42 ` [PATCH 19/21] diagnostics: fix ICE on sarif output when source file is unreadable [PR111700] David Malcolm
2024-05-09 17:42 ` [PATCH 20/21] Fix ICE in -fdiagnostics-generate-patch [PR112684] David Malcolm
2024-05-09 17:42 ` [PATCH 21/21] diagnostics: fix corrupt json/SARIF on stderr [PR114348] David Malcolm
2024-05-13  9:03 ` [pushed 00/21] Various backports to gcc 13 (analyzer, jit, diagnostics) Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).