From: Matthieu Longo Date: Mon, 2 Feb 2026 14:54:55 +0000 (+0000) Subject: bfd: fix memory leak when default-initializing an OAv2 attribute X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=31221ae54956c086b2ec7fab688b414a718901ed;p=thirdparty%2Fbinutils-gdb.git bfd: fix memory leak when default-initializing an OAv2 attribute To merge an OAv2 attribute, the input values must either be present in the subsections being merged, or a default value must be created for the missing ones. Note that this default value is not necessarily null. In the current implementation of oav2_attr_default(), the default value is created by copying another attribute provided as a template. As a result, a string attribute may be copied from the template if it is not NULL. The copied value is overwritten with whatever default the backend provides for that attribute. In oav2_attr_overwrite_with_default(), when no default attribute value is found in the backend, a string attribute is simply assigned NULL. This ignores the possibility that the original value may be non-NULL, and causes the previously allocated memory for the string to be leaked. This issue was detected by the LeakSanitizer (see the relevant part of the stack trace below). This patch fixes the memory leak by freeing the existing value before assigning NULL to the attribute. ==ERROR: LeakSanitizer: detected memory leaks Direct leak of 5 byte(s) in 1 object(s) allocated from: #2 xstrdup ../../libiberty/xstrdup.c:34 #3 _bfd_elf_obj_attr_v2_copy ../../bfd/elf-attrs.c:3185 #4 oav2_attr_default ../../bfd/elf-attrs.c:1109 #5 handle_optional_subsection_merge ../../bfd/elf-attrs.c:1558 --- diff --git a/bfd/elf-attrs.c b/bfd/elf-attrs.c index e0847a04aec..c4f81ba5f6b 100644 --- a/bfd/elf-attrs.c +++ b/bfd/elf-attrs.c @@ -1083,33 +1083,30 @@ oav2_attr_overwrite_with_default (const struct bfd_link_info *info, { const struct elf_backend_data *bed = get_elf_backend_data (info->output_bfd); + union obj_attr_value_v2 default_value; + memset (&default_value, 0, sizeof (default_value)); + const obj_attr_info_t *attr_info = _bfd_obj_attr_v2_find_known_by_tag (bed, subsec->name, attr->tag); if (attr_info == NULL) { attr->status = obj_attr_v2_unknown; - if (subsec->encoding == OA_ENC_ULEB128) - attr->val.uint = 0; - else - attr->val.string = NULL; + oav2_assign_value (subsec->encoding, attr, default_value); return; } if (bed->obj_attr_v2_default_value != NULL && bed->obj_attr_v2_default_value (info, attr_info, subsec, attr)) - {} - else if (subsec->encoding == OA_ENC_NTBS) + return; + + if (subsec->encoding == OA_ENC_NTBS) { - if (attr->val.string != NULL) - { - free ((void *) attr->val.string); - attr->val.string = NULL; - } if (attr_info->default_value.string != NULL) - attr->val.string = xstrdup (attr_info->default_value.string); + default_value.string = xstrdup (attr_info->default_value.string); } else - attr->val.uint = attr_info->default_value.uint; + default_value.uint = attr_info->default_value.uint; + oav2_assign_value (subsec->encoding, attr, default_value); } /* Create a new attribute with the same key (=tag) as ATTR, and initialized with