Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RISC-V64 incorrectly returns error when calling emu_start with count = 1 at end of page #1931

Open
jxors opened this issue Mar 19, 2024 · 0 comments

Comments

@jxors
Copy link

jxors commented Mar 19, 2024

When executing a single instruction at the end of a page with the following page unmapped, unicorn will return a memory error (FETCH_UNMAPPED) instead of stopping.

This can be reproduced with:

// Cargo.toml
[package]
name = "minimal-unicorn-test"
version = "0.1.0"
edition = "2021"

[dependencies]
unicorn-engine = "2.0.1"

// src/main.rs
use unicorn_engine::{unicorn_const::{Arch, Mode, Permission}, RegisterRISCV, Unicorn};

fn main() {
    let mut unicorn = Unicorn::new_with_data(Arch::RISCV, Mode::RISCV64, false)
        .expect("failed to initialize Unicorn instance");

    check(&mut unicorn, 0x6D76D7473FF0);
    check(&mut unicorn, 0x6D76D7473FFC);
}

fn check(unicorn: &mut Unicorn<'_, bool>, addr: u64) {
    unicorn.mem_map(addr & !0xfff, 4096, Permission::EXEC).unwrap();
    unicorn.mem_write(addr, &[ 0x13, 0x81, 0x00, 0x7d ]).unwrap();
    
    unicorn.reg_write(RegisterRISCV::PC, addr).unwrap();
    unicorn.reg_write(RegisterRISCV::X1, 0x1234).unwrap();
    let execution_result = unicorn.emu_start(addr, addr + 4, 0, 1);
    assert_eq!(unicorn.reg_read(RegisterRISCV::PC), Ok(addr + 4));
    assert_eq!(unicorn.reg_read(RegisterRISCV::X2), Ok(0x1234 + 2000));
    assert_eq!(execution_result, Ok(()));

    unicorn.mem_unmap(addr & !0xfff, 4096).unwrap();

    println!("Execution at 0x{addr:X} OK");
}

Note how emu_start is called with count as 1.

The first call to check places the instruction 16 bytes from the end of the page. This is successfully executed. The second call to check places the instruction exactly at the page edge. This fails with an error, but the resulting unicorn state is correct. Unicorn should return Ok(()) here instead of an error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants