002-dont-segv-on-initial-instructions-overflow.patch 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. From: Alan Modra <amodra@gmail.com>
  2. Date: Fri, 20 Dec 2013 13:27:52 +0000 (+1030)
  3. Subject: Don't segv on cie.initial_instructions[] overflow.
  4. X-Git-Tag: gdb-7.7-release~148
  5. X-Git-Url: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff_plain;h=99d190fac4d2aab238cfc798dc5c28ab41456882
  6. Don't segv on cie.initial_instructions[] overflow.
  7. Don't attempt to merge CIEs with a larger number of insns than will
  8. fit in the buffer.
  9. * elf-eh-frame.c (cie_eq): Return false when initial_insn_length
  10. is too large.
  11. (cie_compute_hash): Don't exceed bounds of initial_instructions.
  12. (_bfd_elf_parse_eh_frame): Always set initial_insn_length, and
  13. save as much of insns to initial_instructions[] as will fit.
  14. ---
  15. diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
  16. index 832a991..4b6e8ea 100644
  17. --- a/bfd/elf-eh-frame.c
  18. +++ b/bfd/elf-eh-frame.c
  19. @@ -235,6 +235,7 @@ cie_eq (const void *e1, const void *e2)
  20. && c1->lsda_encoding == c2->lsda_encoding
  21. && c1->fde_encoding == c2->fde_encoding
  22. && c1->initial_insn_length == c2->initial_insn_length
  23. + && c1->initial_insn_length <= sizeof (c1->initial_instructions)
  24. && memcmp (c1->initial_instructions,
  25. c2->initial_instructions,
  26. c1->initial_insn_length) == 0)
  27. @@ -254,6 +255,7 @@ static hashval_t
  28. cie_compute_hash (struct cie *c)
  29. {
  30. hashval_t h = 0;
  31. + size_t len;
  32. h = iterative_hash_object (c->length, h);
  33. h = iterative_hash_object (c->version, h);
  34. h = iterative_hash (c->augmentation, strlen (c->augmentation) + 1, h);
  35. @@ -267,7 +269,10 @@ cie_compute_hash (struct cie *c)
  36. h = iterative_hash_object (c->lsda_encoding, h);
  37. h = iterative_hash_object (c->fde_encoding, h);
  38. h = iterative_hash_object (c->initial_insn_length, h);
  39. - h = iterative_hash (c->initial_instructions, c->initial_insn_length, h);
  40. + len = c->initial_insn_length;
  41. + if (len > sizeof (c->initial_instructions))
  42. + len = sizeof (c->initial_instructions);
  43. + h = iterative_hash (c->initial_instructions, len, h);
  44. c->hash = h;
  45. return h;
  46. }
  47. @@ -762,11 +767,10 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
  48. cie->fde_encoding = DW_EH_PE_absptr;
  49. initial_insn_length = end - buf;
  50. - if (initial_insn_length <= sizeof (cie->initial_instructions))
  51. - {
  52. - cie->initial_insn_length = initial_insn_length;
  53. - memcpy (cie->initial_instructions, buf, initial_insn_length);
  54. - }
  55. + cie->initial_insn_length = initial_insn_length;
  56. + memcpy (cie->initial_instructions, buf,
  57. + initial_insn_length <= sizeof (cie->initial_instructions)
  58. + ? initial_insn_length : sizeof (cie->initial_instructions));
  59. insns = buf;
  60. buf += initial_insn_length;
  61. ENSURE_NO_RELOCS (buf);