diff options
Diffstat (limited to 'debian/patches/pr21438.diff')
-rw-r--r-- | debian/patches/pr21438.diff | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/debian/patches/pr21438.diff b/debian/patches/pr21438.diff new file mode 100644 index 0000000..97886b2 --- /dev/null +++ b/debian/patches/pr21438.diff @@ -0,0 +1,125 @@ +From d949ff5607b9f595e0eed2ff15fbe5eb84eb3a34 Mon Sep 17 00:00:00 2001 +From: Nick Clifton <nickc@redhat.com> +Date: Fri, 28 Apr 2017 10:28:04 +0100 +Subject: [PATCH] Fix heap-buffer overflow bugs caused when dumping debug + information from a corrupt binary. + + PR binutils/21438 + * dwarf.c (process_extended_line_op): Do not assume that the + string extracted from the section is NUL terminated. + (fetch_indirect_string): If the string retrieved from the section + is not NUL terminated, return an error message. + (fetch_indirect_line_string): Likewise. + (fetch_indexed_string): Likewise. +--- + binutils/ChangeLog | 10 +++++++++ + binutils/dwarf.c | 66 +++++++++++++++++++++++++++++++++++++++++------------- + 2 files changed, 60 insertions(+), 16 deletions(-) + +Index: b/binutils/dwarf.c +=================================================================== +--- a/binutils/dwarf.c ++++ b/binutils/dwarf.c +@@ -472,15 +472,20 @@ process_extended_line_op (unsigned char + printf (_(" Entry\tDir\tTime\tSize\tName\n")); + printf (" %d\t", ++state_machine_regs.last_file_entry); + +- name = data; +- data += strnlen ((char *) data, end - data) + 1; +- printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); +- data += bytes_read; +- printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); +- data += bytes_read; +- printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); +- data += bytes_read; +- printf ("%s\n\n", name); ++ { ++ size_t l; ++ ++ name = data; ++ l = strnlen ((char *) data, end - data); ++ data += len + 1; ++ printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); ++ data += bytes_read; ++ printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); ++ data += bytes_read; ++ printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); ++ data += bytes_read; ++ printf ("%.*s\n\n", (int) l, name); ++ } + + if (((unsigned int) (data - orig_data) != len) || data == end) + warn (_("DW_LNE_define_file: Bad opcode length\n")); +@@ -597,18 +602,28 @@ static const unsigned char * + fetch_indirect_string (dwarf_vma offset) + { + struct dwarf_section *section = &debug_displays [str].section; ++ const unsigned char * ret; + + if (section->start == NULL) + return (const unsigned char *) _("<no .debug_str section>"); + +- if (offset > section->size) ++ if (offset >= section->size) + { + warn (_("DW_FORM_strp offset too big: %s\n"), + dwarf_vmatoa ("x", offset)); + return (const unsigned char *) _("<offset is too big>"); + } + +- return (const unsigned char *) section->start + offset; ++ ret = section->start + offset; ++ /* Unfortunately we cannot rely upon the .debug_str section ending with a ++ NUL byte. Since our caller is expecting to receive a well formed C ++ string we test for the lack of a terminating byte here. */ ++ if (strnlen ((const char *) ret, section->size - offset) ++ == section->size - offset) ++ ret = (const unsigned char *) ++ _("<no NUL byte at end of .debug_str section>"); ++ ++ return ret; + } + + static const char * +@@ -621,6 +636,7 @@ fetch_indexed_string (dwarf_vma idx, str + struct dwarf_section *str_section = &debug_displays [str_sec_idx].section; + dwarf_vma index_offset = idx * offset_size; + dwarf_vma str_offset; ++ const char * ret; + + if (index_section->start == NULL) + return (dwo ? _("<no .debug_str_offsets.dwo section>") +@@ -628,7 +644,7 @@ fetch_indexed_string (dwarf_vma idx, str + + if (this_set != NULL) + index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS]; +- if (index_offset > index_section->size) ++ if (index_offset >= index_section->size) + { + warn (_("DW_FORM_GNU_str_index offset too big: %s\n"), + dwarf_vmatoa ("x", index_offset)); +@@ -641,14 +657,22 @@ fetch_indexed_string (dwarf_vma idx, str + + str_offset = byte_get (index_section->start + index_offset, offset_size); + str_offset -= str_section->address; +- if (str_offset > str_section->size) ++ if (str_offset >= str_section->size) + { + warn (_("DW_FORM_GNU_str_index indirect offset too big: %s\n"), + dwarf_vmatoa ("x", str_offset)); + return _("<indirect index offset is too big>"); + } + +- return (const char *) str_section->start + str_offset; ++ ret = (const char *) str_section->start + str_offset; ++ /* Unfortunately we cannot rely upon str_section ending with a NUL byte. ++ Since our caller is expecting to receive a well formed C string we test ++ for the lack of a terminating byte here. */ ++ if (strnlen (ret, str_section->size - str_offset) ++ == str_section->size - str_offset) ++ ret = (const char *) _("<no NUL byte at end of section>"); ++ ++ return ret; + } + + static const char * |