aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2022-06-17 17:25:53 +0930
committerAlan Modra <amodra@gmail.com>2022-06-17 21:10:06 +0930
commit15797439805b1bb92c491b9c9a72500d93c0cb5b (patch)
treef2209bddb16dae0edb7a13ae8ee6aa4324801deb /gas
parentd6e1d48c83b165c129cb0aa78905f7ca80a1f682 (diff)
downloadfsf-binutils-gdb-15797439805b1bb92c491b9c9a72500d93c0cb5b.zip
fsf-binutils-gdb-15797439805b1bb92c491b9c9a72500d93c0cb5b.tar.gz
fsf-binutils-gdb-15797439805b1bb92c491b9c9a72500d93c0cb5b.tar.bz2
PR29256, memory leak in obj_elf_section_name
When handling section names in quotes obj_elf_section_name calls demand_copy_C_string, which puts the name on the gas notes obstack. Such strings aren't usually freed, since obstack_free frees all more recently allocated objects as well as its arg. When handling non-quoted names, obj_elf_section_name mallocs the name. Due to the mix of allocation strategies it isn't possible for callers to free names, if that was desirable. Partially fix this by always creating names on the obstack, which is more efficient anyway. (You still can't obstack_free on error paths due to the xtensa tc_canonicalize_section_name.) Also remove a couple of cases where the name is dup'd for no good reason as far as I know. PR 29256 * config/obj-elf.c (obj_elf_section_name): Create name on notes obstack. (obj_elf_attach_to_group): Don't strdup group name. (obj_elf_section): Likewise. (obj_elf_vendor_attribute): Use xmemdup0 rather than xstrndup.
Diffstat (limited to 'gas')
-rw-r--r--gas/config/obj-elf.c32
1 files changed, 18 insertions, 14 deletions
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index b768530..e5ab851 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -1055,28 +1055,32 @@ obj_elf_section_name (void)
return NULL;
}
- name = xmemdup0 (input_line_pointer, end - input_line_pointer);
+ obstack_grow0 (&notes, input_line_pointer, end - input_line_pointer);
+ name = obstack_base (&notes);
while (flag_sectname_subst)
{
char *subst = strchr (name, '%');
if (subst && subst[1] == 'S')
{
- int oldlen = strlen (name);
- int substlen = strlen (now_seg->name);
- int newlen = oldlen - 2 + substlen;
- char *newname = XNEWVEC (char, newlen + 1);
- int headlen = subst - name;
- memcpy (newname, name, headlen);
- strcpy (newname + headlen, now_seg->name);
- strcat (newname + headlen, subst + 2);
- xfree (name);
- name = newname;
+ size_t head = subst - name;
+ size_t tail = strlen (subst + 2) + 1;
+ size_t slen = strlen (now_seg->name);
+
+ if (slen > 2)
+ {
+ obstack_blank (&notes, slen - 2);
+ name = obstack_base (&notes);
+ }
+ memmove (name + head + slen, name + head + 2, tail);
+ memcpy (name + head, now_seg->name, slen);
}
else
break;
}
+ obstack_finish (&notes);
+
#ifdef tc_canonicalize_section_name
name = tc_canonicalize_section_name (name);
#endif
@@ -1104,7 +1108,7 @@ obj_elf_attach_to_group (int dummy ATTRIBUTE_UNUSED)
return;
}
- elf_group_name (now_seg) = xstrdup (gname);
+ elf_group_name (now_seg) = gname;
elf_section_flags (now_seg) |= SHF_GROUP;
}
@@ -1315,7 +1319,7 @@ obj_elf_section (int push)
const char *now_group = elf_group_name (now_seg);
if (now_group != NULL)
{
- match.group_name = xstrdup (now_group);
+ match.group_name = now_group;
linkonce = (now_seg->flags & SEC_LINK_ONCE) != 0;
}
}
@@ -2019,7 +2023,7 @@ obj_elf_vendor_attribute (int vendor)
if (i == 0)
goto bad;
- name = xstrndup (s, i);
+ name = xmemdup0 (s, i);
#ifndef CONVERT_SYMBOLIC_ATTRIBUTE
#define CONVERT_SYMBOLIC_ATTRIBUTE(a) -1