]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
RISC-V: Release subset lists on all paths when the linker merges arch attributes
authorEthan Y. C. Liang <ycl669@andestech.com>
Mon, 6 Jul 2026 11:44:27 +0000 (19:44 +0800)
committerNelson Chu <nelson.chu@sifive.com>
Thu, 9 Jul 2026 00:54:56 +0000 (08:54 +0800)
riscv_merge_arch_attr_info returned early on the error paths without
releasing in_subsets, out_subsets and merged_subsets, so the nodes
already added to them were leaked.  The leaked nodes of in_subsets
and out_subsets also carry over into the next merge.

Route every post-parse error path through a single cleanup exit that
releases all three subset lists, and drop the now-redundant reset of
merged_subsets at entry.

bfd/elfxx-riscv.c

index e1639cbc2cb717c58fa70ebd5fc59e006b89e9a4..8fc4e1408f9a09ed1fc56b7f8aa857a4e5723235 100644 (file)
@@ -3755,10 +3755,9 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch,
 {
   riscv_subset_t *in, *out;
   static char *merged_arch_str = NULL;
+  char *result = NULL;
 
   unsigned xlen_in, xlen_out;
-  merged_subsets.head = NULL;
-  merged_subsets.tail = NULL;
 
   riscv_parse_subset_t riscv_rps_ld_in =
     {&in_subsets, _bfd_error_handler, &xlen_in, NULL, false};
@@ -3774,9 +3773,9 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch,
 
   /* Parse subset from ISA string.  */
   if (!riscv_parse_subset (&riscv_rps_ld_in, in_arch))
-    return NULL;
+    goto cleanup;
   if (!riscv_parse_subset (&riscv_rps_ld_out, out_arch))
-    return NULL;
+    goto cleanup;
 
   /* Checking XLEN.  */
   if (xlen_out != xlen_in)
@@ -3784,7 +3783,7 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch,
       _bfd_error_handler
        (_("error: %pB: ISA string of input (%s) doesn't match "
           "output (%s)"), ibfd, in_arch, out_arch);
-      return NULL;
+      goto cleanup;
     }
 
   /* Merge subset list.  */
@@ -3793,18 +3792,18 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch,
 
   /* Merge standard extension.  */
   if (!riscv_merge_std_ext (ibfd, in_arch, out_arch, &in, &out))
-    return NULL;
+    goto cleanup;
 
   /* Merge all non-single letter extensions with single call.  */
   if (!riscv_merge_multi_letter_ext (&in, &out))
-    return NULL;
+    goto cleanup;
 
   if (xlen_in != xlen_out)
     {
       _bfd_error_handler
        (_("error: %pB: XLEN of input (%u) doesn't match "
           "output (%u)"), ibfd, xlen_in, xlen_out);
-      return NULL;
+      goto cleanup;
     }
 
   if (xlen_in != arch_size)
@@ -3812,7 +3811,7 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch,
       _bfd_error_handler
        (_("error: %pB: unsupported XLEN (%u), you might be "
           "using wrong emulation"), ibfd, xlen_in);
-      return NULL;
+      goto cleanup;
     }
 
   /* Free the previous merged_arch_str which called xmalloc.  */
@@ -3820,13 +3819,15 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch,
 
   merged_arch_str = riscv_arch_str (arch_size, &merged_subsets,
                                    false/* update */);
+  result = merged_arch_str;
 
+ cleanup:
   /* Release the subset lists.  */
   riscv_release_subset_list (&in_subsets);
   riscv_release_subset_list (&out_subsets);
   riscv_release_subset_list (&merged_subsets);
 
-  return merged_arch_str;
+  return result;
 }
 
 /* Merge object attributes from IBFD into output_bfd of INFO.