[PATCH v1 3/7] bfd: fix memory leak when assigning the merge result of OAv2 string attributes
Matthieu Longo
matthieu.longo@arm.com
Tue Feb 3 10:00:44 GMT 2026
oav2_attr_merge() merges input OAv2 attributes and returns a merge result,
which is then assigned to the previous value held by REF.
In the current implementation of handle_optional_subsection_merge(), when
merging string attributes, the existing value is overwritten without first
being freed. This results in a memory leak. This issue was detected by
LeakSanitizer (see the relevant stack trace below).
This patch fixes the memory leak by wrapping the assignment of the merge
result to REF inside a helper function. For string attributes, the helper
frees the previous value before performing the assignment. This approach
also centralizes the logic and makes easier to correctly free and assign
more complex structures in the future, if needed.
==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 12 byte(s) in 2 object(s) allocated from:
#2 0x5bf8acb5f5af in xmemdup ../../libiberty/xmemdup.c:37
#3 0x5bf8ac95000b in read_ntbs ../../bfd/elf-attrs.c:2676
#4 0x5bf8ac9501c0 in oav2_parse_attr ../../bfd/elf-attrs.c:2699
#5 0x5bf8ac9508fb in oav2_parse_subsection ../../bfd/elf-attrs.c:2845
#6 0x5bf8ac950cca in oav2_parse_section ../../bfd/elf-attrs.c:2883
#7 0x5bf8ac951277 in _bfd_elf_parse_attributes ../../bfd/elf-attrs.c:2947
---
bfd/elf-attrs.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/bfd/elf-attrs.c b/bfd/elf-attrs.c
index 6c3cfc09677..b9547631793 100644
--- a/bfd/elf-attrs.c
+++ b/bfd/elf-attrs.c
@@ -1467,6 +1467,19 @@ oav2_search_by_tag (obj_attr_v2_t *attr_first, obj_attr_tag_t tag)
return NULL;
}
+/* Assign the merge result to REF.
+ The only reason to exist for this helper is when the manipulated value is a
+ string. In this case, the value in REF must be freed before assigning. */
+static void
+oav2_attr_assign_merge_result (obj_attr_encoding_v2_t encoding,
+ obj_attr_v2_t *a_ref,
+ obj_attr_v2_merge_result_t *res)
+{
+ if (encoding == OA_ENC_NTBS)
+ free ((char *) a_ref->val.string);
+ a_ref->val = res->val;
+}
+
/* Merge optional subsection S_ABFD into S_REF. S_FROZEN is used to report any
issue with the selected configuration, and to force the merge value to a
specific value if needed. */
@@ -1505,7 +1518,7 @@ handle_optional_subsection_merge (const struct bfd_link_info *info,
frozen_is_abfd);
_bfd_elf_obj_attr_v2_free (a_default, s_ref->encoding);
if (res.merge)
- a_ref->val = res.val;
+ oav2_attr_assign_merge_result (s_ref->encoding, a_ref, &res);
else if (res.reason == OAv2_MERGE_UNSUPPORTED)
a_ref->status = obj_attr_v2_unknown;
a_ref = a_ref->next;
@@ -1518,7 +1531,7 @@ handle_optional_subsection_merge (const struct bfd_link_info *info,
frozen_is_abfd);
if (res.merge || res.reason == OAv2_MERGE_SAME_VALUE_AS_REF)
{
- a_default->val = res.val;
+ oav2_attr_assign_merge_result (s_ref->encoding, a_default, &res);
LINKED_LIST_INSERT_BEFORE (obj_attr_v2_t)
(s_ref, a_default, a_ref);
}
@@ -1532,7 +1545,7 @@ handle_optional_subsection_merge (const struct bfd_link_info *info,
= oav2_attr_merge (info, abfd, s_ref, a_ref, a_abfd, a_frozen,
frozen_is_abfd);
if (res.merge)
- a_ref->val = res.val;
+ oav2_attr_assign_merge_result (s_ref->encoding, a_ref, &res);
else if (res.reason == OAv2_MERGE_UNSUPPORTED)
a_ref->status = obj_attr_v2_unknown;
a_ref = a_ref->next;
@@ -1547,7 +1560,7 @@ handle_optional_subsection_merge (const struct bfd_link_info *info,
= oav2_attr_merge (info, abfd, s_ref, a_default, a_abfd, NULL, false);
if (res.merge || res.reason == OAv2_MERGE_SAME_VALUE_AS_REF)
{
- a_default->val = res.val;
+ oav2_attr_assign_merge_result (s_ref->encoding, a_default, &res);
LINKED_LIST_APPEND (obj_attr_v2_t) (s_ref, a_default);
}
else
@@ -1566,7 +1579,7 @@ handle_optional_subsection_merge (const struct bfd_link_info *info,
frozen_is_abfd);
_bfd_elf_obj_attr_v2_free (a_default, s_ref->encoding);
if (res.merge)
- a_ref->val = res.val;
+ oav2_attr_assign_merge_result (s_ref->encoding, a_ref, &res);
else if (res.reason == OAv2_MERGE_UNSUPPORTED)
a_ref->status = obj_attr_v2_unknown;
}
--
2.52.0
More information about the Binutils
mailing list