From eea6524dc8270c09029d37d7b0307a2680dac49c Mon Sep 17 00:00:00 2001 From: Saagar Jha Date: Mon, 5 Oct 2026 10:43:07 -0700 Subject: [PATCH 1/2] Add support for BinaryReader slices Slices are helpful when parsing a BinaryView that has some embedded substructure that places bounds on the parser (e.g. a section or a segment). Instead of of continually checking for these bounds it's easier to just form a slice over this region and let reads fail. --- binaryninjaapi.h | 11 +++++++++++ binaryninjacore.h | 1 + binaryreader.cpp | 11 +++++++++++ 3 files changed, 23 insertions(+) diff --git a/binaryninjaapi.h b/binaryninjaapi.h index eae5334dae..08452130d5 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -9006,6 +9006,8 @@ namespace BinaryNinja { Ref m_view; BNBinaryReader* m_stream; + BinaryReader(Ref data, BNBinaryReader* stream); + public: /*! Create a BinaryReader instance given a BinaryView and endianness. @@ -9311,6 +9313,15 @@ namespace BinaryNinja { */ bool IsEndOfFile() const; + + /*! Create a new reader that represents a bounded slice of this reader + + \param offset The start offset for the new slice + \param length The length of the new slice + + \return A new reader representing this slice + */ + BinaryReader Slice(uint64_t offset, size_t length) const; }; /*! Raised whenever a write is performed out of bounds. diff --git a/binaryninjacore.h b/binaryninjacore.h index c53f23db44..e8ca653dec 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -5649,6 +5649,7 @@ extern "C" // Stream reader object BINARYNINJACOREAPI BNBinaryReader* BNCreateBinaryReader(BNBinaryView* view); BINARYNINJACOREAPI void BNFreeBinaryReader(BNBinaryReader* stream); + BINARYNINJACOREAPI BNBinaryReader* BNSliceBinaryReader(BNBinaryReader* stream, uint64_t offset, size_t length); BINARYNINJACOREAPI BNEndianness BNGetBinaryReaderEndianness(BNBinaryReader* stream); BINARYNINJACOREAPI void BNSetBinaryReaderEndianness(BNBinaryReader* stream, BNEndianness endian); diff --git a/binaryreader.cpp b/binaryreader.cpp index 48c7394527..fa5ff849f8 100644 --- a/binaryreader.cpp +++ b/binaryreader.cpp @@ -31,6 +31,11 @@ BinaryReader::BinaryReader(BinaryView* data, BNEndianness endian) : m_view(data) } +BinaryReader::BinaryReader(Ref data, BNBinaryReader* stream) : m_view(data), m_stream(stream) +{ +} + + BinaryReader::~BinaryReader() { BNFreeBinaryReader(m_stream); @@ -443,6 +448,12 @@ bool BinaryReader::TryReadBEPointer(uint64_t& result) } +BinaryReader BinaryReader::Slice(uint64_t offset, size_t length) const +{ + return BinaryReader(m_view, BNSliceBinaryReader(m_stream, offset, length)); +} + + uint64_t BinaryReader::GetOffset() const { return BNGetReaderPosition(m_stream); From bc562771a3b34d44a0252df29414c45716801fa5 Mon Sep 17 00:00:00 2001 From: Saagar Jha Date: Mon, 5 Oct 2026 10:43:53 -0700 Subject: [PATCH 2/2] Add LEB-128 support to BinaryReader --- binaryninjaapi.h | 26 ++++++++++++++++++++++++++ binaryninjacore.h | 2 ++ binaryreader.cpp | 30 ++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 08452130d5..5c533c5cef 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -9092,6 +9092,20 @@ namespace BinaryNinja { */ uint64_t Read64(); + /*! Read a signed LEB128 from the current cursor position + + \throws ReadException + \return The read value + */ + int64_t ReadSLEB128(); + + /*! Read an unsigned LEB128 from the current cursor position + + \throws ReadException + \return The read value + */ + uint64_t ReadULEB128(); + /*! Read a pointer (size of BinaryView::GetAddressSize()) from the current cursor position and advance and advance it that many bytes @@ -9216,6 +9230,18 @@ namespace BinaryNinja { */ bool TryRead64(uint64_t& result); + /*! Try reading an unsigned LEB128 value. + + The cursor and result are unchanged on failure. + */ + bool TryReadULEB128(uint64_t& result); + + /*! Try reading a signed LEB128 value. + + The cursor and result are unchanged on failure. + */ + bool TryReadSLEB128(int64_t& result); + /*! Try reading a pointer (size of BinaryView::GetAddressSize()) \param result Reference to a uint64_t to write to diff --git a/binaryninjacore.h b/binaryninjacore.h index e8ca653dec..5f27b4057b 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -5664,6 +5664,8 @@ extern "C" BINARYNINJACOREAPI bool BNReadBE16(BNBinaryReader* stream, uint16_t* result); BINARYNINJACOREAPI bool BNReadBE32(BNBinaryReader* stream, uint32_t* result); BINARYNINJACOREAPI bool BNReadBE64(BNBinaryReader* stream, uint64_t* result); + BINARYNINJACOREAPI bool BNReadSLEB128(BNBinaryReader* stream, int64_t* result); + BINARYNINJACOREAPI bool BNReadULEB128(BNBinaryReader* stream, uint64_t* result); BINARYNINJACOREAPI bool BNReadPointer(BNBinaryView* view, BNBinaryReader* stream, uint64_t* result); BINARYNINJACOREAPI uint64_t BNGetReaderPosition(BNBinaryReader* stream); diff --git a/binaryreader.cpp b/binaryreader.cpp index fa5ff849f8..c3ac265667 100644 --- a/binaryreader.cpp +++ b/binaryreader.cpp @@ -224,6 +224,24 @@ uint64_t BinaryReader::ReadBE64() } +uint64_t BinaryReader::ReadULEB128() +{ + uint64_t result; + if (!BNReadULEB128(m_stream, &result)) + throw ReadException(); + return result; +} + + +int64_t BinaryReader::ReadSLEB128() +{ + int64_t result; + if (!BNReadSLEB128(m_stream, &result)) + throw ReadException(); + return result; +} + + uint64_t BinaryReader::ReadBEPointer() { uint64_t result; @@ -317,6 +335,18 @@ bool BinaryReader::TryRead64(uint64_t& result) } +bool BinaryReader::TryReadSLEB128(int64_t& result) +{ + return BNReadSLEB128(m_stream, &result); +} + + +bool BinaryReader::TryReadULEB128(uint64_t& result) +{ + return BNReadULEB128(m_stream, &result); +} + + bool BinaryReader::TryReadPointer(uint64_t& result) { return BNReadPointer(m_view->GetObject(), m_stream, &result);