summaryrefslogtreecommitdiffstats
path: root/libdw/memory-access.h
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2014-12-14 21:48:23 +0100
committerMark Wielaard <[email protected]>2014-12-17 16:35:56 +0100
commit7a053473c7bedd22e3db39c444a4cd8f97eace25 (patch)
treef98e9e7def17ec051170aaf663419628d84fae78 /libdw/memory-access.h
parent9202665816763fad8524dd78a664dbcaa157b8d4 (diff)
libdw: Add get_uleb128 and get_sleb128 bounds checking.
Both get_uleb128 and get_sleb128 now take an end pointer to prevent reading too much data. Adjust all callers to provide the end pointer. There are still two exceptions. "Raw" dwarf_getabbrevattr and read_encoded_valued don't have a end pointer associated yet. They will have to be provided in the future. Signed-off-by: Mark Wielaard <[email protected]>
Diffstat (limited to 'libdw/memory-access.h')
-rw-r--r--libdw/memory-access.h13
1 files changed, 7 insertions, 6 deletions
diff --git a/libdw/memory-access.h b/libdw/memory-access.h
index 6a4ce885..8226d00e 100644
--- a/libdw/memory-access.h
+++ b/libdw/memory-access.h
@@ -48,20 +48,21 @@
} while (0)
static inline uint64_t
-__libdw_get_uleb128 (const unsigned char **addrp)
+__libdw_get_uleb128 (const unsigned char **addrp, const unsigned char *end)
{
uint64_t acc = 0;
/* Unroll the first step to help the compiler optimize
for the common single-byte case. */
get_uleb128_step (acc, *addrp, 0);
- for (unsigned int i = 1; i < len_leb128 (acc); ++i)
+ for (unsigned int i = 1; i < len_leb128 (acc) && *addrp < end; ++i)
get_uleb128_step (acc, *addrp, i);
/* Other implementations set VALUE to UINT_MAX in this
case. So we better do this as well. */
return UINT64_MAX;
}
-#define get_uleb128(var, addr) ((var) = __libdw_get_uleb128 (&(addr)))
+/* Note, addr needs to me smaller than end. */
+#define get_uleb128(var, addr, end) ((var) = __libdw_get_uleb128 (&(addr), end))
/* The signed case is similar, but we sign-extend the result. */
@@ -78,18 +79,18 @@ __libdw_get_uleb128 (const unsigned char **addrp)
} while (0)
static inline int64_t
-__libdw_get_sleb128 (const unsigned char **addrp)
+__libdw_get_sleb128 (const unsigned char **addrp, const unsigned char *end)
{
int64_t acc = 0;
/* Unrolling 0 like uleb128 didn't prove to benefit optimization. */
- for (unsigned int i = 0; i < len_leb128 (acc); ++i)
+ for (unsigned int i = 0; i < len_leb128 (acc) && *addrp < end; ++i)
get_sleb128_step (acc, *addrp, i);
/* Other implementations set VALUE to INT_MAX in this
case. So we better do this as well. */
return INT64_MAX;
}
-#define get_sleb128(var, addr) ((var) = __libdw_get_sleb128 (&(addr)))
+#define get_sleb128(var, addr, end) ((var) = __libdw_get_sleb128 (&(addr), end))
/* We use simple memory access functions in case the hardware allows it.