This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR gold/18695


Hi,

is this patch ok?

2015-08-26  Andrew Senkevich  <andrew.senkevich@intel.com>

        PR gold/18695
        * x86_64.cc: Overflow checks added.

diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 007af1d..2d0712f 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -3320,6 +3320,32 @@ Target_x86_64<size>::do_finalize_sections(
     }
 }

+template<int size, int valsize>
+class x86_64_overflow_check
+{
+public:
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+
+  static inline bool
+  has_overflow_signed(Address value)
+  {
+    // limit = 1 << (valsize - 1) without shift count exceeding size of type
+    Address limit = static_cast<Address>(1) << ((valsize - 1) >> 1);
+    limit <<= ((valsize - 1) >> 1);
+    limit <<= ((valsize - 1) - 2 * ((valsize - 1) >> 1));
+    return value + limit > (limit << 1) - 1;
+  }
+
+  static inline bool
+  has_overflow_unsigned(Address value)
+  {
+    Address limit = static_cast<Address>(1) << ((valsize - 1) >> 1);
+    limit <<= ((valsize - 1) >> 1);
+    limit <<= ((valsize - 1) - 2 * ((valsize - 1) >> 1));
+    return value > (limit << 1) - 1;
+  }
+};
+
 // Perform a relocation.

 template<int size>
@@ -3431,18 +3457,25 @@ Target_x86_64<size>::Relocate::relocate(
       break;

     case elfcpp::R_X86_64_32:
-      // FIXME: we need to verify that value + addend fits into 32 bits:
-      //    uint64_t x = value + addend;
-      //    x == static_cast<uint64_t>(static_cast<uint32_t>(x))
-      // Likewise for other <=32-bit relocations (but see R_X86_64_32S).
-      Relocate_functions<size, false>::rela32(view, object, psymval, addend);
+      {
+ Relocate_functions<size, false>::rela32(view, object, psymval, addend);
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
+ value = psymval->value(object, addend) + addend;
+ if (x86_64_overflow_check<size, 32>::has_overflow_unsigned(value))
+  gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
+ _("relocation overflow"));
+      }
       break;

     case elfcpp::R_X86_64_32S:
-      // FIXME: we need to verify that value + addend fits into 32 bits:
-      //    int64_t x = value + addend;   // note this quantity is signed!
-      //    x == static_cast<int64_t>(static_cast<int32_t>(x))
-      Relocate_functions<size, false>::rela32(view, object, psymval, addend);
+      {
+ Relocate_functions<size, false>::rela32(view, object, psymval, addend);
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
+ value = psymval->value(object, addend) + addend;
+ if (x86_64_overflow_check<size, 32>::has_overflow_signed(value))
+  gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
+ _("relocation overflow"));
+      }
       break;

     case elfcpp::R_X86_64_PC32:


--
WBR,
Andrew


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]