Bug 15206 - dwarf process_debug_info invalid accesses
Summary: dwarf process_debug_info invalid accesses
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.23
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-02-27 02:52 UTC by Paul Marinescu
Modified: 2013-03-26 23:55 UTC (History)
1 user (show)

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


Attachments
valgrind readelf -wi readelfdbginfo.o (1.26 KB, application/octet-stream)
2013-02-27 02:52 UTC, Paul Marinescu
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Marinescu 2013-02-27 02:52:30 UTC
Created attachment 6903 [details]
valgrind readelf -wi readelfdbginfo.o

Hello,
I'm using binutils 2.23.52.20130219 on a 64bit Fedora 16 and I see various invalid memory accesses in process_debug_info under valgrind when providing a particular file (attached).

In this case, the accesses are just several bytes after valid objects, but given a slightly different input, they might crash readelf.



==23140== Memcheck, a memory error detector
==23140== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==23140== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==23140== Command: /home/pdm/binutils/binutils/readelf -wi readelfdbginfo.o
==23140== 
Contents of the .debug_info section:

  Compilation Unit @ offset 0x0:
   Length:        0xd8 (32-bit)
   Version:       4
   Abbrev Offset: 0x0
   Pointer Size:  8
 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <c>   DW_AT_producer    : (indirect string, offset: 0x37): GNU C 4.6.3 20120306 (Red Hat 4.6.3-2) -fpreprocessed -mtune=generic -march=x86-64 -g	
    <10>   DW_AT_language    : 1	(ANSI C)
    <11>   DW_AT_name        : (indirect string, offset: 0x8d): /data/benchmarking/patchtesting/binutils-test/l-287/binutils/testsuite/binutils-all/testprog.c	
    <15>   DW_AT_low_pc      : 0x0	
    <1d>   DW_AT_high_pc     : 0x7b	
    <25>   DW_AT_stmt_list   : 0x0	
 <1><29>: Abbrev Number: 2 (DW_TAG_subprogram)
    <2a>   DW_AT_external    : 1	
    <2a>   DW_AT_name        : fn	
    <2d>   DW_AT_decl_file   : 1	
    <2e>   DW_AT_decl_line   : 12	
    <2f>   DW_AT_prototyped  : 1	
    <2f>   DW_AT_type        : <0x45>	
    <33>   DW_AT_low_pc      : 0x0	
    <3b>   DW_AT_high_pc     : 0xb	
    <43>   DW_AT_frame_base  : 1 byte block: 9c 	(DW_OP_call_frame_cfa)
    <45>   DW_AT_GNU_all_call_sites: 1	
 <1><45>: Abbrev Number: 3 (DW_TAG_base_type)
    <46>   DW_AT_byte_size   : 4	
    <47>   DW_AT_encoding    : 5	(signed)
    <48>   DW_AT_name        : int	
 <1><4c>: Abbrev Number: 4 (DW_TAG_subprogram)
    <4d>   DW_AT_external    : 1	
    <4d>   DW_AT_name        : (indirect string, offset: 0x2b): main	
    <51>   DW_AT_decl_file   : 1	
    <52>   DW_AT_decl_line   : 18	
    <53>   DW_AT_prototyped  : 1	
    <53>   DW_AT_type        : <0x45>	
    <57>   DW_AT_low_pc      : 0xb	
    <5f>   DW_AT_high_pc     : 0x7b	
    <67>   DW_AT_frame_base  : 1 byte block: 9c 	(DW_OP_call_frame_cfa)
    <69>   DW_AT_GNU_all_tail_call_sites: 1	
 <1><69>: Abbrev Number: 5 (DW_TAG_variable)
    <6a>   DW_AT_name        : (indirect string, offset: 0x12): local	
    <6e>   DW_AT_decl_file   : 1	
    <6f>   DW_AT_decl_line   : 8	
    <70>   DW_AT_type        : <0x45>	
    <74>   DW_AT_location    : 9 byte block: 3 4 0 0 0 0 0 0 0 	(DW_OP_addr: 4)
 <1><7e>: Abbrev Number: 6 (DW_TAG_array_type)
    <7f>   DW_AT_type        : <0x95>	
    <83>   DW_AT_sibling     : <0x8e>	
 <2><87>: Abbrev Number: 7 (DW_TAG_subrange_type)
    <88>   DW_AT_type        : <0x8e>	
    <8c>   DW_AT_upper_bound : 6	
 <2><8d>: Abbrev Number: 0
 <1><8e>: Abbrev Number: 8 (DW_TAG_base_type)
    <8f>   DW_AT_byte_size   : 8	
    <90>   DW_AT_encoding    : 7	(unsigned)
    <91>   DW_AT_name        : (indirect string, offset: 0x0): long unsigned int	
 <1><95>: Abbrev Number: 8 (DW_TAG_base_type)
    <96>   DW_AT_byte_size   : 1	
    <97>   DW_AT_encoding    : 6	(signed char)
    <98>   DW_AT_name        : (indirect string, offset: 0x18): char	
 <1><9c>: Abbrev Number: 5 (DW_TAG_variable)
    <9d>   DW_AT_name        : (indirect string, offset: 0x1d): string	
    <a1>   DW_AT_decl_file   : 1	
    <a2>   DW_AT_decl_line   : 9	
    <a3>   DW_AT_type        : <0x7e>	
    <a7>   DW_AT_location    : 9 byte block: 3 8 0 0 0 0 0 0 0 	(DW_OP_addr: 8)
 <1><b1>: Abbrev Number: 9 (DW_TAG_variable)
    <b2>   DW_AT_name        : (indirect string, offset: 0x24): common	
    <b6>   DW_AT_decl_file   : 1	
    <b7>   DW_AT_decl_line   : 6	
    <b8>   DW_AT_type        : <0x45>	
    <bc>   DW_AT_external    : 1	
    <bc>   DW_AT_location    : 9 byte block: 3 4 0 0 0 0 0 0 0 	(DW_OP_addr: 4)
 <1><c6>: Abbrev Number: 0
 <0><c7>: Abbrev Number: 0
readelf: Warning: Bogus end-of-siblings marker detected at offset c7 in .debug_info section
 <-1><c8>: Abbrev Number: 0
readelf: Warning: Bogus end-of-siblings marker detected at offset c8 in .debug_info section
 <-2><c9>: Abbrev Number: 0
readelf: Warning: Bogus end-of-siblings marker detected at offset c9 in .debug_info section
readelf: Warning: Further warnings about bogus end-of-sibling markers suppressed
 <-3><ca>: Abbrev Number: 0
 <-4><cb>: Abbrev Number: 1 (DW_TAG_compile_unit)
readelf: Warning: DW_FORM_strp offset too big: 4507
    <cc>   DW_AT_producer    : (indirect string, offset: 0x4507): <offset is too big>	
    <d0>   DW_AT_language    : 0	(Unknown: 0)
readelf: Warning: DW_FORM_strp offset too big: 309
    <d1>   DW_AT_name        : (indirect string, offset: 0x309): <offset is too big>	
    <d5>   DW_AT_low_pc      : 0x0	
==23140== Invalid read of size 1
==23140==    at 0x42EB80: byte_get_little_endian (elfcomm.c:150)
==23140==    by 0x4278A8: read_and_display_attr_value (dwarf.c:1295)
==23140==    by 0x4295EB: process_debug_info (dwarf.c:1911)
==23140==    by 0x41D423: process_section_contents (readelf.c:10985)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140==  Address 0x4c28dfe is 1 bytes after a block of size 221 alloc'd
==23140==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==23140==    by 0x402C2C: get_data (readelf.c:325)
==23140==    by 0x4133E8: load_specific_debug_section (readelf.c:10869)
==23140==    by 0x41D217: process_section_contents (readelf.c:10978)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140== 
==23140== Invalid read of size 1
==23140==    at 0x42EB84: byte_get_little_endian (elfcomm.c:151)
==23140==    by 0x4278A8: read_and_display_attr_value (dwarf.c:1295)
==23140==    by 0x4295EB: process_debug_info (dwarf.c:1911)
==23140==    by 0x41D423: process_section_contents (readelf.c:10985)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140==  Address 0x4c28dff is 2 bytes after a block of size 221 alloc'd
==23140==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==23140==    by 0x402C2C: get_data (readelf.c:325)
==23140==    by 0x4133E8: load_specific_debug_section (readelf.c:10869)
==23140==    by 0x41D217: process_section_contents (readelf.c:10978)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140== 
==23140== Invalid read of size 1
==23140==    at 0x42EB94: byte_get_little_endian (elfcomm.c:149)
==23140==    by 0x4278A8: read_and_display_attr_value (dwarf.c:1295)
==23140==    by 0x4295EB: process_debug_info (dwarf.c:1911)
==23140==    by 0x41D423: process_section_contents (readelf.c:10985)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140==  Address 0x4c28dfd is 0 bytes after a block of size 221 alloc'd
==23140==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==23140==    by 0x402C2C: get_data (readelf.c:325)
==23140==    by 0x4133E8: load_specific_debug_section (readelf.c:10869)
==23140==    by 0x41D217: process_section_contents (readelf.c:10978)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140== 
==23140== Invalid read of size 1
==23140==    at 0x42EB9A: byte_get_little_endian (elfcomm.c:152)
==23140==    by 0x4278A8: read_and_display_attr_value (dwarf.c:1295)
==23140==    by 0x4295EB: process_debug_info (dwarf.c:1911)
==23140==    by 0x41D423: process_section_contents (readelf.c:10985)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140==  Address 0x4c28e00 is 3 bytes after a block of size 221 alloc'd
==23140==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==23140==    by 0x402C2C: get_data (readelf.c:325)
==23140==    by 0x4133E8: load_specific_debug_section (readelf.c:10869)
==23140==    by 0x41D217: process_section_contents (readelf.c:10978)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140== 
==23140== Invalid read of size 1
==23140==    at 0x42EBA5: byte_get_little_endian (elfcomm.c:153)
==23140==    by 0x4278A8: read_and_display_attr_value (dwarf.c:1295)
==23140==    by 0x4295EB: process_debug_info (dwarf.c:1911)
==23140==    by 0x41D423: process_section_contents (readelf.c:10985)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140==  Address 0x4c28e01 is 4 bytes after a block of size 221 alloc'd
==23140==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==23140==    by 0x402C2C: get_data (readelf.c:325)
==23140==    by 0x4133E8: load_specific_debug_section (readelf.c:10869)
==23140==    by 0x41D217: process_section_contents (readelf.c:10978)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140== 
==23140== Invalid read of size 1
==23140==    at 0x42EBB0: byte_get_little_endian (elfcomm.c:154)
==23140==    by 0x4278A8: read_and_display_attr_value (dwarf.c:1295)
==23140==    by 0x4295EB: process_debug_info (dwarf.c:1911)
==23140==    by 0x41D423: process_section_contents (readelf.c:10985)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140==  Address 0x4c28e02 is 5 bytes after a block of size 221 alloc'd
==23140==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==23140==    by 0x402C2C: get_data (readelf.c:325)
==23140==    by 0x4133E8: load_specific_debug_section (readelf.c:10869)
==23140==    by 0x41D217: process_section_contents (readelf.c:10978)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140== 
==23140== Invalid read of size 1
==23140==    at 0x42EBBB: byte_get_little_endian (elfcomm.c:155)
==23140==    by 0x4278A8: read_and_display_attr_value (dwarf.c:1295)
==23140==    by 0x4295EB: process_debug_info (dwarf.c:1911)
==23140==    by 0x41D423: process_section_contents (readelf.c:10985)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140==  Address 0x4c28e03 is 6 bytes after a block of size 221 alloc'd
==23140==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==23140==    by 0x402C2C: get_data (readelf.c:325)
==23140==    by 0x4133E8: load_specific_debug_section (readelf.c:10869)
==23140==    by 0x41D217: process_section_contents (readelf.c:10978)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140== 
==23140== Invalid read of size 1
==23140==    at 0x42EBC6: byte_get_little_endian (elfcomm.c:156)
==23140==    by 0x4278A8: read_and_display_attr_value (dwarf.c:1295)
==23140==    by 0x4295EB: process_debug_info (dwarf.c:1911)
==23140==    by 0x41D423: process_section_contents (readelf.c:10985)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140==  Address 0x4c28e04 is 7 bytes after a block of size 221 alloc'd
==23140==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==23140==    by 0x402C2C: get_data (readelf.c:325)
==23140==    by 0x4133E8: load_specific_debug_section (readelf.c:10869)
==23140==    by 0x41D217: process_section_contents (readelf.c:10978)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140== 
    <dd>   DW_AT_high_pc     : 0x0	
==23140== Invalid read of size 1
==23140==    at 0x42EC10: byte_get_little_endian (elfcomm.c:143)
==23140==    by 0x427AB4: read_and_display_attr_value (dwarf.c:1303)
==23140==    by 0x4295EB: process_debug_info (dwarf.c:1911)
==23140==    by 0x41D423: process_section_contents (readelf.c:10985)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140==  Address 0x4c28e06 is 9 bytes after a block of size 221 alloc'd
==23140==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==23140==    by 0x402C2C: get_data (readelf.c:325)
==23140==    by 0x4133E8: load_specific_debug_section (readelf.c:10869)
==23140==    by 0x41D217: process_section_contents (readelf.c:10978)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140== 
==23140== Invalid read of size 1
==23140==    at 0x42EC14: byte_get_little_endian (elfcomm.c:144)
==23140==    by 0x427AB4: read_and_display_attr_value (dwarf.c:1303)
==23140==    by 0x4295EB: process_debug_info (dwarf.c:1911)
==23140==    by 0x41D423: process_section_contents (readelf.c:10985)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140==  Address 0x4c28e07 is 10 bytes after a block of size 221 alloc'd
==23140==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==23140==    by 0x402C2C: get_data (readelf.c:325)
==23140==    by 0x4133E8: load_specific_debug_section (readelf.c:10869)
==23140==    by 0x41D217: process_section_contents (readelf.c:10978)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140== 
==23140== Invalid read of size 1
==23140==    at 0x42EC24: byte_get_little_endian (elfcomm.c:142)
==23140==    by 0x427AB4: read_and_display_attr_value (dwarf.c:1303)
==23140==    by 0x4295EB: process_debug_info (dwarf.c:1911)
==23140==    by 0x41D423: process_section_contents (readelf.c:10985)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140==  Address 0x4c28e05 is 8 bytes after a block of size 221 alloc'd
==23140==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==23140==    by 0x402C2C: get_data (readelf.c:325)
==23140==    by 0x4133E8: load_specific_debug_section (readelf.c:10869)
==23140==    by 0x41D217: process_section_contents (readelf.c:10978)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140== 
==23140== Invalid read of size 1
==23140==    at 0x42EC2A: byte_get_little_endian (elfcomm.c:145)
==23140==    by 0x427AB4: read_and_display_attr_value (dwarf.c:1303)
==23140==    by 0x4295EB: process_debug_info (dwarf.c:1911)
==23140==    by 0x41D423: process_section_contents (readelf.c:10985)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140==  Address 0x4c28e08 is 11 bytes after a block of size 221 alloc'd
==23140==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==23140==    by 0x402C2C: get_data (readelf.c:325)
==23140==    by 0x4133E8: load_specific_debug_section (readelf.c:10869)
==23140==    by 0x41D217: process_section_contents (readelf.c:10978)
==23140==    by 0x41EB11: process_object (readelf.c:13707)
==23140==    by 0x420E9B: main (readelf.c:14078)
==23140== 
    <e5>   DW_AT_stmt_list   : 0x0	

==23140== 
==23140== HEAP SUMMARY:
==23140==     in use at exit: 0 bytes in 0 blocks
==23140==   total heap usage: 198 allocs, 198 frees, 23,133 bytes allocated
==23140== 
==23140== All heap blocks were freed -- no leaks are possible
==23140== 
==23140== For counts of detected and suppressed errors, rerun with: -v
==23140== ERROR SUMMARY: 12 errors from 12 contexts (suppressed: 2 from 2)
Comment 1 Nick Clifton 2013-03-26 22:54:51 UTC
Hi Paul,

  I have checked in a patch to fix this problem.  (Unfortunately I used the wrong PR number - 15205 - in the changelog entry, so the auto-comment from the CVS system went there by mistake).

  The patch is fairly extensive but there are still plenty of other possible buffer read overruns that could be triggered by badly formatted binary files, so please feel free to file new PRs if you encounter any.

Cheers
  Nick
Comment 2 Sourceware Commits 2013-03-26 23:55:56 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	amodra@sourceware.org	2013-03-26 23:55:55

Modified files:
	binutils       : ChangeLog dwarf.c 

Log message:
	PR binutils/15206
	* dwarf.c (read_and_display_attr_value): Cast format '*' arg to int.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/ChangeLog.diff?cvsroot=src&r1=1.2005&r2=1.2006
http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/dwarf.c.diff?cvsroot=src&r1=1.127&r2=1.128