aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2024-05-10 14:19:49 +0200
committerRichard Biener <rguenther@suse.de>2024-05-10 15:43:47 +0200
commit34d15a4d630a0d54eddb99bdab086c506e10dac5 (patch)
treee4d83dc268f2ac92fa04241bc8a1cc1213c6d6db /gcc
parent52d4691294c84793b301ad3cc24e277b8c7efe0b (diff)
downloadgcc-34d15a4d630a0d54eddb99bdab086c506e10dac5.zip
gcc-34d15a4d630a0d54eddb99bdab086c506e10dac5.tar.gz
gcc-34d15a4d630a0d54eddb99bdab086c506e10dac5.tar.bz2
tree-optimization/114998 - use-after-free with loop distribution
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr114998.c35
-rw-r--r--gcc/tree-loop-distribution.cc24
2 files changed, 53 insertions, 6 deletions
diff --git a/gcc/testsuite/gcc.dg/torture/pr114998.c b/gcc/testsuite/gcc.dg/torture/pr114998.c
new file mode 100644
index 0000000..81fc1e0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr114998.c
@@ -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;
+}
diff --git a/gcc/tree-loop-distribution.cc b/gcc/tree-loop-distribution.cc
index 95203fe..45932ba 100644
--- a/gcc/tree-loop-distribution.cc
+++ b/gcc/tree-loop-distribution.cc
@@ -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)