Guard against negative symbol sizes in ELF symbol tables, which
lead to assertion failures in ML_(find_rx_mapping). Most closely
related to #304980.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12923 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h
index 96a9f28..d42fa45 100644
--- a/coregrind/m_debuginfo/priv_storage.h
+++ b/coregrind/m_debuginfo/priv_storage.h
@@ -872,8 +872,10 @@
if not found. Binary search. */
extern Word ML_(search_one_fpotab) ( struct _DebugInfo* di, Addr ptr );
-/* Helper function for the most often needed searching for an rx mapping
- containing the specified address range. */
+/* Helper function for the most often needed searching for an rx
+ mapping containing the specified address range. The range must
+ fall entirely within the mapping to be considered to be within it.
+ Asserts if lo > hi; caller must ensure this doesn't happen. */
extern struct _DebugInfoMapping* ML_(find_rx_mapping) ( struct _DebugInfo* di,
Addr lo, Addr hi );
diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c
index f978522..d78dc7a 100644
--- a/coregrind/m_debuginfo/readelf.c
+++ b/coregrind/m_debuginfo/readelf.c
@@ -236,10 +236,21 @@
*sym_name_out = sym_name;
*sym_avma_out = sym_svma; /* we will bias this shortly */
*is_text_out = True;
- *sym_size_out = (Int)sym->st_size;
*sym_tocptr_out = 0; /* unknown/inapplicable */
*from_opd_out = False;
*is_ifunc = False;
+ /* Get the symbol size, but restrict it to fit in a signed 32 bit
+ int. Also, deal with the stupid case of negative size by making
+ the size be 1. Note that sym->st_size has type UWord,
+ effectively. */
+ { Word size_tmp = (Word)sym->st_size;
+ Word max_Int = (1LL << 31) - 1;
+ if (size_tmp < 0) size_tmp = 1;
+ if (size_tmp > max_Int) size_tmp = max_Int;
+ *sym_size_out = (Int)size_tmp;
+ }
+ /* After this point refer only to *sym_size_out and not to
+ sym->st_size. */
/* Figure out if we're interested in the symbol. Firstly, is it of
the right flavour? */
@@ -251,9 +262,9 @@
&&
(ELFXX_ST_TYPE(sym->st_info) == STT_FUNC
|| ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT
-#ifdef STT_GNU_IFUNC
+# ifdef STT_GNU_IFUNC
|| ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC
-#endif
+# endif
);
/* Work out the svma and bias for each section as it will appear in
@@ -351,7 +362,7 @@
if (!plausible
&& *is_text_out
&& ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE
- && sym->st_size > 0
+ && *sym_size_out > 0
&& di->opd_present
&& di->opd_size > 0
&& *sym_avma_out >= di->opd_avma
@@ -384,7 +395,7 @@
in /system/lib/libc.so: strlen strcmp strcpy memcmp memcpy
in /system/bin/linker: __dl_strcmp __dl_strlen
*/
- if (sym->st_size == 0) {
+ if (*sym_size_out == 0) {
# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android)
*sym_size_out = 2048;
# else
@@ -556,6 +567,9 @@
background. */
Bool in_rx;
vg_assert(di->fsm.have_rx_map);
+ /* This could actually wrap around and cause
+ ML_(find_rx_mapping) to assert. But that seems so unlikely,
+ let's wait for it to happen before fixing it. */
in_rx = (ML_(find_rx_mapping)(di, *sym_avma_out,
*sym_avma_out + *sym_size_out) != NULL);
if (in_text)