From: David Malcolm Date: Mon, 30 Mar 2020 15:13:59 +0000 (-0400) Subject: lra: set insn_code_data to NULL when freeing X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3809bcd6c0ee324cbd855c68cee104c8bf134dbe;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ace41d0efe6..101956a53c6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2020-03-30 David Malcolm + + * lra.c (finish_insn_code_data_once): Set the array elements + to NULL after freeing them. + 2020-03-30 Andreas Schwab * config/host-linux.c (TRY_EMPTY_VM_SPACE) [__riscv && __LP64__]: 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; + } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 66c71f1c15f..c72aa9aae06 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-03-30 David Malcolm + + * jit.dg/all-non-failing-tests.h: Add test-empty.c + 2020-03-30 Jakub Jelinek PR c++/94385 diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index b2acc74ae95..af744192a73 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -116,6 +116,13 @@ #undef create_code #undef verify_code +/* test-empty.c */ +#define create_code create_code_empty +#define verify_code verify_code_empty +#include "test-empty.c" +#undef create_code +#undef verify_code + /* test-error-*.c: We don't use these test cases, since they deliberately introduce errors, which we don't want here. */ @@ -328,6 +335,9 @@ const struct testcase testcases[] = { {"expressions", create_code_expressions, verify_code_expressions}, + {"empty", + create_code_empty, + verify_code_empty}, {"factorial", create_code_factorial, verify_code_factorial},