Summary: | Lack of DW_LNE_end_sequence causes "infinite" loop | ||
---|---|---|---|
Product: | binutils | Reporter: | skysider <luanjunchao> |
Component: | binutils | Assignee: | Alan Modra <amodra> |
Status: | RESOLVED FIXED | ||
Severity: | normal | ||
Priority: | P2 | ||
Version: | 2.30 | ||
Target Milestone: | 2.30 | ||
Host: | Target: | ||
Build: | Last reconfirmed: | 2017-09-26 00:00:00 | |
Attachments: | poc of integer overflow |
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. Fixed |
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.