[committed] analyzer: fix apparent hang with -fanalyzer-verbosity=0 [PR analyzer/99886]

Message ID 20210405145650.270426-1-dmalcolm@redhat.com
State New
Headers show
Series
  • [committed] analyzer: fix apparent hang with -fanalyzer-verbosity=0 [PR analyzer/99886]
Related show

Commit Message

Paul Richard Thomas via Gcc-patches April 5, 2021, 2:56 p.m.
The analyzer appeared to enter an infinite loop on malloc-1.c
when -fanalyzer-verbosity=0 was used.  In fact, it was slowly
counting from 0 to 0xffffffff.

Root cause is looping up to effectively ((unsigned)0) - 1 in
diagnostic_manager::consolidate_conditions when there are no events
in the path.

Fixed by the following, which uses signed integers when subtracting
from path->num_events () when simplifying checker_paths.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r11-7987-g69b66ff02353a87585329bb3cf4ac20d6dee1b16.

gcc/analyzer/ChangeLog:
	PR analyzer/99886
	* diagnostic-manager.cc
	(diagnostic_manager::prune_interproc_events): Use signed integers
	when subtracting one from path->num_events ().
	(diagnostic_manager::consolidate_conditions): Likewise.  Convert
	next_idx to a signed int.

gcc/testsuite/ChangeLog:
	PR analyzer/99886
	* gcc.dg/analyzer/pr99886.c: New test.
---
 gcc/analyzer/diagnostic-manager.cc      |  8 +++++---
 gcc/testsuite/gcc.dg/analyzer/pr99886.c | 21 +++++++++++++++++++++
 2 files changed, 26 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr99886.c

-- 
2.26.2

Patch

diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc
index 9ec3e899e85..443ff058f65 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -2081,7 +2081,7 @@  diagnostic_manager::prune_interproc_events (checker_path *path) const
   do
     {
       changed = false;
-      int idx = path->num_events () - 1;
+      int idx = (signed)path->num_events () - 1;
       while (idx >= 0)
 	{
 	  /* Prune [..., call, function-entry, return, ...] triples.  */
@@ -2200,7 +2200,9 @@  diagnostic_manager::consolidate_conditions (checker_path *path) const
   if (flag_analyzer_verbose_edges)
     return;
 
-  for (unsigned start_idx = 0; start_idx < path->num_events () - 1; start_idx++)
+  for (int start_idx = 0;
+       start_idx < (signed)path->num_events () - 1;
+       start_idx++)
     {
       if (path->cfg_edge_pair_at_p (start_idx))
 	{
@@ -2231,7 +2233,7 @@  diagnostic_manager::consolidate_conditions (checker_path *path) const
 	       [start_idx, next_idx)
 	     where all apart from the final event are on the same line,
 	     and all are either TRUE or FALSE edges, matching the initial.  */
-	  unsigned next_idx = start_idx + 2;
+	  int next_idx = start_idx + 2;
 	  while (path->cfg_edge_pair_at_p (next_idx)
 		 && same_line_as_p (start_exp_loc, path, next_idx))
 	    {
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr99886.c b/gcc/testsuite/gcc.dg/analyzer/pr99886.c
new file mode 100644
index 00000000000..da768ba6298
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr99886.c
@@ -0,0 +1,21 @@ 
+/* Regression test for hang with -fanalyzer-verbosity=0.  */
+/* { dg-additional-options "-fanalyzer-verbosity=0" } */
+
+#include <stdlib.h>
+
+struct coord {
+  float x;
+  float y;
+};
+
+void test_34 (void)
+{
+  float *q;
+  struct coord *p = malloc (sizeof (struct coord));
+  if (!p)
+    return;
+  p->x = 0.0f;
+  q = &p->x;
+  free (p);
+  *q = 1.0f; /* { dg-warning "use after 'free' of 'q'" } */
+};