summaryrefslogtreecommitdiff
path: root/gcc/lra.c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2020-03-30 11:13:59 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2020-03-30 21:03:00 -0400
commit3809bcd6c0ee324cbd855c68cee104c8bf134dbe (patch)
tree568baf4fc6b07c0092c61cdfad2ad9ba176156ac /gcc/lra.c
parent13a29fc5730ac3a5e3296971d15ca63dcc0ae261 (diff)
lra: set insn_code_data to NULL when freeing
libgccjit's test-threads.c repeatedly compiles and runs numerous tests, each in a separate thread. Attempting to add an empty test that generates no code leads to a double-free ICE within that thread, within lra.c's finish_insn_code_data_once. The root cause is that the insn_code_data array is cleared in init_insn_code_data_once, but this is only called the first time a cgraph_node is expanded [1], whereas the "loop-over-all-elements and free them" is unconditionally called in finalize [2]. Hence if there are no functions: * the array is not re-initialized for the empty context * when finish_insn_code_data_once is called for the empty context it still contains the freed pointers from the previous context that held the jit mutex, and hence the free is a double-free. This patch sets the pointers to NULL after freeing them, fixing the ICE. [1] init_insn_code_data_once is called via lra_init_once called by ira_init_once called by initialize_rtl, via: if (!rtl_initialized) ira_init_once (); called by init_function_start called by cgraph_node::expand [2]: finish_insn_code_data_once is called by: lra_finish_once called by finalize gcc/ChangeLog: * lra.c (finish_insn_code_data_once): Set the array elements to NULL after freeing them. gcc/testsuite/ChangeLog: * jit.dg/all-non-failing-tests.h: Add test-empty.c
Diffstat (limited to 'gcc/lra.c')
-rw-r--r--gcc/lra.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/gcc/lra.c b/gcc/lra.c
index d5ea3622686..5e8b75b1fda 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -653,7 +653,10 @@ finish_insn_code_data_once (void)
for (unsigned int i = 0; i < NUM_INSN_CODES; i++)
{
if (insn_code_data[i] != NULL)
- free (insn_code_data[i]);
+ {
+ free (insn_code_data[i]);
+ insn_code_data[i] = NULL;
+ }
}
}