From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12181 invoked by alias); 3 Dec 2019 09:39:14 -0000 Mailing-List: contact gdb-testers-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-testers-owner@sourceware.org Received: (qmail 12123 invoked by uid 89); 3 Dec 2019 09:39:14 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-15.1 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: kwanyin.sergiodj.net Received: from kwanyin.sergiodj.net (HELO kwanyin.sergiodj.net) (158.69.185.54) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 03 Dec 2019 09:39:12 +0000 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [binutils-gdb] dwarf2.c: read_abbrevs fail cleanup, and offset checking From: gdb-buildbot@sergiodj.net To: gdb-testers@sourceware.org Message-Id: <019cc8758a68d016db920f96de3273a2824929d1@gdb-build> Date: Tue, 03 Dec 2019 09:39:00 -0000 X-SW-Source: 2019-q4/txt/msg03786.txt.bz2 *** TEST RESULTS FOR COMMIT 019cc8758a68d016db920f96de3273a2824929d1 *** commit 019cc8758a68d016db920f96de3273a2824929d1 Author: Alan Modra AuthorDate: Sat Nov 30 09:12:29 2019 +1030 Commit: Alan Modra CommitDate: Tue Dec 3 16:05:40 2019 +1030 dwarf2.c: read_abbrevs fail cleanup, and offset checking read_section does offset checking, reporting an error on out of bounds. There's no need to duplicate the check in functions calling read_section. Also, I spotted a place where a pointer difference expression was being cast to unsigned int, possibly truncating relevant bits on a 64-bit host. * dwarf2.c (read_indirect_string): Don't duplicate offset check done in read_section. (read_indirect_line_string): Likewise. (read_alt_indirect_string): Likewise. (read_alt_indirect_ref): Likewise. (read_abbrevs): Likewise. Free memory on all failure paths. Use correct unsigned type for pointer difference comparison. diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7765703985..f299ff1593 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2019-12-03 Alan Modra + + * dwarf2.c (read_indirect_string): Don't duplicate offset check + done in read_section. + (read_indirect_line_string): Likewise. + (read_alt_indirect_string): Likewise. + (read_alt_indirect_ref): Likewise. + (read_abbrevs): Likewise. Free memory on all failure paths. + Use correct unsigned type for pointer difference comparison. + 2019-12-03 Alan Modra * dwarf2.c (struct dwarf2_debug): Update comments. Remove sec diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index dd3a2fbe9e..0d5d84ea4c 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -721,8 +721,6 @@ read_indirect_string (struct comp_unit * unit, &stash->dwarf_str_buffer, &stash->dwarf_str_size)) return NULL; - if (offset >= stash->dwarf_str_size) - return NULL; str = (char *) stash->dwarf_str_buffer + offset; if (*str == '\0') return NULL; @@ -760,8 +758,6 @@ read_indirect_line_string (struct comp_unit * unit, &stash->dwarf_line_str_size)) return NULL; - if (offset >= stash->dwarf_line_str_size) - return NULL; str = (char *) stash->dwarf_line_str_buffer + offset; if (*str == '\0') return NULL; @@ -825,8 +821,6 @@ read_alt_indirect_string (struct comp_unit * unit, &stash->alt_dwarf_str_size)) return NULL; - if (offset >= stash->alt_dwarf_str_size) - return NULL; str = (char *) stash->alt_dwarf_str_buffer + offset; if (*str == '\0') return NULL; @@ -874,8 +868,6 @@ read_alt_indirect_ref (struct comp_unit * unit, &stash->alt_dwarf_info_size)) return NULL; - if (offset >= stash->alt_dwarf_info_size) - return NULL; return stash->alt_dwarf_info_buffer + offset; } @@ -963,9 +955,6 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash) &stash->dwarf_abbrev_buffer, &stash->dwarf_abbrev_size)) return NULL; - if (offset >= stash->dwarf_abbrev_size) - return NULL; - amt = sizeof (struct abbrev_info*) * ABBREV_HASH_SIZE; abbrevs = (struct abbrev_info **) bfd_zalloc (abfd, amt); if (abbrevs == NULL) @@ -983,7 +972,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash) amt = sizeof (struct abbrev_info); cur_abbrev = (struct abbrev_info *) bfd_zalloc (abfd, amt); if (cur_abbrev == NULL) - return NULL; + goto fail; /* Read in abbrev header. */ cur_abbrev->number = abbrev_number; @@ -1025,21 +1014,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash) amt *= sizeof (struct attr_abbrev); tmp = (struct attr_abbrev *) bfd_realloc (cur_abbrev->attrs, amt); if (tmp == NULL) - { - size_t i; - - for (i = 0; i < ABBREV_HASH_SIZE; i++) - { - struct abbrev_info *abbrev = abbrevs[i]; - - while (abbrev) - { - free (abbrev->attrs); - abbrev = abbrev->next; - } - } - return NULL; - } + goto fail; cur_abbrev->attrs = tmp; } @@ -1063,7 +1038,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash) already read (which means we are about to read the abbreviations for the next compile unit) or if the end of the abbreviation table is reached. */ - if ((unsigned int) (abbrev_ptr - stash->dwarf_abbrev_buffer) + if ((size_t) (abbrev_ptr - stash->dwarf_abbrev_buffer) >= stash->dwarf_abbrev_size) break; abbrev_number = _bfd_safe_read_leb128 (abfd, abbrev_ptr, @@ -1072,8 +1047,26 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash) if (lookup_abbrev (abbrev_number, abbrevs) != NULL) break; } - return abbrevs; + + fail: + if (abbrevs != NULL) + { + size_t i; + + for (i = 0; i < ABBREV_HASH_SIZE; i++) + { + struct abbrev_info *abbrev = abbrevs[i]; + + while (abbrev) + { + free (abbrev->attrs); + abbrev = abbrev->next; + } + } + free (abbrevs); + } + return NULL; } /* Returns true if the form is one which has a string value. */