From f18d4c5eec540fcd45094a60aa60887b07c65abf Mon Sep 17 00:00:00 2001 From: Dmitri Makarov Date: Fri, 21 May 2021 20:25:43 +0200 Subject: [PATCH] Cherry pick v0.2 branch and release v0.2.10 off main (#171) --- Cargo.lock | 4 +-- Cargo.toml | 2 +- README.md | 2 +- cli/Cargo.lock | 6 ++-- cli/Cargo.toml | 2 +- src/aligned_memory.rs | 83 ++++++++++++++++++++++++++----------------- src/call_frames.rs | 3 +- src/elf.rs | 6 ++-- test_utils/Cargo.lock | 4 +-- test_utils/Cargo.toml | 2 +- 10 files changed, 66 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a032e6ca..11bf408a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -219,7 +219,7 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.2.8" +version = "0.2.10" dependencies = [ "byteorder 1.2.7", "combine", @@ -250,7 +250,7 @@ dependencies = [ [[package]] name = "test_utils" -version = "0.2.8" +version = "0.2.10" dependencies = [ "libc", "solana_rbpf", diff --git a/Cargo.toml b/Cargo.toml index 1d577470..059fdde2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "solana_rbpf" -version = "0.2.8" +version = "0.2.10" description = "Virtual machine and JIT compiler for eBPF programs" authors = ["Solana Maintainers "] repository = "https://github.com/solana-labs/rbpf" diff --git a/README.md b/README.md index 739ccc10..7c0f04d4 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ so it should work out of the box by adding it as a dependency in your ```toml [dependencies] -solana_rbpf = "0.2.8" +solana_rbpf = "0.2.10" ``` You can also use the development version from this GitHub repository. This diff --git a/cli/Cargo.lock b/cli/Cargo.lock index 5c203a18..ea39151f 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -297,7 +297,7 @@ dependencies = [ [[package]] name = "rbpf_cli" -version = "0.2.8" +version = "0.2.10" dependencies = [ "clap", "solana_rbpf", @@ -332,7 +332,7 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.2.8" +version = "0.2.10" dependencies = [ "byteorder", "combine", @@ -375,7 +375,7 @@ dependencies = [ [[package]] name = "test_utils" -version = "0.2.8" +version = "0.2.10" dependencies = [ "libc", "solana_rbpf", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index f1f8165a..c9384223 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rbpf_cli" -version = "0.2.8" +version = "0.2.10" description = "CLI to test and analyze eBPF programs" authors = ["Solana Maintainers "] repository = "https://github.com/solana-labs/rbpf" diff --git a/src/aligned_memory.rs b/src/aligned_memory.rs index b801425e..e11d09d5 100644 --- a/src/aligned_memory.rs +++ b/src/aligned_memory.rs @@ -3,70 +3,93 @@ /// Provides u8 slices at a specified alignment #[derive(Clone, Debug, PartialEq)] pub struct AlignedMemory { - len: usize, + max_len: usize, align_offset: usize, - write_index: usize, mem: Vec, } impl AlignedMemory { - /// Return a new AlignedMem type - pub fn new(len: usize, align: usize) -> Self { - let mem = vec![0u8; len + align]; + fn get_mem(max_len: usize, align: usize) -> (Vec, usize) { + let mut mem: Vec = Vec::with_capacity(max_len + align); + mem.push(0); let align_offset = mem.as_ptr().align_offset(align); + mem.resize(align_offset, 0); + (mem, align_offset) + } + /// Return a new AlignedMemory type + pub fn new(max_len: usize, align: usize) -> Self { + let (mem, align_offset) = Self::get_mem(max_len, align); + Self { + max_len, + align_offset, + mem, + } + } + /// Return a pre-filled AlignedMemory type + pub fn new_with_size(len: usize, align: usize) -> Self { + let (mut mem, align_offset) = Self::get_mem(len, align); + mem.resize(align_offset + len, 0); Self { - len, + max_len: len, + align_offset, + mem, + } + } + /// Return a pre-filled AlignedMemory type + pub fn new_with_data(data: &[u8], align: usize) -> Self { + let max_len = data.len(); + let (mut mem, align_offset) = Self::get_mem(max_len, align); + mem.extend_from_slice(data); + Self { + max_len, align_offset, mem, - write_index: align_offset, } } /// Get the length of the data pub fn len(&self) -> usize { - self.len + self.mem.len() - self.align_offset } /// Is the memory empty pub fn is_empty(&self) -> bool { - self.len == 0 + self.mem.len() - self.align_offset == 0 } /// Get the current write index pub fn write_index(&self) -> usize { - self.write_index + self.mem.len() } /// Get an aligned slice pub fn as_slice(&self) -> &[u8] { - &self.mem[self.align_offset..self.align_offset + self.len] + let start = self.align_offset; + let end = self.mem.len(); + &self.mem[start..end] } /// Get an aligned mutable slice pub fn as_slice_mut(&mut self) -> &mut [u8] { - &mut self.mem[self.align_offset..self.align_offset + self.len] + let start = self.align_offset; + let end = self.mem.len(); + &mut self.mem[start..end] } - /// Fill memory with value starting at the write_index - pub fn fill(&mut self, num: usize, value: u8) -> std::io::Result<()> { - if self.write_index + num > self.align_offset + self.len() { + /// resize memory with value starting at the write_index + pub fn resize(&mut self, num: usize, value: u8) -> std::io::Result<()> { + if self.mem.len() + num > self.align_offset + self.max_len { return Err(std::io::Error::new( std::io::ErrorKind::InvalidInput, - "aligned memory fill failed", + "aligned memory resize failed", )); } - if value != 0 { - for i in 0..num { - self.mem[self.write_index + i] = value; - } - } - self.write_index += num; + self.mem.resize(self.mem.len() + num, value); Ok(()) } } impl std::io::Write for AlignedMemory { fn write(&mut self, buf: &[u8]) -> std::io::Result { - if self.write_index + buf.len() > self.align_offset + self.len() { + if self.mem.len() + buf.len() > self.align_offset + self.max_len { return Err(std::io::Error::new( std::io::ErrorKind::InvalidInput, "aligned memory write failed", )); } - self.mem[self.write_index..self.write_index + buf.len()].copy_from_slice(buf); - self.write_index += buf.len(); + self.mem.extend_from_slice(buf); Ok(buf.len()) } fn flush(&mut self) -> std::io::Result<()> { @@ -81,10 +104,6 @@ mod tests { fn do_test(align: usize) { let mut aligned_memory = AlignedMemory::new(10, align); - assert!(!aligned_memory.is_empty()); - assert_eq!(aligned_memory.len(), 10); - assert_eq!(aligned_memory.as_slice().len(), 10); - assert_eq!(aligned_memory.as_slice_mut().len(), 10); assert_eq!(aligned_memory.write(&[42u8; 1]).unwrap(), 1); assert_eq!(aligned_memory.write(&[42u8; 9]).unwrap(), 9); @@ -97,11 +116,11 @@ mod tests { assert_eq!(aligned_memory.as_slice(), &[84u8; 10]); let mut aligned_memory = AlignedMemory::new(10, align); - aligned_memory.fill(5, 0).unwrap(); - aligned_memory.fill(2, 1).unwrap(); + aligned_memory.resize(5, 0).unwrap(); + aligned_memory.resize(2, 1).unwrap(); assert_eq!(aligned_memory.write(&[2u8; 3]).unwrap(), 3); assert_eq!(aligned_memory.as_slice(), &[0, 0, 0, 0, 0, 1, 1, 2, 2, 2]); - aligned_memory.fill(1, 3).unwrap_err(); + aligned_memory.resize(1, 3).unwrap_err(); aligned_memory.write(&[4u8; 1]).unwrap_err(); assert_eq!(aligned_memory.as_slice(), &[0, 0, 0, 0, 0, 1, 1, 2, 2, 2]); } diff --git a/src/call_frames.rs b/src/call_frames.rs index adb704ff..69b35189 100644 --- a/src/call_frames.rs +++ b/src/call_frames.rs @@ -29,7 +29,8 @@ pub struct CallFrames { impl CallFrames { /// New call frame, depth indicates maximum call depth pub fn new(depth: usize, frame_size: usize) -> Self { - let stack = AlignedMemory::new(depth * frame_size, HOST_ALIGN); + let mut stack = AlignedMemory::new(depth * frame_size, HOST_ALIGN); + stack.resize(depth * frame_size, 0).unwrap(); let region = MemoryRegion::new_from_slice(stack.as_slice(), MM_STACK_START, frame_size as u64, true); let mut frames = CallFrames { diff --git a/src/elf.rs b/src/elf.rs index 2e3575e4..9c8fe38a 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -345,8 +345,7 @@ impl<'a, E: UserDefinedError, I: InstructionMeter> EBpfElf { text_bytes: &[u8], bpf_functions: BTreeMap, ) -> Self { - let mut elf_bytes = AlignedMemory::new(text_bytes.len(), ebpf::HOST_ALIGN); - elf_bytes.as_slice_mut().copy_from_slice(text_bytes); + let elf_bytes = AlignedMemory::new_with_data(text_bytes, ebpf::HOST_ALIGN); Self { config, elf_bytes, @@ -368,8 +367,7 @@ impl<'a, E: UserDefinedError, I: InstructionMeter> EBpfElf { /// Fully loads an ELF, including validation and relocation pub fn load(config: Config, bytes: &[u8]) -> Result { let elf = Elf::parse(bytes)?; - let mut elf_bytes = AlignedMemory::new(bytes.len(), ebpf::HOST_ALIGN); - elf_bytes.as_slice_mut().copy_from_slice(bytes); + let mut elf_bytes = AlignedMemory::new_with_data(bytes, ebpf::HOST_ALIGN); Self::validate(&elf, &elf_bytes.as_slice())?; diff --git a/test_utils/Cargo.lock b/test_utils/Cargo.lock index 66117937..efefb602 100644 --- a/test_utils/Cargo.lock +++ b/test_utils/Cargo.lock @@ -198,7 +198,7 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.2.8" +version = "0.2.10" dependencies = [ "byteorder", "combine", @@ -226,7 +226,7 @@ dependencies = [ [[package]] name = "test_utils" -version = "0.2.8" +version = "0.2.10" dependencies = [ "libc", "solana_rbpf", diff --git a/test_utils/Cargo.toml b/test_utils/Cargo.toml index e49ff5fc..0503e765 100644 --- a/test_utils/Cargo.toml +++ b/test_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_utils" -version = "0.2.8" +version = "0.2.10" authors = ["Solana Maintainers "] edition = "2018" publish = false