This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[patch] asan error on bfd bfd_simple_get_relocated_section_contents
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: binutils at sourceware dot org
- Date: Sun, 16 Feb 2014 19:28:40 +0100
- Subject: [patch] asan error on bfd bfd_simple_get_relocated_section_contents
- Authentication-results: sourceware.org; auth=none
Hi,
-fsanitize=address build crashes on an error when GDB loads a file.
https://sourceware.org/bugzilla/show_bug.cgi?id=16595
abfd->section_count unexpectedly changes between 218 and 248 in:
150 bfd_simple_get_relocated_section_contents (bfd *abfd,
[...]
218 saved_offsets = malloc (sizeof (struct saved_output_info)
219 * abfd->section_count);
[...]
230 _bfd_generic_link_add_symbols (abfd, &link_info);
[...]
248 bfd_map_over_sections (abfd, simple_restore_output_info, saved_offsets);
_bfd_generic_link_add_symbols increases section_count
#0 bfd_section_init (abfd=0x60280003c640, newsect=0x60620010a668) at section.c:831
830 abfd->section_count++;
#1 in bfd_make_section_old_way (abfd=0x60280003c640, name=0x2fe0ae0 "COMMON") at section.c:1106
#2 in _bfd_generic_link_add_one_symbol (info=0x7fffffffccb0, abfd=0x60280003c640, name=0x6062001092b8 "symbol_01_length_40", '_' <repeats 21 times>, flags=65536, section=0x3c34220 <_bfd_std_section>, value=4, string=0x6062001092b8 "symbol_01_length_40", '_' <repeats 21 times>, copy=0, collect=0, hashp=0x7fffffffca10) at linker.c:1769
#3 in generic_link_add_symbol_list (abfd=0x60280003c640, info=0x7fffffffccb0, symbol_count=16, symbols=0x606200109388, collect=0) at linker.c:1382
#4 in generic_link_add_object_symbols (abfd=0x60280003c640, info=0x7fffffffccb0, collect=0) at linker.c:872
#5 in generic_link_add_symbols (abfd=0x60280003c640, info=0x7fffffffccb0, collect=0) at linker.c:841
#6 in _bfd_generic_link_add_symbols (abfd=0x60280003c640, info=0x7fffffffccb0) at linker.c:789
#7 in bfd_simple_get_relocated_section_contents (abfd=0x60280003c640, sec=0x606200109d20, outbuf=0x6062001056a0 "", symbol_table=0x0) at simple.c:230
and simple_restore_output_info later reads unallocated part of saved_offsets.
READ of size 8 at 0x601c0000c5c0 thread T0
#0 0x1124770 in simple_restore_output_info (.../gdb/gdb+0x1124770)
#1 0x10ecd51 in bfd_map_over_sections (.../gdb/gdb+0x10ecd51)
#2 0x1125150 in bfd_simple_get_relocated_section_contents (.../gdb/gdb+0x1125150)
No regressions on x86_64-fedora20-linux-gnu.
Thanks,
Jan
bfd/
2014-02-16 Jan Kratochvil <jan.kratochvil@redhat.com>
PR binutils/16595
* simple.c (struct saved_offsets): New.
(simple_save_output_info): Use it for ptr.
(simple_restore_output_info): Use it for ptr. Check section_count.
(bfd_simple_get_relocated_section_contents): Use it for saved_offsets.
diff --git a/bfd/simple.c b/bfd/simple.c
index e5a5b58..424d5a0 100644
--- a/bfd/simple.c
+++ b/bfd/simple.c
@@ -101,14 +101,23 @@ struct saved_output_info
asection *section;
};
+struct saved_offsets
+{
+ int section_count;
+ struct saved_output_info *sections;
+};
+
static void
simple_save_output_info (bfd *abfd ATTRIBUTE_UNUSED,
asection *section,
void *ptr)
{
- struct saved_output_info *output_info = (struct saved_output_info *) ptr;
- output_info[section->index].offset = section->output_offset;
- output_info[section->index].section = section->output_section;
+ struct saved_offsets *saved_offsets = (struct saved_offsets *) ptr;
+ struct saved_output_info *output_info;
+
+ output_info = &saved_offsets->sections[section->index];
+ output_info->offset = section->output_offset;
+ output_info->section = section->output_section;
if ((section->flags & SEC_DEBUGGING) != 0
|| section->output_section == NULL)
{
@@ -122,9 +131,15 @@ simple_restore_output_info (bfd *abfd ATTRIBUTE_UNUSED,
asection *section,
void *ptr)
{
- struct saved_output_info *output_info = (struct saved_output_info *) ptr;
- section->output_offset = output_info[section->index].offset;
- section->output_section = output_info[section->index].section;
+ struct saved_offsets *saved_offsets = (struct saved_offsets *) ptr;
+ struct saved_output_info *output_info;
+
+ if (section->index >= saved_offsets->section_count)
+ return;
+
+ output_info = &saved_offsets->sections[section->index];
+ section->output_offset = output_info->offset;
+ section->output_section = output_info->section;
}
/*
@@ -157,7 +172,7 @@ bfd_simple_get_relocated_section_contents (bfd *abfd,
struct bfd_link_callbacks callbacks;
bfd_byte *contents, *data;
int storage_needed;
- void *saved_offsets;
+ struct saved_offsets saved_offsets;
/* Don't apply relocation on executable and shared library. See
PR 4756. */
@@ -215,15 +230,16 @@ bfd_simple_get_relocated_section_contents (bfd *abfd,
section->output_offset to equal section->vma, which we do by setting
section->output_section to point back to section. Save the original
output offset and output section to restore later. */
- saved_offsets = malloc (sizeof (struct saved_output_info)
- * abfd->section_count);
- if (saved_offsets == NULL)
+ saved_offsets.section_count = abfd->section_count;
+ saved_offsets.sections = malloc (sizeof (*saved_offsets.sections)
+ * saved_offsets.section_count);
+ if (saved_offsets.sections == NULL)
{
if (data)
free (data);
return NULL;
}
- bfd_map_over_sections (abfd, simple_save_output_info, saved_offsets);
+ bfd_map_over_sections (abfd, simple_save_output_info, &saved_offsets);
if (symbol_table == NULL)
{
@@ -245,8 +261,8 @@ bfd_simple_get_relocated_section_contents (bfd *abfd,
if (contents == NULL && data != NULL)
free (data);
- bfd_map_over_sections (abfd, simple_restore_output_info, saved_offsets);
- free (saved_offsets);
+ bfd_map_over_sections (abfd, simple_restore_output_info, &saved_offsets);
+ free (saved_offsets.sections);
_bfd_generic_link_hash_table_free (link_info.hash);
return contents;