Skip to content

Commit eb21049

Browse files
authored
[libunwind] Avoid reading OOB for non-existent .eh_frame_hdr (#68815)
I was running the tests with baremetal picolibc which has a linker script that __eh_frame_start==__eh_frame_end (not equal to zero) in case there is no .eh_frame_hdr. I noticed that libunwind was trying to read nonsense data because it was printing messages such as `libunwind: unsupported .eh_frame_hdr version: 20 at https://github.com/llvm/llvm-project/commit/8000d308146ebf49cb364cb600e28a0a42e22c83` This change adds a ehHdr size check to avoid reading this out-of-bounds data and potentially crashing.
1 parent 05181a8 commit eb21049

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

libunwind/src/EHHeaderParser.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,19 @@ template <typename A>
5555
bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
5656
pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
5757
pint_t p = ehHdrStart;
58+
59+
// Ensure that we don't read data beyond the end of .eh_frame_hdr
60+
if (ehHdrEnd - ehHdrStart < 4) {
61+
// Don't print a message for an empty .eh_frame_hdr (this can happen if
62+
// the linker script defines symbols for it even in the empty case).
63+
if (ehHdrEnd == ehHdrStart)
64+
return false;
65+
_LIBUNWIND_LOG("unsupported .eh_frame_hdr at %" PRIx64
66+
": need at least 4 bytes of data but only got %zd",
67+
static_cast<uint64_t>(ehHdrStart),
68+
static_cast<size_t>(ehHdrEnd - ehHdrStart));
69+
return false;
70+
}
5871
uint8_t version = addressSpace.get8(p++);
5972
if (version != 1) {
6073
_LIBUNWIND_LOG("unsupported .eh_frame_hdr version: %" PRIu8 " at %" PRIx64,

0 commit comments

Comments
 (0)