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

Core trait misrepresents the lifetime of GameData #12

Open
stewbasic opened this issue Feb 5, 2020 · 0 comments
Open

Core trait misrepresents the lifetime of GameData #12

stewbasic opened this issue Feb 5, 2020 · 0 comments

Comments

@stewbasic
Copy link

A Core is able to access the GameData any time between on_load_game (when it is passed in) until on_unload_game (when it must be returned). However the data seems to be valid only for the duration of the on_load_game call (I don't know if the libretro documentation states this explicitly anywhere). Thus the trait allows use-after-free errors. Consider the following minimal example:

extern crate libretro_backend;

use libretro_backend::*;

const WIDTH: usize = 320;
const HEIGHT: usize = 240;

struct MyCore {
    video: Vec<u8>,
    game_data: Option<GameData>,
}

impl Default for MyCore {
    fn default() -> Self {
        let (video, game_data) = (vec![0x40; WIDTH * HEIGHT * 4], None);
        Self { video, game_data }
    }
}

impl MyCore {
    fn print(&self, label: &str) {
        if let Some(game_data) = &self.game_data {
            if let Some(data) = game_data.data() {
                println!("{}: {:?}", label, data);
            }
        }
    }
}

impl Core for MyCore {
    fn info() -> CoreInfo {
        CoreInfo::new("defect", "0.1").supports_roms_with_extension("txt")
    }
    fn on_load_game(&mut self, game_data: GameData) -> LoadGameResult {
        self.game_data = Some(game_data);
        self.print("on_load_game");
        let info =
            AudioVideoInfo::new().video(WIDTH as u32, HEIGHT as u32, 60.0, PixelFormat::ARGB8888);
        LoadGameResult::Success(info)
    }
    fn on_unload_game(&mut self) -> GameData {
        self.game_data.take().unwrap()
    }
    fn on_run(&mut self, handle: &mut RuntimeHandle) {
        self.print("run");
        handle.upload_video_frame(&self.video);
    }
    fn on_reset(&mut self) {}
}

libretro_core!(MyCore);

$ retroarch --version
RetroArch: Frontend for libretro -- v1.4.1 -- d8855ca --
$ echo blah > text.txt
$ retroarch -L target/release/libdefect.so text.txt 2>/dev/null
on_load_game: [98, 108, 97, 104, 10]
run: [0, 0, 0, 0, 0]
run: [0, 0, 0, 0, 0]
run: [0, 0, 0, 0, 0]
run: [0, 0, 0, 0, 0]
run: [0, 0, 0, 0, 0]

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

No branches or pull requests

1 participant