From 5c1c468d0eddd0fda1ec8c5f33888657f94e3266 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 26 Sep 2017 12:14:42 +0100 Subject: [PATCH] Fix address violations when parsing a corrupt DWARF linenumber table. PR 22154 * dwarf.c (get_line_filename_and_dirname): Add extra checks for buffer overruns. --- binutils/ChangeLog | 6 ++++++ binutils/dwarf.c | 21 ++++++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 80fff9ccd14..dc4faf553f0 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2017-09-26 Nick Clifton + + PR 22154 + * dwarf.c (get_line_filename_and_dirname): Add extra checks for + buffer overruns. + 2017-09-26 Nick Clifton * README-how-to-make-a-release: New file. diff --git a/binutils/dwarf.c b/binutils/dwarf.c index d4156e480ad..edc65aa39aa 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -4742,13 +4742,21 @@ get_line_filename_and_dirname (dwarf_vma line_offset, return NULL; hdrptr += opcode_base - 1; + if (hdrptr >= end) + return NULL; + dirtable = hdrptr; /* Skip over dirname table. */ while (*hdrptr != '\0') - hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1; + { + hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1; + if (hdrptr >= end) + return NULL; + } hdrptr++; /* Skip the NUL at the end of the table. */ + /* Now skip over preceding filename table entries. */ - for (; *hdrptr != '\0' && fileidx > 1; fileidx--) + for (; hdrptr < end && *hdrptr != '\0' && fileidx > 1; fileidx--) { hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1; read_uleb128 (hdrptr, &bytes_read, end); @@ -4758,16 +4766,19 @@ get_line_filename_and_dirname (dwarf_vma line_offset, read_uleb128 (hdrptr, &bytes_read, end); hdrptr += bytes_read; } - if (hdrptr == end || *hdrptr == '\0') + if (hdrptr >= end || *hdrptr == '\0') return NULL; + file_name = hdrptr; hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1; + if (hdrptr >= end) + return NULL; diridx = read_uleb128 (hdrptr, &bytes_read, end); if (diridx == 0) return file_name; - for (; *dirtable != '\0' && diridx > 1; diridx--) + for (; dirtable < end && *dirtable != '\0' && diridx > 1; diridx--) dirtable += strnlen ((char *) dirtable, end - dirtable) + 1; - if (*dirtable == '\0') + if (dirtable >= end || *dirtable == '\0') return NULL; *dir_name = dirtable; return file_name; -- 2.30.2