From 758aca3189d4e599f9b13eedbf0a6cc3ae18c4cc Mon Sep 17 00:00:00 2001 From: Johannes Stoelp Date: Sat, 30 Apr 2022 11:39:25 +0200 Subject: add TypeConversion error and contains method on LoadSegment to check if addr is contained in segment --- src/lib.rs | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index df4a7e3..ef2535d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,8 @@ pub enum Error { OutOfBytes, /// Const generic on `Elf` is too small to hold all `LOAD` from the ELF file. OutOfLoadSegments, + /// Failed to convert between data types internally. + TypeConversion(&'static str), /// Unknown value in `e_ident:EI_CLASS` byte. UnknownBitness(u8), /// Unknown value in `e_ident:EI_DATA` byte. @@ -185,12 +187,20 @@ impl<'bytes> ElfReader<'bytes> { pub struct LoadSegment<'bytes> { pub vaddr: u64, pub bytes: &'bytes [u8], - pub zero_pad: usize, + pub zero_pad: u64, pub x: bool, pub w: bool, pub r: bool, } +impl LoadSegment<'_> { + #[inline] + pub fn contains(&self, addr: u64) -> bool { + let len = u64::try_from(self.bytes.len()).expect("segment byte len exceeds u64"); + self.vaddr <= addr && addr < (self.vaddr + len + self.zero_pad) + } +} + #[derive(Debug)] pub struct Elf<'bytes, const N: usize> { machine: Machine, @@ -244,14 +254,17 @@ impl Elf<'_, N> { const PF_W: u32 = 1 << 1; const PF_R: u32 = 1 << 2; - let phoff = usize::try_from(phoff).expect("phoff too large!"); + let phoff = usize::try_from(phoff) + .map_err(|_| Error::TypeConversion("phoff does not fit into usize"))?; for ph in 0..phnum { let off = ph .checked_mul(phentsize) .map(usize::from) - .expect("phdr offset overflowed"); - let pos = phoff.checked_add(off).expect("phdr position overflowed"); + .ok_or(Error::TypeConversion("phdr offset does not fit into usize"))?; + let pos = phoff.checked_add(off).ok_or(Error::TypeConversion( + "phdr position does not fit into usize", + ))?; r.set_pos(pos); // We only care about load segments. @@ -276,15 +289,16 @@ impl Elf<'_, N> { } let _align = r.read_native(en, bit)?; - let offset = usize::try_from(offset).expect("file offset too large"); - let filesz = usize::try_from(filesz).expect("file size too large"); - let memsz = usize::try_from(memsz).expect("mem size too large"); + let data_off = usize::try_from(offset) + .map_err(|_| Error::TypeConversion("file offset does not fit into usize"))?; + let data_len = usize::try_from(filesz) + .map_err(|_| Error::TypeConversion("file size does not fit into usize"))?; // Seek to start of PT_LOAD segment bytes. - r.set_pos(offset); + r.set_pos(data_off); // Get slice of PT_LOAD segment bytes. - let bytes = r.read_slice(filesz)?; + let bytes = r.read_slice(data_len)?; let x = (flags & PF_X) != 0; let w = (flags & PF_W) != 0; let r = (flags & PF_R) != 0; -- cgit v1.2.3