Bug 22204 - Lack of DW_LNE_end_sequence causes "infinite" loop
Summary: Lack of DW_LNE_end_sequence causes "infinite" loop
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.30 (HEAD)
: P2 normal
Target Milestone: 2.30
Assignee: Alan Modra
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-09-25 13:29 UTC by skysider
Modified: 2017-09-26 00:15 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed: 2017-09-26 00:00:00


Attachments
poc of integer overflow (6.09 KB, application/x-executable)
2017-09-25 13:29 UTC, skysider
Details

Note You need to log in before you can comment on or make changes to this bug.
Description skysider 2017-09-25 13:29:00 UTC
Created attachment 10477 [details]
poc of integer overflow

When I run "nm-new -a -A -D -l -n -P -r -S --size-sort --special-syms --synthetic --with-symbol-versions integer_overflow.elf", it just hangs there and lasts for long time. And When I run ltrace with above command, I find that it call malloc persistly.

And then I debug it with gdb, I finall find the reason in function decode_line_info. Here is the snippet of it:

 /* Decode the table.  */
      while (! end_sequence)
	{
	  op_code = read_1_byte (abfd, line_ptr, line_end);
	  line_ptr += 1;

	  if (op_code >= lh.opcode_base)
	    {
	      /* Special operand.  */
	      adj_opcode = op_code - lh.opcode_base;
	      if (lh.line_range == 0)
		goto line_fail;
	      if (lh.maximum_ops_per_insn == 1)
		address += (adj_opcode / lh.line_range
			    * lh.minimum_instruction_length);
	      else
		{
		  address += ((op_index + adj_opcode / lh.line_range)
			      / lh.maximum_ops_per_insn
			      * lh.minimum_instruction_length);
		  op_index = ((op_index + adj_opcode / lh.line_range)
			      % lh.maximum_ops_per_insn);
		}
2294:	      line += lh.line_base + (adj_opcode % lh.line_range);
	      /* Append row to matrix using current values.  */
	      if (!add_line_info (table, address, op_index, filename,
				  line, column, discriminator, 0))
		goto line_fail;
	      discriminator = 0;
	      if (address < low_pc)
		low_pc = address;
	      if (address > high_pc)
		high_pc = address;
	    }


When I debug the process, the lh.line_base=-5 (int type), while the line is declared a unsigned int with initial value 0, when it meets a specific condition, it just traps in the while loop.

The poc is attached.
Comment 1 cvs-commit@gcc.gnu.org 2017-09-26 00:14:48 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

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

commit e338894dc2e603683bed2172e8e9f25b29051005
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Sep 26 09:32:18 2017 +0930

    PR22204, Lack of DW_LNE_end_sequence causes "infinite" loop
    
    	PR 22204
    	* dwarf2.c (decode_line_info): Ensure line_ptr stays within
    	bounds in inner loop.
Comment 2 Alan Modra 2017-09-26 00:15:41 UTC
Fixed