[binutils-gdb] bfd: fix memory leak when default-initializing an OAv2 attribute

Matthieu Longo mlongo@sourceware.org
Fri Feb 6 10:42:31 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=31221ae54956c086b2ec7fab688b414a718901ed

commit 31221ae54956c086b2ec7fab688b414a718901ed
Author: Matthieu Longo <matthieu.longo@arm.com>
Date:   Mon Feb 2 14:54:55 2026 +0000

    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:
---
 bfd/elf-attrs.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

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


More information about the Binutils-cvs mailing list