diff options
author | Alan Modra <amodra@gmail.com> | 2013-12-20 23:57:52 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2013-12-21 00:08:34 +1030 |
commit | 99d190fac4d2aab238cfc798dc5c28ab41456882 (patch) | |
tree | e05cdd046418c9f609282c8997528d923d7caa10 /bfd/elf-eh-frame.c | |
parent | 21986715b1e238269e919f7d7c85b134a9e18b17 (diff) | |
download | gdb-99d190fac4d2aab238cfc798dc5c28ab41456882.zip gdb-99d190fac4d2aab238cfc798dc5c28ab41456882.tar.gz gdb-99d190fac4d2aab238cfc798dc5c28ab41456882.tar.bz2 |
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.
Diffstat (limited to 'bfd/elf-eh-frame.c')
-rw-r--r-- | bfd/elf-eh-frame.c | 16 |
1 files changed, 10 insertions, 6 deletions
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); |