| From: Alan Modra <amodra@gmail.com> |
| Date: Fri, 20 Dec 2013 13:27:52 +0000 (+1030) |
| Subject: Don't segv on cie.initial_instructions[] overflow. |
| X-Git-Tag: gdb-7.7-release~148 |
| X-Git-Url: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff_plain;h=99d190fac4d2aab238cfc798dc5c28ab41456882 |
| |
| Don't segv on cie.initial_instructions[] overflow. |
| |
| Don't attempt to merge CIEs with a larger number of insns than will |
| fit in the buffer. |
| |
| * elf-eh-frame.c (cie_eq): Return false when initial_insn_length |
| is too large. |
| (cie_compute_hash): Don't exceed bounds of initial_instructions. |
| (_bfd_elf_parse_eh_frame): Always set initial_insn_length, and |
| save as much of insns to initial_instructions[] as will fit. |
| --- |
| |
| diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c |
| index 832a991..4b6e8ea 100644 |
| --- a/bfd/elf-eh-frame.c |
| +++ b/bfd/elf-eh-frame.c |
| @@ -235,6 +235,7 @@ cie_eq (const void *e1, const void *e2) |
| && c1->lsda_encoding == c2->lsda_encoding |
| && c1->fde_encoding == c2->fde_encoding |
| && c1->initial_insn_length == c2->initial_insn_length |
| + && c1->initial_insn_length <= sizeof (c1->initial_instructions) |
| && memcmp (c1->initial_instructions, |
| c2->initial_instructions, |
| c1->initial_insn_length) == 0) |
| @@ -254,6 +255,7 @@ static hashval_t |
| cie_compute_hash (struct cie *c) |
| { |
| hashval_t h = 0; |
| + size_t len; |
| h = iterative_hash_object (c->length, h); |
| h = iterative_hash_object (c->version, h); |
| h = iterative_hash (c->augmentation, strlen (c->augmentation) + 1, h); |
| @@ -267,7 +269,10 @@ cie_compute_hash (struct cie *c) |
| h = iterative_hash_object (c->lsda_encoding, h); |
| h = iterative_hash_object (c->fde_encoding, h); |
| h = iterative_hash_object (c->initial_insn_length, h); |
| - h = iterative_hash (c->initial_instructions, c->initial_insn_length, h); |
| + len = c->initial_insn_length; |
| + if (len > sizeof (c->initial_instructions)) |
| + len = sizeof (c->initial_instructions); |
| + h = iterative_hash (c->initial_instructions, len, h); |
| c->hash = h; |
| return h; |
| } |
| @@ -762,11 +767,10 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info, |
| cie->fde_encoding = DW_EH_PE_absptr; |
| |
| initial_insn_length = end - buf; |
| - if (initial_insn_length <= sizeof (cie->initial_instructions)) |
| - { |
| - cie->initial_insn_length = initial_insn_length; |
| - memcpy (cie->initial_instructions, buf, initial_insn_length); |
| - } |
| + cie->initial_insn_length = initial_insn_length; |
| + memcpy (cie->initial_instructions, buf, |
| + initial_insn_length <= sizeof (cie->initial_instructions) |
| + ? initial_insn_length : sizeof (cie->initial_instructions)); |
| insns = buf; |
| buf += initial_insn_length; |
| ENSURE_NO_RELOCS (buf); |