diff --git a/src/machine/asm/mod.rs b/src/machine/asm/mod.rs index 6e5a7237..c60eaaba 100644 --- a/src/machine/asm/mod.rs +++ b/src/machine/asm/mod.rs @@ -212,13 +212,16 @@ impl<'a> FastMemory<'a> { check_memory(self.0, addr >> RISCV_PAGE_SHIFTS); } let end = addr.wrapping_add(size); - let aligned_end = round_page_down(end); - let frame_next_start = ((end >> MEMORY_FRAME_SHIFTS) + 1) << MEMORY_FRAME_SHIFTS; - // There is some memory space between the ending address of memory to be - // written, and the end of the last memory frame touched, we will need to - // initialize the last memory frame. - if (aligned_end + RISCV_PAGESIZE as u64) < frame_next_start { - check_memory(self.0, aligned_end >> RISCV_PAGE_SHIFTS); + if end > 0 { + let aligned_end = round_page_down(end); + // Note that end is exclusive + let frame_next_start = (((end - 1) >> MEMORY_FRAME_SHIFTS) + 1) << MEMORY_FRAME_SHIFTS; + // There is some memory space between the ending address of memory to be + // written, and the end of the last memory frame touched, we will need to + // initialize the last memory frame. + if (aligned_end + RISCV_PAGESIZE as u64) < frame_next_start { + check_memory(self.0, aligned_end >> RISCV_PAGE_SHIFTS); + } } let page_indices = get_page_indices(addr, size); for page in page_indices.0..=page_indices.1 { diff --git a/tests/programs/memory_crash b/tests/programs/memory_crash new file mode 100644 index 00000000..2cfc1047 Binary files /dev/null and b/tests/programs/memory_crash differ diff --git a/tests/programs/memory_crash.md b/tests/programs/memory_crash.md new file mode 100644 index 00000000..98ecdbab --- /dev/null +++ b/tests/programs/memory_crash.md @@ -0,0 +1 @@ +This file comes from a fuzzing test. diff --git a/tests/test_asm.rs b/tests/test_asm.rs index c82544d3..3214c37d 100644 --- a/tests/test_asm.rs +++ b/tests/test_asm.rs @@ -503,3 +503,13 @@ fn test_fast_memory_initialization_bug() { machine.load_program(&buffer, &[]).unwrap(); assert_eq!(machine.machine.memory_mut().load8(&0).unwrap(), 0); } + +#[test] +pub fn test_memory_load_crash() { + let buffer = fs::read("tests/programs/memory_crash").unwrap().into(); + let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::max_value()); + let core = DefaultMachineBuilder::new(asm_core).build(); + let mut machine = AsmMachine::new(core); + let result = machine.load_program(&buffer, &vec!["memory_crash".into()]); + assert_eq!(result.unwrap_err(), Error::MemWriteOnExecutablePage); +}