From: 翁愷邑 Date: Thu, 17 Apr 2025 22:24:20 +0000 (-0600) Subject: [PATCH] RISC-V: Do not free a riscv_arch_string when handling target-arch attribute X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2d6f1ca17f25b28da8f8d83622f0e029da2340e7;p=thirdparty%2Fgcc.git [PATCH] RISC-V: Do not free a riscv_arch_string when handling target-arch attribute The build_target_option_node() function may return a cached node when fndecl having the same effective global_options. Therefore, freeing memory used in target nodes can lead to a use-after-free issue, as a target node may be shared by multiple fndecl. This issue occurs in gcc.target/riscv/target-attr-16.c, where all functions have the same march, but the last function tries to free its old x_riscv_arch_string (which is shared) when processing the second target attribute.However, the behavior of this issue depends on how the OS handles malloc. It's very likely that xstrdup returns the old address just freed, coincidentally hiding the issue. We can verify the issue by forcing xstrdup to return a new address, e.g., - if (opts->x_riscv_arch_string != default_opts->x_riscv_arch_string) - free (CONST_CAST (void *, (const void *) opts->x_riscv_arch_string)); + // Force it to use a new address, NFCI + const char *tmp = opts->x_riscv_arch_string; opts->x_riscv_arch_string = xstrdup (local_arch_str); + if (tmp != default_opts->x_riscv_arch_string) + free (CONST_CAST (void *, (const void *) tmp)); This patch replaces xstrdup with ggc_strdup and let gc to take care of unused strings. gcc/ChangeLog: * config/riscv/riscv-target-attr.cc (riscv_target_attr_parser::update_settings): Do not manually free any arch string. --- diff --git a/gcc/config/riscv/riscv-target-attr.cc b/gcc/config/riscv/riscv-target-attr.cc index 1d968655f95..8ad3025579b 100644 --- a/gcc/config/riscv/riscv-target-attr.cc +++ b/gcc/config/riscv/riscv-target-attr.cc @@ -257,11 +257,7 @@ riscv_target_attr_parser::update_settings (struct gcc_options *opts) const { std::string local_arch = m_subset_list->to_string (true); const char* local_arch_str = local_arch.c_str (); - struct cl_target_option *default_opts - = TREE_TARGET_OPTION (target_option_default_node); - if (opts->x_riscv_arch_string != default_opts->x_riscv_arch_string) - free (CONST_CAST (void *, (const void *) opts->x_riscv_arch_string)); - opts->x_riscv_arch_string = xstrdup (local_arch_str); + opts->x_riscv_arch_string = ggc_strdup (local_arch_str); riscv_set_arch_by_subset_list (m_subset_list, opts); }