From a953eec996f2f93914cc78d68d4478a2660432b6 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 30 Apr 2014 17:04:04 +0100 Subject: [PATCH 1/1] Fixes a problem with the BFD library running out of memory because it mistakenly thought that an uncompressed .debug_str section was compressed. * compress.c (bfd_is_section_compressed): When checking the .debug_str section, also check the fifth byte in the section is not part of a string. * binutils-all/debug_str.s: New test. * binutils-all/debug_str.d: New test control file. * binutils-all/compress.exp: Run debug_str test. --- bfd/ChangeLog | 6 ++++++ bfd/compress.c | 10 ++++++++++ binutils/testsuite/ChangeLog | 6 ++++++ binutils/testsuite/binutils-all/compress.exp | 10 ++++++++++ binutils/testsuite/binutils-all/debug_str.d | 9 +++++++++ binutils/testsuite/binutils-all/debug_str.s | 12 ++++++++++++ 6 files changed, 53 insertions(+) create mode 100644 binutils/testsuite/binutils-all/debug_str.d create mode 100644 binutils/testsuite/binutils-all/debug_str.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 4a4d3cf24a..414ebab639 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2014-04-30 Nick Clifton + + * compress.c (bfd_is_section_compressed): When checking the + .debug_str section, also check the fifth byte in the section is + not part of a string. + 2014-04-30 Alan Modra * elf-eh-frame.c (struct cie.personality): Replace val with sym. diff --git a/bfd/compress.c b/bfd/compress.c index 5a289e62e8..20eef95282 100644 --- a/bfd/compress.c +++ b/bfd/compress.c @@ -24,6 +24,7 @@ #ifdef HAVE_ZLIB_H #include #endif +#include "safe-ctype.h" #ifdef HAVE_ZLIB_H static bfd_boolean @@ -303,6 +304,15 @@ bfd_is_section_compressed (bfd *abfd, sec_ptr sec) compressed = (bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12) && CONST_STRNEQ ((char*) compressed_buffer, "ZLIB")); + /* Check for the pathalogical case of a debug string section that + contains the string ZLIB.... as the first entry. We assume that + no uncompressed .debug_str section would ever be big enough to + have the first byte of its (big-endian) size be non-zero. */ + if (compressed + && strcmp (sec->name, ".debug_str") == 0 + && ISPRINT (compressed_buffer[4])) + compressed = FALSE; + /* Restore compress_status. */ sec->compress_status = saved; return compressed; diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog index a308b63821..1231a24b8c 100644 --- a/binutils/testsuite/ChangeLog +++ b/binutils/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2014-04-30 Nick Clifton + + * binutils-all/debug_str.s: New test. + * binutils-all/debug_str.d: New test control file. + * binutils-all/compress.exp: Run debug_str test. + 2014-04-22 Christian Svensson * binutils-all/objcopy.exp: Remove openrisc and or32 support. Add diff --git a/binutils/testsuite/binutils-all/compress.exp b/binutils/testsuite/binutils-all/compress.exp index 570425be11..d74555dc75 100644 --- a/binutils/testsuite/binutils-all/compress.exp +++ b/binutils/testsuite/binutils-all/compress.exp @@ -173,3 +173,13 @@ if ![string match "" $got] then { fail "objcopy ($testname)" } } + +if ![is_remote host] { + set tempfile tmpdir/debug_str.o + set copyfile tmpdir/debug_str.copy +} else { + set tempfile [remote_download host tmpdir/debug_str.o] + set copyfile debug_str.copy +} + +run_dump_test "debug_str" diff --git a/binutils/testsuite/binutils-all/debug_str.d b/binutils/testsuite/binutils-all/debug_str.d new file mode 100644 index 0000000000..eda1db14b3 --- /dev/null +++ b/binutils/testsuite/binutils-all/debug_str.d @@ -0,0 +1,9 @@ +#PROG: objcopy +#source: debug_str.s +#objdump: -h +#name: Uncompressed .debug_str section starting with ZLIB + +.*ebug_str.copy.o: file format .* +#... + . .debug_str 0+01. 0+0 0+0 0+0.. 2..0 +#... diff --git a/binutils/testsuite/binutils-all/debug_str.s b/binutils/testsuite/binutils-all/debug_str.s new file mode 100644 index 0000000000..485d0cc318 --- /dev/null +++ b/binutils/testsuite/binutils-all/debug_str.s @@ -0,0 +1,12 @@ +/* This test is derived from a C source file which, when compiled by gcc + with debugging enabled, managed to create a .debug_str section whose + first string was ZLIB_VER_SUBVERSION. The code in bfd/compress.c + used to just check for the characters "ZLIB" at the start of a section + and then assume that the section was compressed. This meant that the BFD + library then processed the next 8 bytes as if they were the size of the + decompressed version of the section. Naturally with this test case the + resulting size was gigantic and consequently the library quickly ran out + of memory. */ + + .section .debug_str,"MS",@progbits,1 + .string "ZLIB_VER_SUBREVISION 0" -- 2.34.1