Skip to content

Commit 18c5648

Browse files
authored
fix: improve errors for elf decode (#2179)
1 parent 576b125 commit 18c5648

File tree

1 file changed

+30
-4
lines changed
  • crates/core/executor/src/disassembler

1 file changed

+30
-4
lines changed

crates/core/executor/src/disassembler/elf.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use elf::{
66
file::Class,
77
ElfBytes,
88
};
9+
use eyre::OptionExt;
910
use hashbrown::HashMap;
1011
use sp1_primitives::consts::{MAXIMUM_MEMORY_SIZE, WORD_SIZE};
1112

@@ -82,6 +83,11 @@ impl Elf {
8283
let mut instructions: Vec<u32> = Vec::new();
8384
let mut base_address = u32::MAX;
8485

86+
// Data about the last segment.
87+
let mut prev_segment_end_addr = None;
88+
89+
// Check that the segments are sorted and disjoint.
90+
8591
// Only read segments that are executable instructions that are also PT_LOAD.
8692
for segment in segments.iter().filter(|x| x.p_type == PT_LOAD) {
8793
// Get the file size of the segment as an u32.
@@ -102,10 +108,30 @@ impl Elf {
102108
eyre::bail!("vaddr {vaddr:08x} is unaligned");
103109
}
104110

105-
// If the virtual address is less than the first memory address, then update the first
106-
// memory address.
107-
if (segment.p_flags & PF_X) != 0 && base_address > vaddr {
108-
base_address = vaddr;
111+
// Check that the ELF structure is supported.
112+
if let Some(last_addr) = prev_segment_end_addr {
113+
eyre::ensure!(last_addr <= vaddr, "unsupported elf structure");
114+
}
115+
prev_segment_end_addr =
116+
Some(vaddr.checked_add(mem_size).ok_or_eyre("last addr overflow")?);
117+
118+
if (segment.p_flags & PF_X) != 0 {
119+
if base_address == u32::MAX {
120+
base_address = vaddr;
121+
eyre::ensure!(
122+
base_address > 0x20,
123+
"base address {base_address} should be greater than 0x20"
124+
);
125+
} else {
126+
let instr_len: u32 = WORD_SIZE
127+
.checked_mul(instructions.len())
128+
.ok_or_eyre("instructions length overflow")?
129+
.try_into()?;
130+
let last_instruction_addr = base_address
131+
.checked_add(instr_len)
132+
.ok_or_eyre("instruction addr overflow")?;
133+
eyre::ensure!(vaddr == last_instruction_addr, "unsupported elf structure");
134+
}
109135
}
110136

111137
// Get the offset to the segment.

0 commit comments

Comments
 (0)