From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14551 invoked by alias); 30 Oct 2007 16:11:55 -0000 Received: (qmail 14539 invoked by uid 22791); 30 Oct 2007 16:11:54 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 30 Oct 2007 16:11:52 +0000 Received: (qmail 8203 invoked from network); 30 Oct 2007 16:10:19 -0000 Received: from unknown (HELO digraph.polyomino.org.uk) (joseph@127.0.0.2) by mail.codesourcery.com with ESMTPA; 30 Oct 2007 16:10:19 -0000 Received: from jsm28 (helo=localhost) by digraph.polyomino.org.uk with local-esmtp (Exim 4.63) (envelope-from ) id 1ImtfW-0004QR-Dn for binutils@sourceware.org; Tue, 30 Oct 2007 16:10:18 +0000 Date: Tue, 30 Oct 2007 16:19:00 -0000 From: "Joseph S. Myers" To: binutils@sourceware.org Subject: Patch to detect invalid mergeable string sections Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org X-SW-Source: 2007-10/txt/msg00393.txt.bz2 GCC versions before 4.1.2 could generate object files with invalid mergeable string sections containing unterminated strings. This was fixed by: 2006-06-21 Jakub Jelinek * varasm.c (mergeable_string_section): Check for embedded NULs and NUL termination in the first int_size_in_bytes (TREE_TYPE (decl)) rather than TREE_STRING_LENGTH bytes. When linking such object files, the linker can give internal errors from _bfd_merged_section_offset (or possibly fail in other ways; looking for the end of such a string will run off the end of the section and start reading uninitialized memory). Invalid input should never cause internal errors from the linker; it should give normal non-internal errors to the user diagnosing the invalid input instead. This patch adds a check that the strings found in such sections in input files do not run off the end of their sections. A failure at this point in turn requires two other checks for NULL secinfo to be inserted so later stages in the attempted merging don't dereference a NULL pointer. Tested on i686-pc-linux-gnu (native). OK to commit? bfd: 2007-10-30 Joseph Myers * merge.c (sec_merge_hash_lookup): Add parameter sec_end. Check for unterminated strings. All callers changed. (_bfd_write_merged_section, _bfd_merged_section_offset): Handle NULL secinfo from merge failures. ld/testsuite: 2007-10-30 Joseph Myers * ld-elf/merge3.d, ld-elf/merge3.s: New. Index: bfd/merge.c =================================================================== RCS file: /cvs/src/src/bfd/merge.c,v retrieving revision 1.33 diff -u -r1.33 merge.c --- bfd/merge.c 19 Sep 2007 12:08:34 -0000 1.33 +++ bfd/merge.c 30 Oct 2007 16:00:19 -0000 @@ -133,6 +133,7 @@ static struct sec_merge_hash_entry * sec_merge_hash_lookup (struct sec_merge_hash *table, const char *string, + const unsigned char *sec_end, unsigned int alignment, bfd_boolean create) { register const unsigned char *s; @@ -154,6 +155,12 @@ hash += c + (c << 17); hash ^= hash >> 2; ++len; + if (sec_end && s >= sec_end) + { + (*_bfd_error_handler) + (_("unterminated string in section marked for merging")); + return NULL; + } } hash += len + (len << 17); } @@ -161,6 +168,12 @@ { for (;;) { + if (sec_end && s + table->entsize > sec_end) + { + (*_bfd_error_handler) + (_("unterminated string in section marked for merging")); + return NULL; + } for (i = 0; i < table->entsize; ++i) if (s[i] != '\0') break; @@ -264,7 +277,9 @@ { register struct sec_merge_hash_entry *entry; - entry = sec_merge_hash_lookup (tab, str, alignment, TRUE); + entry = sec_merge_hash_lookup (tab, str, + secinfo->contents + secinfo->sec->size, + alignment, TRUE); if (entry == NULL) return NULL; @@ -779,6 +794,9 @@ secinfo = (struct sec_merge_sec_info *) psecinfo; + if (!secinfo) + return FALSE; + if (secinfo->first_str == NULL) return TRUE; @@ -807,6 +825,9 @@ secinfo = (struct sec_merge_sec_info *) psecinfo; + if (!secinfo) + return 0; + if (offset >= sec->rawsize) { if (offset > sec->rawsize) @@ -849,7 +870,7 @@ { p = secinfo->contents + (offset / sec->entsize) * sec->entsize; } - entry = sec_merge_hash_lookup (secinfo->htab, (char *) p, 0, FALSE); + entry = sec_merge_hash_lookup (secinfo->htab, (char *) p, NULL, 0, FALSE); if (!entry) { if (! secinfo->htab->strings) Index: ld/testsuite/ld-elf/merge3.d =================================================================== RCS file: ld/testsuite/ld-elf/merge3.d diff -N ld/testsuite/ld-elf/merge3.d --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ld/testsuite/ld-elf/merge3.d 30 Oct 2007 16:00:20 -0000 @@ -0,0 +1,3 @@ +#source: merge3.s +#ld: -T merge.ld +#error: unterminated string in section marked for merging Index: ld/testsuite/ld-elf/merge3.s =================================================================== RCS file: ld/testsuite/ld-elf/merge3.s diff -N ld/testsuite/ld-elf/merge3.s --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ld/testsuite/ld-elf/merge3.s 30 Oct 2007 16:00:20 -0000 @@ -0,0 +1,7 @@ + .section .rodata.str,"aMS","progbits",1 +.LC0: + .ascii "abcd" + .text + .global _start +_start: + .long .LC0 -- Joseph S. Myers joseph@codesourcery.com