This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] PR gold/18695
- From: Andrew Senkevich <andrew dot n dot senkevich at gmail dot com>
- To: Binutils <binutils at sourceware dot org>
- Cc: "H.J. Lu" <hjl dot tools at gmail dot com>
- Date: Wed, 26 Aug 2015 16:11:04 +0300
- Subject: [PATCH] PR gold/18695
- Authentication-results: sourceware.org; auth=none
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