aboutsummaryrefslogtreecommitdiff
path: root/libunwind
diff options
context:
space:
mode:
authorAlexander Richardson <alexrichardson@google.com>2023-10-11 11:46:09 -0700
committerGitHub <noreply@github.com>2023-10-11 19:46:09 +0100
commiteb21049b4b904b072679ece60e73c6b0dc0d1ebf (patch)
tree4efef0ac88765096e6ea8f7a0ccaa415fa8b128b /libunwind
parent05181a849b4c1ec14fdd6d667285d6f5ad34a5a2 (diff)
downloadllvm-eb21049b4b904b072679ece60e73c6b0dc0d1ebf.zip
llvm-eb21049b4b904b072679ece60e73c6b0dc0d1ebf.tar.gz
llvm-eb21049b4b904b072679ece60e73c6b0dc0d1ebf.tar.bz2
[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.
Diffstat (limited to 'libunwind')
-rw-r--r--libunwind/src/EHHeaderParser.hpp13
1 files changed, 13 insertions, 0 deletions
diff --git a/libunwind/src/EHHeaderParser.hpp b/libunwind/src/EHHeaderParser.hpp
index ed4317c..0662a13 100644
--- a/libunwind/src/EHHeaderParser.hpp
+++ b/libunwind/src/EHHeaderParser.hpp
@@ -55,6 +55,19 @@ template <typename A>
bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
pint_t p = ehHdrStart;
+
+ // Ensure that we don't read data beyond the end of .eh_frame_hdr
+ if (ehHdrEnd - ehHdrStart < 4) {
+ // Don't print a message for an empty .eh_frame_hdr (this can happen if
+ // the linker script defines symbols for it even in the empty case).
+ if (ehHdrEnd == ehHdrStart)
+ return false;
+ _LIBUNWIND_LOG("unsupported .eh_frame_hdr at %" PRIx64
+ ": need at least 4 bytes of data but only got %zd",
+ static_cast<uint64_t>(ehHdrStart),
+ static_cast<size_t>(ehHdrEnd - ehHdrStart));
+ return false;
+ }
uint8_t version = addressSpace.get8(p++);
if (version != 1) {
_LIBUNWIND_LOG("unsupported .eh_frame_hdr version: %" PRIu8 " at %" PRIx64,