]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/114998 - use-after-free with loop distribution
authorRichard Biener <rguenther@suse.de>
Fri, 10 May 2024 12:19:49 +0000 (14:19 +0200)
committerRichard Biener <rguenther@suse.de>
Fri, 10 May 2024 13:43:47 +0000 (15:43 +0200)
When loop distribution releases a PHI node of the original IL it
can end up clobbering memory that's re-used when it upon releasing
its RDG resets all stmt UIDs back to -1, even those that got released.

The fix is to avoid resetting UIDs based on stmts in the RDG but
instead reset only those still present in the loop.

PR tree-optimization/114998
* tree-loop-distribution.cc (free_rdg): Take loop argument.
Reset UIDs of stmts still in the IL rather than all stmts
referenced from the RDG.
(loop_distribution::build_rdg): Pass loop to free_rdg.
(loop_distribution::distribute_loop): Likewise.
(loop_distribution::transform_reduction_loop): Likewise.

* gcc.dg/torture/pr114998.c: New testcase.

gcc/testsuite/gcc.dg/torture/pr114998.c [new file with mode: 0644]
gcc/tree-loop-distribution.cc

diff --git a/gcc/testsuite/gcc.dg/torture/pr114998.c b/gcc/testsuite/gcc.dg/torture/pr114998.c
new file mode 100644 (file)
index 0000000..81fc1e0
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-dce -ftree-loop-distribution" } */
+
+short a, d;
+int b, c, f, g, h, i, j[2], o;
+__attribute__((const)) int s(char r);
+int main() {
+  int l, m, k, n;
+  if (b) {
+    char p;
+    for (; p >= 0; p--) {
+      int e[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0,
+                 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1,
+                 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0};
+      if (j[p]) {
+        int q[1];
+        i = o;
+        o = q[h];
+        if (g)
+          n = d;
+        m = 4;
+        for (; m; m--) {
+          if (l)
+            k |= c;
+          if (a)
+            break;
+        }
+      }
+      s(n);
+      f |= b;
+    }
+  }
+  return 0;
+}
index 95203fefa18827c4f1f2ee85fc973d1b7f8a0c57..45932bae5e7fb54760aaef43815550905343be0c 100644 (file)
@@ -778,7 +778,7 @@ loop_distribution::stmts_from_loop (class loop *loop, vec<gimple *> *stmts)
 /* Free the reduced dependence graph RDG.  */
 
 static void
-free_rdg (struct graph *rdg)
+free_rdg (struct graph *rdg, loop_p loop)
 {
   int i;
 
@@ -792,13 +792,25 @@ free_rdg (struct graph *rdg)
 
       if (v->data)
        {
-         gimple_set_uid (RDGV_STMT (v), -1);
          (RDGV_DATAREFS (v)).release ();
          free (v->data);
        }
     }
 
   free_graph (rdg);
+
+  /* Reset UIDs of stmts still in the loop.  */
+  basic_block *bbs = get_loop_body (loop);
+  for (unsigned i = 0; i < loop->num_nodes; ++i)
+    {
+      basic_block bb = bbs[i];
+      gimple_stmt_iterator gsi;
+      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+       gimple_set_uid (gsi_stmt (gsi), -1);
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+       gimple_set_uid (gsi_stmt (gsi), -1);
+    }
+  free (bbs);
 }
 
 struct graph *
@@ -812,7 +824,7 @@ loop_distribution::build_rdg (class loop *loop, control_dependences *cd)
   rdg = new_graph (stmts.length ());
   if (!create_rdg_vertices (rdg, stmts, loop))
     {
-      free_rdg (rdg);
+      free_rdg (rdg, loop);
       return NULL;
     }
   stmts.release ();
@@ -3062,7 +3074,7 @@ loop_distribution::distribute_loop (class loop *loop,
                 "Loop %d not distributed: too many memory references.\n",
                 loop->num);
 
-      free_rdg (rdg);
+      free_rdg (rdg, loop);
       loop_nest.release ();
       free_data_refs (datarefs_vec);
       delete ddrs_table;
@@ -3259,7 +3271,7 @@ loop_distribution::distribute_loop (class loop *loop,
   FOR_EACH_VEC_ELT (partitions, i, partition)
     partition_free (partition);
 
-  free_rdg (rdg);
+  free_rdg (rdg, loop);
   return nbp - *nb_calls;
 }
 
@@ -3665,7 +3677,7 @@ loop_distribution::transform_reduction_loop (loop_p loop)
   auto_bitmap partition_stmts;
   bitmap_set_range (partition_stmts, 0, rdg->n_vertices);
   find_single_drs (loop, rdg, partition_stmts, &store_dr, &load_dr);
-  free_rdg (rdg);
+  free_rdg (rdg, loop);
 
   /* Bail out if there is no single load.  */
   if (load_dr == NULL)