aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2021-04-05 10:48:01 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2021-04-05 10:48:01 -0400
commit69b66ff02353a87585329bb3cf4ac20d6dee1b16 (patch)
treed65789a51f9c7a14f4b6fcf0f13a157d8a680bd8
parentbd89b8fe9efbdf0a95d827553d1a84fd3cefaa16 (diff)
downloadgcc-69b66ff02353a87585329bb3cf4ac20d6dee1b16.zip
gcc-69b66ff02353a87585329bb3cf4ac20d6dee1b16.tar.gz
gcc-69b66ff02353a87585329bb3cf4ac20d6dee1b16.tar.bz2
analyzer: fix apparent hang with -fanalyzer-verbosity=0 [PR analyzer/99886]
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. 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.
-rw-r--r--gcc/analyzer/diagnostic-manager.cc8
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr99886.c21
2 files changed, 26 insertions, 3 deletions
diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc
index 9ec3e89..443ff05 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 0000000..da768ba
--- /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'" } */
+};