Bug 22210 - large loop in read_formatted_entries in dwarf2.c in binutils 2.30(HEAD)
Summary: large loop in read_formatted_entries in dwarf2.c in binutils 2.30(HEAD)
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.30
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-09-26 08:09 UTC by skysider
Modified: 2017-09-26 14:01 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
poc of large loop (10.61 KB, application/x-executable)
2017-09-26 08:09 UTC, skysider
Details

Note You need to log in before you can comment on or make changes to this bug.
Description skysider 2017-09-26 08:09:17 UTC
Created attachment 10484 [details]
poc of large loop

I wonder if it's normal or not. When I run "nm: -A -a -l -S -s --special-syms --synthetic --with-symbol-versions hang.elf", it stops for a long time and call realloc persistently.

I look into the problem and find the point, here is the snippet of function read_formatted_entries:

  data_count = _bfd_safe_read_leb128 (abfd, buf, &bytes_read, FALSE, buf_end);
  buf += bytes_read;
  for (datai = 0; datai < data_count; datai++)
    {
      bfd_byte *format = format_header_data;
      struct fileinfo fe;
      
      ......

      if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
	return FALSE;
    }

data_count is unsigned long, and callback is function line_info_add_include_dir_stub, and then I debug it with gdb:

(gdb)ptype data_count
unsigned long
(gdb)p/x data_count
0xfffbfff
(gdb)p/x datai
0x01

I'm not sure if there is lack of verifcation or not, it seems abnormal.
The poc is attached here.
Comment 1 Andreas Schwab 2017-09-26 08:36:23 UTC
The file looks like being corrupted:

$ readelf -p .shstrtab hang.elf 

String dump of section '.shstrtab':
  [     1]  .symtab
  [     9]  .
  [     e]  ab
  [    11]  .shstrtab
  [    1b]  .int�
  [    23]  .note.ABI-tag
  [    31]  .gnu.hash
  [    3b]  .dynsym
  [    43]  .dynstr
  [    4b]  .gnu.version
  [    58]  .gnu.version_r
  [    67]  .rela.dyn
  [    71]  .rela.plt
  [    7b]  .init
  [    81]  .text
  [    87]  .fini
  [    8d]  .rodata
  [    95]  .eh_frame_hdr
  [    a3]  .eh_frame
  [    ad]  .init_array
  [    b9]  .fini_array
  [    c5]  .
  [    c8]  r
  [    ca]  .dynamic
  [    d3]  .got
  [    d8]  .got.plt
  [    e1]  .data
  [    e7]  .bss
  [    ec]  .comment
  [    f5]  .debug_aranges
  [   104]  .debug_info
  [   110]  .debug_abbrev
  [   11e]  .debug_line
  [   12a]  .debug_str
  [   135]  .debug_loc
  [   140]  .debug_ranges
  [   14e]  .debug_macro
Comment 2 skysider 2017-09-26 09:41:06 UTC
My purpose is to test whether nm works well when opening crafted elf file.
Comment 3 Sourceware Commits 2017-09-26 13:40:03 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=30d0157a2ad64e64e5ff9fcc0dbe78a3e682f573

commit 30d0157a2ad64e64e5ff9fcc0dbe78a3e682f573
Author: Nick Clifton <nickc@redhat.com>
Date:   Tue Sep 26 14:37:47 2017 +0100

    Avoid needless resource usage when processing a corrupt DWARF directory or file name table.
    
    	PR 22210
    	* dwarf2.c (read_formatted_entries): Fail early if we know that
    	the loop parsing data entries will overflow the end of the
    	section.
Comment 4 Nick Clifton 2017-09-26 13:42:05 UTC
Hi Skysider,

  Thanks for reporting this problem.  As Andreas explained the current code will handle the corrupt input file correctly, but I also accept your point that it will use up a lot of CPU resources whilst doing so.  So I have checked in a small patch which causes the read_formatted_entries() function to fail before starting the loop, if it knows that the loop cannot possibly terminate successfully.

Cheers
  Nick
Comment 5 Sourceware Commits 2017-09-26 14:01:57 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=33e0a9a056bd23e923b929a4f2ab049ade0b1c32

commit 33e0a9a056bd23e923b929a4f2ab049ade0b1c32
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Sep 26 23:20:06 2017 +0930

    Tidy reading data in read_formatted_entries
    
    Using read_attribute_value accomplishes two things: It checks for
    unexpected formats, and ensures the buffer pointer always increments.
    
    	PR 22210
    	* dwarf2.c (read_formatted_entries): Use read_attribute_value to
    	read data.